[BACK]Return to i2s.c CVS log [TXT][DIR] Up to [local] / sys / arch / macppc / dev

Annotation of sys/arch/macppc/dev/i2s.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: i2s.c,v 1.8 2007/04/22 22:31:14 deraadt Exp $ */
                      2: /*     $NetBSD: i2s.c,v 1.1 2003/12/27 02:19:34 grant Exp $    */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2002 Tsubai Masanari.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the author may not be used to endorse or promote products
                     16:  *    derived from this software without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     27:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     28:  */
                     29:
                     30: #include <sys/param.h>
                     31: #include <sys/audioio.h>
                     32: #include <sys/device.h>
                     33: #include <sys/malloc.h>
                     34: #include <sys/systm.h>
                     35:
                     36: #include <dev/auconv.h>
                     37: #include <dev/audio_if.h>
                     38: #include <dev/mulaw.h>
                     39: #include <dev/ofw/openfirm.h>
                     40: #include <macppc/dev/dbdma.h>
                     41:
                     42: #include <uvm/uvm_extern.h>
                     43:
                     44: #include <machine/autoconf.h>
                     45: #include <machine/pio.h>
                     46:
                     47: #include <macppc/dev/i2svar.h>
                     48: #include <macppc/dev/i2sreg.h>
                     49:
                     50: #ifdef I2S_DEBUG
                     51: # define DPRINTF(x) printf x
                     52: #else
                     53: # define DPRINTF(x)
                     54: #endif
                     55:
                     56: struct i2s_mode *i2s_find_mode(u_int, u_int, u_int);
                     57: void i2s_cs16mts(void *, u_char *, int);
                     58:
                     59: static int gpio_read(char *);
                     60: static void gpio_write(char *, int);
                     61: void i2s_mute_speaker(struct i2s_softc *, int);
                     62: void i2s_mute_headphone(struct i2s_softc *, int);
                     63: void i2s_mute_lineout(struct i2s_softc *, int);
                     64: int i2s_cint(void *);
                     65: u_char *i2s_gpio_map(struct i2s_softc *, char *, int *);
                     66: void i2s_init(struct i2s_softc *, int);
                     67:
                     68: static void mono16_to_stereo16(void *, u_char *, int);
                     69: static void swap_bytes_mono16_to_stereo16(void *, u_char *, int);
                     70:
                     71: /* XXX */
                     72: void keylargo_fcr_enable(int, u_int32_t);
                     73: void keylargo_fcr_disable(int, u_int32_t);
                     74:
                     75: struct cfdriver i2s_cd = {
                     76:        NULL, "i2s", DV_DULL
                     77: };
                     78:
                     79: static u_char *amp_mute;
                     80: static u_char *headphone_mute;
                     81: static u_char *lineout_mute;
                     82: static u_char *audio_hw_reset;
                     83: static u_char *headphone_detect;
                     84: static int headphone_detect_active;
                     85: static u_char *lineout_detect;
                     86: static int lineout_detect_active;
                     87:
                     88: /* GPIO bits */
                     89: #define GPIO_OUTSEL    0xf0    /* Output select */
                     90:                /*      0x00    GPIO bit0 is output
                     91:                        0x10    media-bay power
                     92:                        0x20    reserved
                     93:                        0x30    MPIC */
                     94:
                     95: #define GPIO_ALTOE     0x08    /* Alternate output enable */
                     96:                /*      0x00    Use DDR
                     97:                        0x08    Use output select */
                     98:
                     99: #define GPIO_DDR       0x04    /* Data direction */
                    100: #define GPIO_DDR_OUTPUT        0x04    /* Output */
                    101: #define GPIO_DDR_INPUT 0x00    /* Input */
                    102:
                    103: #define GPIO_LEVEL     0x02    /* Pin level (RO) */
                    104:
                    105: #define        GPIO_DATA       0x01    /* Data */
                    106:
                    107: void
                    108: i2s_attach(struct device *parent, struct i2s_softc *sc, struct confargs *ca)
                    109: {
                    110:        int cirq, oirq, iirq, cirq_type, oirq_type, iirq_type;
                    111:        u_int32_t reg[6], intr[6];
                    112:
                    113:        sc->sc_node = OF_child(ca->ca_node);
                    114:        sc->sc_baseaddr = ca->ca_baseaddr;
                    115:
                    116:        OF_getprop(sc->sc_node, "reg", reg, sizeof reg);
                    117:        reg[0] += sc->sc_baseaddr;
                    118:        reg[2] += sc->sc_baseaddr;
                    119:        reg[4] += sc->sc_baseaddr;
                    120:
                    121:        sc->sc_reg = mapiodev(reg[0], reg[1]);
                    122:
                    123:        sc->sc_dmat = ca->ca_dmat;
                    124:        sc->sc_odma = mapiodev(reg[2], reg[3]); /* out */
                    125:        sc->sc_idma = mapiodev(reg[4], reg[5]); /* in */
                    126:        sc->sc_odbdma = dbdma_alloc(sc->sc_dmat, I2S_DMALIST_MAX);
                    127:        sc->sc_odmacmd = sc->sc_odbdma->d_addr;
                    128:        sc->sc_idbdma = dbdma_alloc(sc->sc_dmat, I2S_DMALIST_MAX);
                    129:        sc->sc_idmacmd = sc->sc_idbdma->d_addr;
                    130:
                    131:        OF_getprop(sc->sc_node, "interrupts", intr, sizeof intr);
                    132:        cirq = intr[0];
                    133:        oirq = intr[2];
                    134:        iirq = intr[4];
                    135:        cirq_type = intr[1] ? IST_LEVEL : IST_EDGE;
                    136:        oirq_type = intr[3] ? IST_LEVEL : IST_EDGE;
                    137:        iirq_type = intr[5] ? IST_LEVEL : IST_EDGE;
                    138:
                    139:        /* intr_establish(cirq, cirq_type, IPL_AUDIO, i2s_intr, sc); */
                    140:        mac_intr_establish(parent, oirq, oirq_type, IPL_AUDIO, i2s_intr,
                    141:            sc, sc->sc_dev.dv_xname);
                    142:        /* intr_establish(iirq, iirq_type, IPL_AUDIO, i2s_intr, sc); */
                    143:
                    144:        printf(": irq %d,%d,%d\n", cirq, oirq, iirq);
                    145:
                    146:        i2s_set_rate(sc, 44100);
                    147:        i2s_gpio_init(sc, ca->ca_node, parent);
                    148: }
                    149:
                    150: int
                    151: i2s_intr(v)
                    152:        void *v;
                    153: {
                    154:        struct i2s_softc *sc = v;
                    155:        struct dbdma_command *cmd = sc->sc_odmap;
                    156:        u_int16_t c, status;
                    157:
                    158:        /* if not set we are not running */
                    159:        if (!cmd)
                    160:                return (0);
                    161:        DPRINTF(("i2s_intr: cmd %x\n", cmd));
                    162:
                    163:        c = in16rb(&cmd->d_command);
                    164:        status = in16rb(&cmd->d_status);
                    165:
                    166:        if (c >> 12 == DBDMA_CMD_OUT_LAST)
                    167:                sc->sc_odmap = sc->sc_odmacmd;
                    168:        else
                    169:                sc->sc_odmap++;
                    170:
                    171:        if (c & (DBDMA_INT_ALWAYS << 4)) {
                    172:                cmd->d_status = 0;
                    173:                if (status)     /* status == 0x8400 */
                    174:                        if (sc->sc_ointr)
                    175:                                (*sc->sc_ointr)(sc->sc_oarg);
                    176:        }
                    177:
                    178:        return 1;
                    179: }
                    180:
                    181: int
                    182: i2s_open(h, flags)
                    183:        void *h;
                    184:        int flags;
                    185: {
                    186:        return 0;
                    187: }
                    188:
                    189: /*
                    190:  * Close function is called at splaudio().
                    191:  */
                    192: void
                    193: i2s_close(h)
                    194:        void *h;
                    195: {
                    196:        struct i2s_softc *sc = h;
                    197:
                    198:        i2s_halt_output(sc);
                    199:        i2s_halt_input(sc);
                    200:
                    201:        sc->sc_ointr = 0;
                    202:        sc->sc_iintr = 0;
                    203: }
                    204:
                    205: int
                    206: i2s_query_encoding(h, ae)
                    207:        void *h;
                    208:        struct audio_encoding *ae;
                    209: {
                    210:        int err = 0;
                    211:
                    212:        switch (ae->index) {
                    213:        case 0:
                    214:                strlcpy(ae->name, AudioEslinear, sizeof(ae->name));
                    215:                ae->encoding = AUDIO_ENCODING_SLINEAR;
                    216:                ae->precision = 16;
                    217:                ae->flags = 0;
                    218:                break;
                    219:        case 1:
                    220:                strlcpy(ae->name, AudioEslinear_be, sizeof(ae->name));
                    221:                ae->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    222:                ae->precision = 16;
                    223:                ae->flags = 0;
                    224:                break;
                    225:        case 2:
                    226:                strlcpy(ae->name, AudioEslinear_le, sizeof(ae->name));
                    227:                ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    228:                ae->precision = 16;
                    229:                ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    230:                break;
                    231:        case 3:
                    232:                strlcpy(ae->name, AudioEulinear_be, sizeof(ae->name));
                    233:                ae->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    234:                ae->precision = 16;
                    235:                ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    236:                break;
                    237:        case 4:
                    238:                strlcpy(ae->name, AudioEulinear_le, sizeof(ae->name));
                    239:                ae->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    240:                ae->precision = 16;
                    241:                ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    242:                break;
                    243:        case 5:
                    244:                strlcpy(ae->name, AudioEmulaw, sizeof(ae->name));
                    245:                ae->encoding = AUDIO_ENCODING_ULAW;
                    246:                ae->precision = 8;
                    247:                ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    248:                break;
                    249:        case 6:
                    250:                strlcpy(ae->name, AudioEalaw, sizeof(ae->name));
                    251:                ae->encoding = AUDIO_ENCODING_ALAW;
                    252:                ae->precision = 8;
                    253:                ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    254:                break;
                    255:        case 7:
                    256:                strlcpy(ae->name, AudioEslinear, sizeof(ae->name));
                    257:                ae->encoding = AUDIO_ENCODING_SLINEAR;
                    258:                ae->precision = 8;
                    259:                ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    260:                break;
                    261:        case 8:
                    262:                strlcpy(ae->name, AudioEulinear, sizeof(ae->name));
                    263:                ae->encoding = AUDIO_ENCODING_ULINEAR;
                    264:                ae->precision = 8;
                    265:                ae->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    266:                break;
                    267:        default:
                    268:                err = EINVAL;
                    269:                break;
                    270:        }
                    271:        return (err);
                    272: }
                    273:
                    274: static void
                    275: mono16_to_stereo16(v, p, cc)
                    276:        void *v;
                    277:        u_char *p;
                    278:        int cc;
                    279: {
                    280:        int x;
                    281:        int16_t *src, *dst;
                    282:
                    283:        src = (void *)(p + cc);
                    284:        dst = (void *)(p + cc * 2);
                    285:        while (cc > 0) {
                    286:                x = *--src;
                    287:                *--dst = x;
                    288:                *--dst = x;
                    289:                cc -= 2;
                    290:        }
                    291: }
                    292:
                    293: static void
                    294: swap_bytes_mono16_to_stereo16(v, p, cc)
                    295:        void *v;
                    296:        u_char *p;
                    297:        int cc;
                    298: {
                    299:        swap_bytes(v, p, cc);
                    300:        mono16_to_stereo16(v, p, cc);
                    301: }
                    302:
                    303: void
                    304: i2s_cs16mts(void *v, u_char *p, int cc)
                    305: {
                    306:        mono16_to_stereo16(v, p, cc);
                    307:        change_sign16_be(v, p, cc * 2);
                    308: }
                    309:
                    310: struct i2s_mode {
                    311:        u_int encoding;
                    312:        u_int precision;
                    313:        u_int channels;
                    314:        void (*sw_code)(void *, u_char *, int);
                    315:        int factor;
                    316: } i2s_modes[] = {
                    317:        { AUDIO_ENCODING_SLINEAR_LE,  8, 1, linear8_to_linear16_be_mts, 4 },
                    318:        { AUDIO_ENCODING_SLINEAR_LE,  8, 2, linear8_to_linear16_be, 2 },
                    319:        { AUDIO_ENCODING_SLINEAR_LE, 16, 1, swap_bytes_mono16_to_stereo16, 2 },
                    320:        { AUDIO_ENCODING_SLINEAR_LE, 16, 2, swap_bytes, 1 },
                    321:        { AUDIO_ENCODING_SLINEAR_BE,  8, 1, linear8_to_linear16_be_mts, 4 },
                    322:        { AUDIO_ENCODING_SLINEAR_BE,  8, 2, linear8_to_linear16_be, 2 },
                    323:        { AUDIO_ENCODING_SLINEAR_BE, 16, 1, mono16_to_stereo16, 2 },
                    324:        { AUDIO_ENCODING_SLINEAR_BE, 16, 2, NULL, 1 },
                    325:        { AUDIO_ENCODING_ULINEAR_LE,  8, 1, ulinear8_to_linear16_be_mts, 4 },
                    326:        { AUDIO_ENCODING_ULINEAR_LE,  8, 2, ulinear8_to_linear16_be, 2 },
                    327:        { AUDIO_ENCODING_ULINEAR_LE, 16, 1, change_sign16_swap_bytes_le_mts, 2 },
                    328:        { AUDIO_ENCODING_ULINEAR_LE, 16, 2, swap_bytes_change_sign16_be, 1 },
                    329:        { AUDIO_ENCODING_ULINEAR_BE,  8, 1, ulinear8_to_linear16_be_mts, 4 },
                    330:        { AUDIO_ENCODING_ULINEAR_BE,  8, 2, ulinear8_to_linear16_be, 2 },
                    331:        { AUDIO_ENCODING_ULINEAR_BE, 16, 1, i2s_cs16mts, 2 },
                    332:        { AUDIO_ENCODING_ULINEAR_BE, 16, 2, change_sign16_be, 1 }
                    333: };
                    334:
                    335:
                    336: struct i2s_mode *
                    337: i2s_find_mode(u_int encoding, u_int precision, u_int channels)
                    338: {
                    339:        struct i2s_mode *m;
                    340:        int i;
                    341:
                    342:        for (i = 0; i < sizeof(i2s_modes)/sizeof(i2s_modes[0]); i++) {
                    343:                m = &i2s_modes[i];
                    344:                if (m->encoding == encoding &&
                    345:                    m->precision == precision &&
                    346:                    m->channels == channels)
                    347:                        return (m);
                    348:        }
                    349:        return (NULL);
                    350: }
                    351:
                    352: int
                    353: i2s_set_params(h, setmode, usemode, play, rec)
                    354:        void *h;
                    355:        int setmode, usemode;
                    356:        struct audio_params *play, *rec;
                    357: {
                    358:        struct i2s_mode *m;
                    359:        struct i2s_softc *sc = h;
                    360:        struct audio_params *p;
                    361:        int mode;
                    362:
                    363:        p = play; /* default to play */
                    364:
                    365:        /*
                    366:         * This device only has one clock, so make the sample rates match.
                    367:         */
                    368:        if (play->sample_rate != rec->sample_rate &&
                    369:            usemode == (AUMODE_PLAY | AUMODE_RECORD)) {
                    370:                if (setmode == AUMODE_PLAY) {
                    371:                        rec->sample_rate = play->sample_rate;
                    372:                        setmode |= AUMODE_RECORD;
                    373:                } else if (setmode == AUMODE_RECORD) {
                    374:                        play->sample_rate = rec->sample_rate;
                    375:                        setmode |= AUMODE_PLAY;
                    376:                } else
                    377:                        return EINVAL;
                    378:        }
                    379:
                    380:        for (mode = AUMODE_RECORD; mode != -1;
                    381:             mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) {
                    382:                if ((setmode & mode) == 0)
                    383:                        continue;
                    384:
                    385:                p = mode == AUMODE_PLAY ? play : rec;
                    386:
                    387:                if (p->sample_rate < 4000 || p->sample_rate > 50000 ||
                    388:                    (p->precision != 8 && p->precision != 16) ||
                    389:                    (p->channels != 1 && p->channels != 2))
                    390:                        return EINVAL;
                    391:
                    392:                switch (p->encoding) {
                    393:                case AUDIO_ENCODING_SLINEAR_LE:
                    394:                case AUDIO_ENCODING_SLINEAR_BE:
                    395:                case AUDIO_ENCODING_ULINEAR_LE:
                    396:                case AUDIO_ENCODING_ULINEAR_BE:
                    397:                        m = i2s_find_mode(p->encoding, p->precision,
                    398:                            p->channels);
                    399:                        if (m == NULL) {
                    400:                                printf("mode not found: %u/%u/%u\n",
                    401:                                    p->encoding, p->precision, p->channels);
                    402:                                return (EINVAL);
                    403:                        }
                    404:                        p->factor = m->factor;
                    405:                        p->sw_code = m->sw_code;
                    406:                        break;
                    407:
                    408:                case AUDIO_ENCODING_ULAW:
                    409:                        if (mode == AUMODE_PLAY) {
                    410:                                if (p->channels == 1) {
                    411:                                        p->factor = 4;
                    412:                                        p->sw_code = mulaw_to_slinear16_be_mts;
                    413:                                        break;
                    414:                                }
                    415:                                if (p->channels == 2) {
                    416:                                        p->factor = 2;
                    417:                                        p->sw_code = mulaw_to_slinear16_be;
                    418:                                        break;
                    419:                                }
                    420:                        } else
                    421:                                break; /* XXX */
                    422:                        return (EINVAL);
                    423:
                    424:                case AUDIO_ENCODING_ALAW:
                    425:                        if (mode == AUMODE_PLAY) {
                    426:                                if (p->channels == 1) {
                    427:                                        p->factor = 4;
                    428:                                        p->sw_code = alaw_to_slinear16_be_mts;
                    429:                                        break;
                    430:                                }
                    431:                                if (p->channels == 2) {
                    432:                                        p->factor = 2;
                    433:                                        p->sw_code = alaw_to_slinear16_be;
                    434:                                        break;
                    435:                                }
                    436:                        } else
                    437:                                break; /* XXX */
                    438:                        return (EINVAL);
                    439:
                    440:                default:
                    441:                        return (EINVAL);
                    442:                }
                    443:        }
                    444:
                    445:        /* Set the speed */
                    446:        if (i2s_set_rate(sc, play->sample_rate))
                    447:                return EINVAL;
                    448:
                    449:        p->sample_rate = sc->sc_rate;
                    450:
                    451:        return 0;
                    452: }
                    453:
                    454: int
                    455: i2s_round_blocksize(h, size)
                    456:        void *h;
                    457:        int size;
                    458: {
                    459:        if (size < NBPG)
                    460:                size = NBPG;
                    461:        return size & ~PGOFSET;
                    462: }
                    463:
                    464: int
                    465: i2s_halt_output(h)
                    466:        void *h;
                    467: {
                    468:        struct i2s_softc *sc = h;
                    469:
                    470:        dbdma_stop(sc->sc_odma);
                    471:        dbdma_reset(sc->sc_odma);
                    472:        return 0;
                    473: }
                    474:
                    475: int
                    476: i2s_halt_input(h)
                    477:        void *h;
                    478: {
                    479:        struct i2s_softc *sc = h;
                    480:
                    481:        dbdma_stop(sc->sc_idma);
                    482:        dbdma_reset(sc->sc_idma);
                    483:        return 0;
                    484: }
                    485:
                    486: enum {
                    487:        I2S_OUTPUT_CLASS,
                    488:        I2S_RECORD_CLASS,
                    489:        I2S_OUTPUT_SELECT,
                    490:        I2S_VOL_OUTPUT,
                    491:        I2S_INPUT_SELECT,
                    492:        I2S_VOL_INPUT,
                    493:        I2S_BASS,
                    494:        I2S_TREBLE,
                    495:        I2S_ENUM_LAST
                    496: };
                    497:
                    498: int
                    499: i2s_set_port(h, mc)
                    500:        void *h;
                    501:        mixer_ctrl_t *mc;
                    502: {
                    503:        struct i2s_softc *sc = h;
                    504:        int l, r;
                    505:
                    506:        DPRINTF(("i2s_set_port dev = %d, type = %d\n", mc->dev, mc->type));
                    507:
                    508:        l = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
                    509:        r = mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                    510:
                    511:        switch (mc->dev) {
                    512:        case I2S_OUTPUT_SELECT:
                    513:                /* No change necessary? */
                    514:                if (mc->un.mask == sc->sc_output_mask)
                    515:                        return 0;
                    516:
                    517:                i2s_mute_speaker(sc, 1);
                    518:                i2s_mute_headphone(sc, 1);
                    519:                i2s_mute_lineout(sc, 1);
                    520:                if (mc->un.mask & 1 << 0)
                    521:                        i2s_mute_speaker(sc, 0);
                    522:                if (mc->un.mask & 1 << 1)
                    523:                        i2s_mute_headphone(sc, 0);
                    524:                if (mc->un.mask & 1 << 2)
                    525:                        i2s_mute_lineout(sc, 0);
                    526:
                    527:                sc->sc_output_mask = mc->un.mask;
                    528:                return 0;
                    529:
                    530:        case I2S_VOL_OUTPUT:
                    531:                (*sc->sc_setvolume)(sc, l, r);
                    532:                return 0;
                    533:
                    534:        case I2S_BASS:
                    535:                if (sc->sc_setbass != NULL)
                    536:                        (*sc->sc_setbass)(sc, l);
                    537:                return (0);
                    538:
                    539:        case I2S_TREBLE:
                    540:                if (sc->sc_settreble != NULL)
                    541:                        (*sc->sc_settreble)(sc, l);
                    542:                return (0);
                    543:
                    544:        case I2S_INPUT_SELECT:
                    545:                /* no change necessary? */
                    546:                if (mc->un.mask == sc->sc_record_source)
                    547:                        return 0;
                    548:                switch (mc->un.mask) {
                    549:                case 1 << 0: /* CD */
                    550:                case 1 << 1: /* microphone */
                    551:                case 1 << 2: /* line in */
                    552:                        /* XXX TO BE DONE */
                    553:                        break;
                    554:                default: /* invalid argument */
                    555:                        return EINVAL;
                    556:                }
                    557:                sc->sc_record_source = mc->un.mask;
                    558:                return 0;
                    559:
                    560:        case I2S_VOL_INPUT:
                    561:                /* XXX TO BE DONE */
                    562:                return 0;
                    563:        }
                    564:
                    565:        return ENXIO;
                    566: }
                    567:
                    568: int
                    569: i2s_get_port(h, mc)
                    570:        void *h;
                    571:        mixer_ctrl_t *mc;
                    572: {
                    573:        struct i2s_softc *sc = h;
                    574:
                    575:        DPRINTF(("i2s_get_port dev = %d, type = %d\n", mc->dev, mc->type));
                    576:
                    577:        switch (mc->dev) {
                    578:        case I2S_OUTPUT_SELECT:
                    579:                mc->un.mask = sc->sc_output_mask;
                    580:                return 0;
                    581:
                    582:        case I2S_VOL_OUTPUT:
                    583:                mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_vol_l;
                    584:                mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_vol_r;
                    585:                return 0;
                    586:
                    587:        case I2S_INPUT_SELECT:
                    588:                mc->un.mask = sc->sc_record_source;
                    589:                return 0;
                    590:
                    591:        case I2S_BASS:
                    592:                mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_bass;
                    593:                return (0);
                    594:
                    595:        case I2S_TREBLE:
                    596:                mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_treble;
                    597:                return (0);
                    598:
                    599:        case I2S_VOL_INPUT:
                    600:                /* XXX TO BE DONE */
                    601:                mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = 0;
                    602:                mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = 0;
                    603:                return 0;
                    604:
                    605:        default:
                    606:                return ENXIO;
                    607:        }
                    608:
                    609:        return 0;
                    610: }
                    611:
                    612: int
                    613: i2s_query_devinfo(h, dip)
                    614:        void *h;
                    615:        mixer_devinfo_t *dip;
                    616: {
                    617:        struct i2s_softc *sc = h;
                    618:        int n = 0;
                    619:
                    620:        switch (dip->index) {
                    621:
                    622:        case I2S_OUTPUT_SELECT:
                    623:                dip->mixer_class = I2S_OUTPUT_CLASS;
                    624:                strlcpy(dip->label.name, AudioNselect, sizeof(dip->label.name));
                    625:                dip->type = AUDIO_MIXER_SET;
                    626:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                    627:                strlcpy(dip->un.s.member[n].label.name, AudioNspeaker,
                    628:                    sizeof(dip->un.s.member[n].label.name));
                    629:                dip->un.s.member[n++].mask = 1 << 0;
                    630:                if (headphone_mute) {
                    631:                        strlcpy(dip->un.s.member[n].label.name,
                    632:                            AudioNheadphone,
                    633:                            sizeof(dip->un.s.member[n].label.name));
                    634:                        dip->un.s.member[n++].mask = 1 << 1;
                    635:                }
                    636:                if (lineout_mute) {
                    637:                        strlcpy(dip->un.s.member[n].label.name, AudioNline,
                    638:                            sizeof(dip->un.s.member[n].label.name));
                    639:                        dip->un.s.member[n++].mask = 1 << 2;
                    640:                }
                    641:                dip->un.s.num_mem = n;
                    642:                return 0;
                    643:
                    644:        case I2S_VOL_OUTPUT:
                    645:                dip->mixer_class = I2S_OUTPUT_CLASS;
                    646:                strlcpy(dip->label.name, AudioNmaster, sizeof(dip->label.name));
                    647:                dip->type = AUDIO_MIXER_VALUE;
                    648:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                    649:                dip->un.v.num_channels = 2;
                    650:                strlcpy(dip->un.v.units.name, AudioNvolume,
                    651:                    sizeof(dip->un.v.units.name));
                    652:                return 0;
                    653:
                    654:        case I2S_INPUT_SELECT:
                    655:                dip->mixer_class = I2S_RECORD_CLASS;
                    656:                strlcpy(dip->label.name, AudioNsource, sizeof(dip->label.name));
                    657:                dip->type = AUDIO_MIXER_SET;
                    658:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                    659:                dip->un.s.num_mem = 3;
                    660:                strlcpy(dip->un.s.member[0].label.name, AudioNcd,
                    661:                    sizeof(dip->un.s.member[0].label.name));
                    662:                dip->un.s.member[0].mask = 1 << 0;
                    663:                strlcpy(dip->un.s.member[1].label.name, AudioNmicrophone,
                    664:                    sizeof(dip->un.s.member[1].label.name));
                    665:                dip->un.s.member[1].mask = 1 << 1;
                    666:                strlcpy(dip->un.s.member[2].label.name, AudioNline,
                    667:                    sizeof(dip->un.s.member[2].label.name));
                    668:                dip->un.s.member[2].mask = 1 << 2;
                    669:                return 0;
                    670:
                    671:        case I2S_VOL_INPUT:
                    672:                dip->mixer_class = I2S_RECORD_CLASS;
                    673:                strlcpy(dip->label.name, AudioNrecord, sizeof(dip->label.name));
                    674:                dip->type = AUDIO_MIXER_VALUE;
                    675:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                    676:                dip->un.v.num_channels = 2;
                    677:                strlcpy(dip->un.v.units.name, AudioNvolume,
                    678:                    sizeof(dip->un.v.units.name));
                    679:                return 0;
                    680:
                    681:        case I2S_OUTPUT_CLASS:
                    682:                dip->mixer_class = I2S_OUTPUT_CLASS;
                    683:                strlcpy(dip->label.name, AudioCoutputs,
                    684:                    sizeof(dip->label.name));
                    685:                dip->type = AUDIO_MIXER_CLASS;
                    686:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                    687:                return 0;
                    688:
                    689:        case I2S_RECORD_CLASS:
                    690:                dip->mixer_class = I2S_RECORD_CLASS;
                    691:                strlcpy(dip->label.name, AudioCrecord, sizeof(dip->label.name));
                    692:                dip->type = AUDIO_MIXER_CLASS;
                    693:                dip->next = dip->prev = AUDIO_MIXER_LAST;
                    694:                return 0;
                    695:
                    696:        case I2S_BASS:
                    697:                if (sc->sc_setbass == NULL)
                    698:                        return (ENXIO);
                    699:                dip->mixer_class = I2S_OUTPUT_CLASS;
                    700:                strlcpy(dip->label.name, AudioNbass, sizeof(dip->label.name));
                    701:                dip->type = AUDIO_MIXER_VALUE;
                    702:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                    703:                dip->un.v.num_channels = 1;
                    704:                return (0);
                    705:
                    706:        case I2S_TREBLE:
                    707:                if (sc->sc_settreble == NULL)
                    708:                        return (ENXIO);
                    709:                dip->mixer_class = I2S_OUTPUT_CLASS;
                    710:                strlcpy(dip->label.name, AudioNtreble, sizeof(dip->label.name));
                    711:                dip->type = AUDIO_MIXER_VALUE;
                    712:                dip->prev = dip->next = AUDIO_MIXER_LAST;
                    713:                dip->un.v.num_channels = 1;
                    714:                return (0);
                    715:        }
                    716:
                    717:        return ENXIO;
                    718: }
                    719:
                    720: size_t
                    721: i2s_round_buffersize(h, dir, size)
                    722:        void *h;
                    723:        int dir;
                    724:        size_t size;
                    725: {
                    726:        if (size > 65536)
                    727:                size = 65536;
                    728:        return size;
                    729: }
                    730:
                    731: paddr_t
                    732: i2s_mappage(h, mem, off, prot)
                    733:        void *h;
                    734:        void *mem;
                    735:        off_t off;
                    736:        int prot;
                    737: {
                    738:        if (off < 0)
                    739:                return -1;
                    740:        return -1;      /* XXX */
                    741: }
                    742:
                    743: int
                    744: i2s_get_props(h)
                    745:        void *h;
                    746: {
                    747:        return AUDIO_PROP_FULLDUPLEX /* | AUDIO_PROP_MMAP */;
                    748: }
                    749:
                    750: int
                    751: i2s_trigger_output(h, start, end, bsize, intr, arg, param)
                    752:        void *h;
                    753:        void *start, *end;
                    754:        int bsize;
                    755:        void (*intr)(void *);
                    756:        void *arg;
                    757:        struct audio_params *param;
                    758: {
                    759:        struct i2s_softc *sc = h;
                    760:        struct i2s_dma *p;
                    761:        struct dbdma_command *cmd = sc->sc_odmacmd;
                    762:        vaddr_t spa, pa, epa;
                    763:        int c;
                    764:
                    765:        DPRINTF(("trigger_output %p %p 0x%x\n", start, end, bsize));
                    766:
                    767:        for (p = sc->sc_dmas; p && p->addr != start; p = p->next);
                    768:        if (!p)
                    769:                return -1;
                    770:
                    771:        sc->sc_ointr = intr;
                    772:        sc->sc_oarg = arg;
                    773:        sc->sc_odmap = sc->sc_odmacmd;
                    774:
                    775:        spa = p->segs[0].ds_addr;
                    776:        c = DBDMA_CMD_OUT_MORE;
                    777:        for (pa = spa, epa = spa + (end - start);
                    778:            pa < epa; pa += bsize, cmd++) {
                    779:
                    780:                if (pa + bsize == epa)
                    781:                        c = DBDMA_CMD_OUT_LAST;
                    782:
                    783:                DBDMA_BUILD(cmd, c, 0, bsize, pa, DBDMA_INT_ALWAYS,
                    784:                        DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
                    785:        }
                    786:
                    787:        DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
                    788:                DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
                    789:        dbdma_st32(&cmd->d_cmddep, sc->sc_odbdma->d_paddr);
                    790:
                    791:        dbdma_start(sc->sc_odma, sc->sc_odbdma);
                    792:
                    793:        return 0;
                    794: }
                    795:
                    796: int
                    797: i2s_trigger_input(h, start, end, bsize, intr, arg, param)
                    798:        void *h;
                    799:        void *start, *end;
                    800:        int bsize;
                    801:        void (*intr)(void *);
                    802:        void *arg;
                    803:        struct audio_params *param;
                    804: {
                    805:        DPRINTF(("i2s_trigger_input called\n"));
                    806:
                    807:        return 1;
                    808: }
                    809:
                    810:
                    811: /* rate = fs = LRCLK
                    812:  * SCLK = 64*LRCLK (I2S)
                    813:  * MCLK = 256fs (typ. -- changeable)
                    814:  * MCLK = clksrc / mdiv
                    815:  *  SCLK = MCLK / sdiv
                    816:  * rate = SCLK / 64    ( = LRCLK = fs)
                    817:  */
                    818: int
                    819: i2s_set_rate(sc, rate)
                    820:        struct i2s_softc *sc;
                    821:        int rate;
                    822: {
                    823:        u_int reg = 0;
                    824:        int MCLK;
                    825:        int clksrc, mdiv, sdiv;
                    826:        int mclk_fs;
                    827:        int timo;
                    828:
                    829:        /* sanify */
                    830:        if (rate > 48000)
                    831:                rate = 48000;
                    832:        else if (rate < 8000)
                    833:                rate = 8000;
                    834:
                    835:        switch (rate) {
                    836:        case 8000:
                    837:                clksrc = 18432000;              /* 18MHz */
                    838:                reg = CLKSRC_18MHz;
                    839:                mclk_fs = 256;
                    840:                break;
                    841:
                    842:        case 44100:
                    843:                clksrc = 45158400;              /* 45MHz */
                    844:                reg = CLKSRC_45MHz;
                    845:                mclk_fs = 256;
                    846:                break;
                    847:
                    848:        case 48000:
                    849:                clksrc = 49152000;              /* 49MHz */
                    850:                reg = CLKSRC_49MHz;
                    851:                mclk_fs = 256;
                    852:                break;
                    853:
                    854:        default:
                    855:                return EINVAL;
                    856:        }
                    857:
                    858:        MCLK = rate * mclk_fs;
                    859:        mdiv = clksrc / MCLK;                   /* 4 */
                    860:        sdiv = mclk_fs / 64;                    /* 4 */
                    861:
                    862:        switch (mdiv) {
                    863:        case 1:
                    864:                reg |= MCLK_DIV1;
                    865:                break;
                    866:        case 3:
                    867:                reg |= MCLK_DIV3;
                    868:                break;
                    869:        case 5:
                    870:                reg |= MCLK_DIV5;
                    871:                break;
                    872:        default:
                    873:                reg |= ((mdiv / 2 - 1) << 24) & 0x1f000000;
                    874:                break;
                    875:        }
                    876:
                    877:        switch (sdiv) {
                    878:        case 1:
                    879:                reg |= SCLK_DIV1;
                    880:                break;
                    881:        case 3:
                    882:                reg |= SCLK_DIV3;
                    883:                break;
                    884:        default:
                    885:                reg |= ((sdiv / 2 - 1) << 20) & 0x00f00000;
                    886:                break;
                    887:        }
                    888:
                    889:        reg |= SCLK_MASTER;     /* XXX master mode */
                    890:
                    891:        reg |= SERIAL_64x;
                    892:
                    893:        if (sc->sc_rate == rate)
                    894:                return (0);
                    895:
                    896:        /* stereo input and output */
                    897:        DPRINTF(("I2SSetDataWordSizeReg 0x%08x -> 0x%08x\n",
                    898:            in32rb(sc->sc_reg + I2S_WORDSIZE), 0x02000200));
                    899:        out32rb(sc->sc_reg + I2S_WORDSIZE, 0x02000200);
                    900:
                    901:        /* Clear CLKSTOPPEND */
                    902:        out32rb(sc->sc_reg + I2S_INT, I2S_INT_CLKSTOPPEND);
                    903:
                    904:        keylargo_fcr_disable(I2SClockOffset, I2S0CLKEN);
                    905:
                    906:        /* Wait until clock is stopped */
                    907:        for (timo = 1000; timo > 0; timo--) {
                    908:                if (in32rb(sc->sc_reg + I2S_INT) & I2S_INT_CLKSTOPPEND)
                    909:                        goto done;
                    910:                delay(1);
                    911:        }
                    912:
                    913:        printf("i2s_set_rate: timeout\n");
                    914:
                    915: done:
                    916:        DPRINTF(("I2SSetSerialFormatReg 0x%x -> 0x%x\n",
                    917:            in32rb(sc->sc_reg + I2S_FORMAT), reg));
                    918:        out32rb(sc->sc_reg + I2S_FORMAT, reg);
                    919:
                    920:        keylargo_fcr_enable(I2SClockOffset, I2S0CLKEN);
                    921:
                    922:        sc->sc_rate = rate;
                    923:
                    924:        return 0;
                    925: }
                    926:
                    927: int
                    928: gpio_read(addr)
                    929:        char *addr;
                    930: {
                    931:        if (*addr & GPIO_DATA)
                    932:                return 1;
                    933:        return 0;
                    934: }
                    935:
                    936: void
                    937: gpio_write(addr, val)
                    938:        char *addr;
                    939:        int val;
                    940: {
                    941:        u_int data = GPIO_DDR_OUTPUT;
                    942:
                    943:        if (val)
                    944:                data |= GPIO_DATA;
                    945:        *addr = data;
                    946:        asm volatile ("eieio" ::: "memory");
                    947: }
                    948:
                    949: #define amp_active 0           /* XXX OF */
                    950: #define headphone_active 0     /* XXX OF */
                    951: #define lineout_active 0       /* XXX OF */
                    952:
                    953: void
                    954: i2s_mute_speaker(sc, mute)
                    955:        struct i2s_softc *sc;
                    956:        int mute;
                    957: {
                    958:        u_int x;
                    959:
                    960:        if (amp_mute == NULL)
                    961:                return;
                    962:
                    963:        DPRINTF(("ampmute %d --> ", gpio_read(amp_mute)));
                    964:
                    965:        if (mute)
                    966:                x = amp_active;         /* mute */
                    967:        else
                    968:                x = !amp_active;        /* unmute */
                    969:        if (x != gpio_read(amp_mute))
                    970:                gpio_write(amp_mute, x);
                    971:
                    972:        DPRINTF(("%d\n", gpio_read(amp_mute)));
                    973: }
                    974:
                    975: void
                    976: i2s_mute_headphone(sc, mute)
                    977:        struct i2s_softc *sc;
                    978:        int mute;
                    979: {
                    980:        u_int x;
                    981:
                    982:        if (headphone_mute == NULL)
                    983:                return;
                    984:
                    985:        DPRINTF(("headphonemute %d --> ", gpio_read(headphone_mute)));
                    986:
                    987:        if (mute)
                    988:                x = headphone_active;   /* mute */
                    989:        else
                    990:                x = !headphone_active;  /* unmute */
                    991:        if (x != gpio_read(headphone_mute))
                    992:                gpio_write(headphone_mute, x);
                    993:
                    994:        DPRINTF(("%d\n", gpio_read(headphone_mute)));
                    995: }
                    996:
                    997: void
                    998: i2s_mute_lineout(sc, mute)
                    999:        struct i2s_softc *sc;
                   1000:        int mute;
                   1001: {
                   1002:        u_int x;
                   1003:
                   1004:        if (lineout_mute == NULL)
                   1005:                return;
                   1006:
                   1007:        DPRINTF(("lineout %d --> ", gpio_read(lineout_mute)));
                   1008:
                   1009:        if (mute)
                   1010:                x = lineout_active;     /* mute */
                   1011:        else
                   1012:                x = !lineout_active;    /* unmute */
                   1013:        if (x != gpio_read(lineout_mute))
                   1014:                gpio_write(lineout_mute, x);
                   1015:
                   1016:        DPRINTF(("%d\n", gpio_read(lineout_mute)));
                   1017: }
                   1018:
                   1019: int
                   1020: i2s_cint(v)
                   1021:        void *v;
                   1022: {
                   1023:        struct i2s_softc *sc = v;
                   1024:        u_int sense;
                   1025:
                   1026:        sc->sc_output_mask = 0;
                   1027:        i2s_mute_speaker(sc, 1);
                   1028:        i2s_mute_headphone(sc, 1);
                   1029:        i2s_mute_lineout(sc, 1);
                   1030:
                   1031:        if (headphone_detect)
                   1032:                sense = *headphone_detect;
                   1033:        else
                   1034:                sense = !headphone_detect_active << 1;
                   1035:        DPRINTF(("headphone detect = 0x%x\n", sense));
                   1036:
                   1037:        if (((sense & 0x02) >> 1) == headphone_detect_active) {
                   1038:                DPRINTF(("headphone is inserted\n"));
                   1039:                sc->sc_output_mask |= 1 << 1;
                   1040:                i2s_mute_headphone(sc, 0);
                   1041:        } else {
                   1042:                DPRINTF(("headphone is NOT inserted\n"));
                   1043:        }
                   1044:
                   1045:        if (lineout_detect)
                   1046:                sense = *lineout_detect;
                   1047:        else
                   1048:                sense = !lineout_detect_active << 1;
                   1049:        DPRINTF(("lineout detect = 0x%x\n", sense));
                   1050:
                   1051:        if (((sense & 0x02) >> 1) == lineout_detect_active) {
                   1052:                DPRINTF(("lineout is inserted\n"));
                   1053:                sc->sc_output_mask |= 1 << 2;
                   1054:                i2s_mute_lineout(sc, 0);
                   1055:        } else {
                   1056:                DPRINTF(("lineout is NOT inserted\n"));
                   1057:        }
                   1058:
                   1059:        if (sc->sc_output_mask == 0) {
                   1060:                sc->sc_output_mask |= 1 << 0;
                   1061:                i2s_mute_speaker(sc, 0);
                   1062:        }
                   1063:
                   1064:        return 1;
                   1065: }
                   1066:
                   1067: u_char *
                   1068: i2s_gpio_map(struct i2s_softc *sc, char *name, int *irq)
                   1069: {
                   1070:        u_int32_t reg[2];
                   1071:        u_int32_t intr[2];
                   1072:        int gpio;
                   1073:
                   1074:        if (OF_getprop(sc->sc_node, name, &gpio,
                   1075:             sizeof(gpio)) != sizeof(gpio) ||
                   1076:            OF_getprop(gpio, "reg", &reg[0],
                   1077:            sizeof(reg[0])) != sizeof(reg[0]) ||
                   1078:            OF_getprop(OF_parent(gpio), "reg", &reg[1],
                   1079:            sizeof(reg[1])) != sizeof(reg[1]))
                   1080:                return NULL;
                   1081:
                   1082:        if (irq && OF_getprop(gpio, "interrupts",
                   1083:            intr, sizeof(intr)) == sizeof(intr)) {
                   1084:                *irq = intr[0];
                   1085:        }
                   1086:
                   1087:        return mapiodev(sc->sc_baseaddr + reg[0] + reg[1], 1);
                   1088: }
                   1089:
                   1090: void
                   1091: i2s_gpio_init(sc, node, parent)
                   1092:        struct i2s_softc *sc;
                   1093:        int node;
                   1094:        struct device *parent;
                   1095: {
                   1096:        int gpio;
                   1097:        int headphone_detect_intr = -1, headphone_detect_intrtype;
                   1098:        int lineout_detect_intr = -1;
                   1099:
                   1100:        /* Map gpios. */
                   1101:        amp_mute = i2s_gpio_map(sc, "platform-amp-mute", NULL);
                   1102:        headphone_mute = i2s_gpio_map(sc, "platform-headphone-mute", NULL);
                   1103:        headphone_detect = i2s_gpio_map(sc, "platform-headphone-detect",
                   1104:            &headphone_detect_intr);
                   1105:        lineout_mute = i2s_gpio_map(sc, "platform-lineout-mute", NULL);
                   1106:        lineout_detect = i2s_gpio_map(sc, "platform-lineout-detect",
                   1107:            &lineout_detect_intr);
                   1108:        audio_hw_reset = i2s_gpio_map(sc, "platform-hw-reset", NULL);
                   1109:
                   1110:        gpio = OF_getnodebyname(OF_parent(node), "gpio");
                   1111:        DPRINTF((" /gpio 0x%x\n", gpio));
                   1112:        gpio = OF_child(gpio);
                   1113:        while (gpio) {
                   1114:                char name[64], audio_gpio[64];
                   1115:                int intr[2];
                   1116:                paddr_t addr;
                   1117:
                   1118:                bzero(name, sizeof name);
                   1119:                bzero(audio_gpio, sizeof audio_gpio);
                   1120:                addr = 0;
                   1121:                OF_getprop(gpio, "name", name, sizeof name);
                   1122:                OF_getprop(gpio, "audio-gpio", audio_gpio, sizeof audio_gpio);
                   1123:                OF_getprop(gpio, "AAPL,address", &addr, sizeof addr);
                   1124:                /* printf("0x%x %s %s\n", gpio, name, audio_gpio); */
                   1125:
                   1126:                /* gpio5 */
                   1127:                if (headphone_mute == NULL &&
                   1128:                    strcmp(audio_gpio, "headphone-mute") == 0)
                   1129:                        headphone_mute = mapiodev(addr,1);
                   1130:
                   1131:                /* gpio6 */
                   1132:                if (amp_mute == NULL &&
                   1133:                    strcmp(audio_gpio, "amp-mute") == 0)
                   1134:                        amp_mute = mapiodev(addr,1);
                   1135:
                   1136:                /* extint-gpio15 */
                   1137:                if (headphone_detect == NULL &&
                   1138:                    strcmp(audio_gpio, "headphone-detect") == 0) {
                   1139:                        headphone_detect = mapiodev(addr,1);
                   1140:                        OF_getprop(gpio, "audio-gpio-active-state",
                   1141:                            &headphone_detect_active, 4);
                   1142:                        OF_getprop(gpio, "interrupts", intr, 8);
                   1143:                        headphone_detect_intr = intr[0];
                   1144:                        headphone_detect_intrtype = intr[1];
                   1145:                }
                   1146:
                   1147:                /* gpio11 (keywest-11) */
                   1148:                if (audio_hw_reset == NULL &&
                   1149:                    strcmp(audio_gpio, "audio-hw-reset") == 0)
                   1150:                        audio_hw_reset = mapiodev(addr,1);
                   1151:
                   1152:                gpio = OF_peer(gpio);
                   1153:        }
                   1154:        DPRINTF((" amp-mute %p\n", amp_mute));
                   1155:        DPRINTF((" headphone-mute %p\n", headphone_mute));
                   1156:        DPRINTF((" headphone-detect %p\n", headphone_detect));
                   1157:        DPRINTF((" headphone-detect active %x\n", headphone_detect_active));
                   1158:        DPRINTF((" headphone-detect intr %x\n", headphone_detect_intr));
                   1159:        DPRINTF((" lineout-mute %p\n", lineout_mute));
                   1160:        DPRINTF((" lineout-detect %p\n", lineout_detect));
                   1161:        DPRINTF((" lineout-detect active %x\n", lineout_detect_active));
                   1162:        DPRINTF((" lineout-detect intr %x\n", lineout_detect_intr));
                   1163:        DPRINTF((" audio-hw-reset %p\n", audio_hw_reset));
                   1164:
                   1165:        if (headphone_detect_intr != -1)
                   1166:                mac_intr_establish(parent, headphone_detect_intr, IST_EDGE,
                   1167:                    IPL_AUDIO, i2s_cint, sc, sc->sc_dev.dv_xname);
                   1168:
                   1169:        if (lineout_detect_intr != -1)
                   1170:                mac_intr_establish(parent, lineout_detect_intr, IST_EDGE,
                   1171:                    IPL_AUDIO, i2s_cint, sc, sc->sc_dev.dv_xname);
                   1172:
                   1173:        /* Enable headphone interrupt? */
                   1174:        *headphone_detect |= 0x80;
                   1175:        asm volatile("eieio");
                   1176:
                   1177:        /* Update headphone status. */
                   1178:        i2s_cint(sc);
                   1179: }
                   1180:
                   1181: void *
                   1182: i2s_allocm(void *h, int dir, size_t size, int type, int flags)
                   1183: {
                   1184:        struct i2s_softc *sc = h;
                   1185:        struct i2s_dma *p;
                   1186:        int error;
                   1187:
                   1188:        if (size > I2S_DMALIST_MAX * I2S_DMASEG_MAX)
                   1189:                return (NULL);
                   1190:
                   1191:        p = malloc(sizeof(*p), type, flags);
                   1192:        if (!p)
                   1193:                return (NULL);
                   1194:        bzero(p, sizeof(*p));
                   1195:
                   1196:        /* convert to the bus.h style, not used otherwise */
                   1197:        if (flags & M_NOWAIT)
                   1198:                flags = BUS_DMA_NOWAIT;
                   1199:
                   1200:        p->size = size;
                   1201:        if ((error = bus_dmamem_alloc(sc->sc_dmat, p->size, NBPG, 0, p->segs,
                   1202:            1, &p->nsegs, flags)) != 0) {
                   1203:                printf("%s: unable to allocate dma, error = %d\n",
                   1204:                    sc->sc_dev.dv_xname, error);
                   1205:                free(p, type);
                   1206:                return NULL;
                   1207:        }
                   1208:
                   1209:        if ((error = bus_dmamem_map(sc->sc_dmat, p->segs, p->nsegs, p->size,
                   1210:            &p->addr, flags | BUS_DMA_COHERENT)) != 0) {
                   1211:                printf("%s: unable to map dma, error = %d\n",
                   1212:                    sc->sc_dev.dv_xname, error);
                   1213:                bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
                   1214:                free(p, type);
                   1215:                return NULL;
                   1216:        }
                   1217:
                   1218:        if ((error = bus_dmamap_create(sc->sc_dmat, p->size, 1,
                   1219:            p->size, 0, flags, &p->map)) != 0) {
                   1220:                printf("%s: unable to create dma map, error = %d\n",
                   1221:                    sc->sc_dev.dv_xname, error);
                   1222:                bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
                   1223:                bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
                   1224:                free(p, type);
                   1225:                return NULL;
                   1226:        }
                   1227:
                   1228:        if ((error = bus_dmamap_load(sc->sc_dmat, p->map, p->addr, p->size,
                   1229:            NULL, flags)) != 0) {
                   1230:                printf("%s: unable to load dma map, error = %d\n",
                   1231:                    sc->sc_dev.dv_xname, error);
                   1232:                bus_dmamap_destroy(sc->sc_dmat, p->map);
                   1233:                bus_dmamem_unmap(sc->sc_dmat, p->addr, size);
                   1234:                bus_dmamem_free(sc->sc_dmat, p->segs, p->nsegs);
                   1235:                free(p, type);
                   1236:                return NULL;
                   1237:        }
                   1238:
                   1239:        p->next = sc->sc_dmas;
                   1240:        sc->sc_dmas = p;
                   1241:
                   1242:        return p->addr;
                   1243: }
                   1244:
                   1245: #define reset_active 0
                   1246:
                   1247: int
                   1248: deq_reset(struct i2s_softc *sc)
                   1249: {
                   1250:        if (audio_hw_reset == NULL)
                   1251:                return (-1);
                   1252:
                   1253:        gpio_write(audio_hw_reset, !reset_active);
                   1254:        delay(1000000);
                   1255:
                   1256:        gpio_write(audio_hw_reset, reset_active);
                   1257:        delay(1);
                   1258:
                   1259:        gpio_write(audio_hw_reset, !reset_active);
                   1260:        delay(10000);
                   1261:
                   1262:        return (0);
                   1263: }

CVSweb