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

Annotation of sys/arch/zaurus/dev/zaurus_audio.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: zaurus_audio.c,v 1.8 2005/08/18 13:23:02 robert Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 2005 Christopher Pascoe <pascoe@openbsd.org>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: /*
                     20:  * TODO:
                     21:  *     - powerhooks (currently only works until first suspend)
                     22:  *     - record support
                     23:  */
                     24:
                     25: #include <sys/param.h>
                     26: #include <sys/systm.h>
                     27: #include <sys/timeout.h>
                     28: #include <sys/device.h>
                     29: #include <sys/malloc.h>
                     30: #include <sys/kernel.h>
                     31: #include <sys/audioio.h>
                     32:
                     33: #include <machine/intr.h>
                     34: #include <machine/bus.h>
                     35:
                     36: #include <arm/xscale/pxa2x0reg.h>
                     37: #include <arm/xscale/pxa2x0var.h>
                     38: #include <arm/xscale/pxa2x0_i2c.h>
                     39: #include <arm/xscale/pxa2x0_i2s.h>
                     40: #include <arm/xscale/pxa2x0_dmac.h>
                     41: #include <arm/xscale/pxa2x0_gpio.h>
                     42:
                     43: #include <zaurus/dev/zaurus_scoopvar.h>
                     44: #include <dev/i2c/wm8750reg.h>
                     45:
                     46: #include <dev/audio_if.h>
                     47: #include <dev/mulaw.h>
                     48: #include <dev/auconv.h>
                     49:
                     50: #define WM8750_ADDRESS  0x1B
                     51: #define SPKR_VOLUME    112
                     52:
                     53: #define wm8750_write(sc, reg, val)     pxa2x0_i2c_write_2(&sc->sc_i2c, \
                     54:     WM8750_ADDRESS, (((reg) << 9) | ((val) & 0x1ff)))
                     55:
                     56: int    zaudio_match(struct device *, void *, void *);
                     57: void   zaudio_attach(struct device *, struct device *, void *);
                     58: int    zaudio_detach(struct device *, int);
                     59: void   zaudio_power(int, void *);
                     60:
                     61: #define ZAUDIO_OP_SPKR 0
                     62: #define ZAUDIO_OP_HP   1
                     63:
                     64: #define ZAUDIO_JACK_STATE_OUT  0
                     65: #define ZAUDIO_JACK_STATE_IN   1
                     66: #define ZAUDIO_JACK_STATE_INS  2
                     67: #define ZAUDIO_JACK_STATE_REM  3
                     68:
                     69: /* GPIO pins */
                     70: #define GPIO_HP_IN_C3000       116
                     71:
                     72: struct zaudio_volume {
                     73:        u_int8_t                left;
                     74:        u_int8_t                right;
                     75: };
                     76:
                     77: struct zaudio_softc {
                     78:        struct device           sc_dev;
                     79:
                     80:        /* i2s device softc */
                     81:        /* NB: pxa2x0_i2s requires this to be the second struct member */
                     82:        struct pxa2x0_i2s_softc sc_i2s;
                     83:
                     84:        /* i2c device softc */
                     85:        struct pxa2x0_i2c_softc sc_i2c;
                     86:
                     87:        void                    *sc_powerhook;
                     88:        int                     sc_playing;
                     89:
                     90:        struct zaudio_volume    sc_volume[2];
                     91:        char                    sc_unmute[2];
                     92:
                     93:        int                     sc_state;
                     94:        int                     sc_icount;
                     95:        struct timeout          sc_to;
                     96: };
                     97:
                     98: struct cfattach zaudio_ca = {
                     99:        sizeof(struct zaudio_softc), zaudio_match, zaudio_attach,
                    100:        zaudio_detach
                    101: };
                    102:
                    103: struct cfdriver zaudio_cd = {
                    104:        NULL, "zaudio", DV_DULL
                    105: };
                    106:
                    107: struct audio_device wm8750_device = {
                    108:        "WM8750",
                    109:        "1.0",
                    110:        "wm"
                    111: };
                    112:
                    113: void zaudio_init(struct zaudio_softc *);
                    114: int zaudio_jack_intr(void *);
                    115: void zaudio_jack(void *);
                    116: void zaudio_standby(struct zaudio_softc *);
                    117: void zaudio_update_volume(struct zaudio_softc *, int);
                    118: void zaudio_update_mutes(struct zaudio_softc *);
                    119: void zaudio_play_setup(struct zaudio_softc *);
                    120: int zaudio_open(void *, int);
                    121: void zaudio_close(void *);
                    122: int zaudio_query_encoding(void *, struct audio_encoding *);
                    123: int zaudio_set_params(void *, int, int, struct audio_params *,
                    124:     struct audio_params *);
                    125: int zaudio_halt_output(void *);
                    126: int zaudio_halt_input(void *);
                    127: int zaudio_getdev(void *, struct audio_device *);
                    128: int zaudio_set_port(void *, struct mixer_ctrl *);
                    129: int zaudio_get_port(void *, struct mixer_ctrl *);
                    130: int zaudio_query_devinfo(void *, struct mixer_devinfo *);
                    131: int zaudio_get_props(void *);
                    132: int zaudio_start_output(void *, void *, int, void (*)(void *), void *);
                    133: int zaudio_start_input(void *, void *, int, void (*)(void *), void *);
                    134:
                    135: struct audio_hw_if wm8750_hw_if = {
                    136:        zaudio_open,
                    137:        zaudio_close,
                    138:        NULL /* zaudio_drain */,
                    139:        zaudio_query_encoding,
                    140:        zaudio_set_params,
                    141:        pxa2x0_i2s_round_blocksize,
                    142:        NULL /* zaudio_commit_settings */,
                    143:        NULL /* zaudio_init_output */,
                    144:        NULL /* zaudio_init_input */,
                    145:        zaudio_start_output,
                    146:        zaudio_start_input,
                    147:        zaudio_halt_output,
                    148:        zaudio_halt_input,
                    149:        NULL /* zaudio_speaker_ctl */,
                    150:        zaudio_getdev,
                    151:        NULL /* zaudio_setfd */,
                    152:        zaudio_set_port,
                    153:        zaudio_get_port,
                    154:        zaudio_query_devinfo,
                    155:        pxa2x0_i2s_allocm,
                    156:        pxa2x0_i2s_freem,
                    157:        pxa2x0_i2s_round_buffersize,
                    158:        pxa2x0_i2s_mappage,
                    159:        zaudio_get_props,
                    160:        NULL /* zaudio_trigger_output */,
                    161:        NULL /* zaudio_trigger_input */
                    162: };
                    163:
                    164: static const unsigned short playback_registers[][2] = {
                    165:        /* Unmute DAC */
                    166:        { ADCDACCTL_REG, 0x000 },
                    167:
                    168:        /* 16 bit audio words */
                    169:        { AUDINT_REG, AUDINT_SET_FORMAT(2) },
                    170:
                    171:        /* Enable thermal protection, power */
                    172:        { ADCTL1_REG, ADCTL1_TSDEN | ADCTL1_SET_VSEL(3) },
                    173:
                    174:        /* Enable speaker driver, DAC oversampling */
                    175:        { ADCTL2_REG, ADCTL2_ROUT2INV | ADCTL2_DACOSR },
                    176:
                    177:        /* Set DAC voltage references */
                    178:        { PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(1) | PWRMGMT1_VREF },
                    179:
                    180:        /* Direct DACs to output mixers */
                    181:        { LOUTMIX1_REG, LOUTMIX1_LD2LO },
                    182:        { ROUTMIX2_REG, ROUTMIX2_RD2RO },
                    183:
                    184:        /* End of list */
                    185:        { 0xffff, 0xffff }
                    186: };
                    187:
                    188: int
                    189: zaudio_match(struct device *parent, void *match, void *aux)
                    190: {
                    191:        return (1);
                    192: }
                    193:
                    194: void
                    195: zaudio_attach(struct device *parent, struct device *self, void *aux)
                    196: {
                    197:        struct zaudio_softc             *sc = (struct zaudio_softc *)self;
                    198:        struct pxaip_attach_args        *pxa = aux;
                    199:        int err;
                    200:
                    201:        sc->sc_powerhook = powerhook_establish(zaudio_power, sc);
                    202:        if (sc->sc_powerhook == NULL) {
                    203:                printf(": unable to establish powerhook\n");
                    204:                return;
                    205:        }
                    206:
                    207:        sc->sc_i2s.sc_iot = pxa->pxa_iot;
                    208:        sc->sc_i2s.sc_dmat = pxa->pxa_dmat;
                    209:        sc->sc_i2s.sc_size = PXA2X0_I2S_SIZE;
                    210:        if (pxa2x0_i2s_attach_sub(&sc->sc_i2s)) {
                    211:                printf(": unable to attach I2S\n");
                    212:                goto fail_i2s;
                    213:        }
                    214:
                    215:        sc->sc_i2c.sc_iot = pxa->pxa_iot;
                    216:        sc->sc_i2c.sc_size = PXA2X0_I2C_SIZE;
                    217:        if (pxa2x0_i2c_attach_sub(&sc->sc_i2c)) {
                    218:                printf(": unable to attach I2C\n");
                    219:                goto fail_i2c;
                    220:        }
                    221:
                    222:        /* Check for an I2C response from the wm8750 */
                    223:        pxa2x0_i2c_open(&sc->sc_i2c);
                    224:        err = wm8750_write(sc, RESET_REG, 0);
                    225:        pxa2x0_i2c_close(&sc->sc_i2c);
                    226:
                    227:        if (err) {
                    228:                printf(": codec failed to respond\n");
                    229:                goto fail_probe;
                    230:        }
                    231:        delay(100);
                    232:
                    233:        /* Speaker on, headphones off by default. */
                    234:        sc->sc_volume[ZAUDIO_OP_SPKR].left = 240;
                    235:        sc->sc_unmute[ZAUDIO_OP_SPKR] = 1;
                    236:        sc->sc_volume[ZAUDIO_OP_HP].left = 180;
                    237:        sc->sc_volume[ZAUDIO_OP_HP].right = 180;
                    238:        sc->sc_unmute[ZAUDIO_OP_HP] = 0;
                    239:
                    240:        /* Configure headphone jack state change handling. */
                    241:        timeout_set(&sc->sc_to, zaudio_jack, sc);
                    242:        pxa2x0_gpio_set_function(GPIO_HP_IN_C3000, GPIO_IN);
                    243:        (void)pxa2x0_gpio_intr_establish(GPIO_HP_IN_C3000,
                    244:            IST_EDGE_BOTH, IPL_BIO, zaudio_jack_intr, sc, "hpjk");
                    245:
                    246:        zaudio_init(sc);
                    247:
                    248:        printf(": I2C, I2S, WM8750 Audio\n");
                    249:
                    250:        audio_attach_mi(&wm8750_hw_if, sc, &sc->sc_dev);
                    251:
                    252:        return;
                    253:
                    254: fail_probe:
                    255:        pxa2x0_i2c_detach_sub(&sc->sc_i2c);
                    256: fail_i2c:
                    257:        pxa2x0_i2s_detach_sub(&sc->sc_i2s);
                    258: fail_i2s:
                    259:        powerhook_disestablish(sc->sc_powerhook);
                    260: }
                    261:
                    262: int
                    263: zaudio_detach(struct device *self, int flags)
                    264: {
                    265:        struct zaudio_softc *sc = (struct zaudio_softc *)self;
                    266:
                    267:        if (sc->sc_powerhook != NULL) {
                    268:                powerhook_disestablish(sc->sc_powerhook);
                    269:                sc->sc_powerhook = NULL;
                    270:        }
                    271:
                    272:        pxa2x0_i2c_detach_sub(&sc->sc_i2c);
                    273:        pxa2x0_i2s_detach_sub(&sc->sc_i2s);
                    274:
                    275:        return (0);
                    276: }
                    277:
                    278: void
                    279: zaudio_power(int why, void *arg)
                    280: {
                    281:        struct zaudio_softc *sc = arg;
                    282:
                    283:        switch (why) {
                    284:        case PWR_STANDBY:
                    285:        case PWR_SUSPEND:
                    286:                timeout_del(&sc->sc_to);
                    287:                zaudio_standby(sc);
                    288:                break;
                    289:
                    290:        case PWR_RESUME:
                    291:                pxa2x0_i2s_init(&sc->sc_i2s);
                    292:                pxa2x0_i2c_init(&sc->sc_i2c);
                    293:                zaudio_init(sc);
                    294:                break;
                    295:        }
                    296: }
                    297:
                    298: void
                    299: zaudio_init(struct zaudio_softc *sc)
                    300: {
                    301:        pxa2x0_i2c_open(&sc->sc_i2c);
                    302:
                    303:        /* Reset the codec */
                    304:        wm8750_write(sc, RESET_REG, 0);
                    305:        delay(100);
                    306:
                    307:        /* Switch to standby power only */
                    308:        wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2));
                    309:        wm8750_write(sc, PWRMGMT2_REG, 0);
                    310:
                    311:        /* Configure digital interface for I2S */
                    312:        wm8750_write(sc, AUDINT_REG, AUDINT_SET_FORMAT(2));
                    313:
                    314:        /* Initialise volume levels */
                    315:        zaudio_update_volume(sc, ZAUDIO_OP_SPKR);
                    316:        zaudio_update_volume(sc, ZAUDIO_OP_HP);
                    317:        scoop_set_headphone(0);
                    318:
                    319:        pxa2x0_i2c_close(&sc->sc_i2c);
                    320:
                    321:        /* Assume that the jack state has changed. */
                    322:        zaudio_jack(sc);
                    323:
                    324: }
                    325:
                    326: int
                    327: zaudio_jack_intr(void *v)
                    328: {
                    329:        struct zaudio_softc *sc = v;
                    330:
                    331:        if (!timeout_triggered(&sc->sc_to))
                    332:                zaudio_jack(sc);
                    333:
                    334:        return (1);
                    335: }
                    336:
                    337: void
                    338: zaudio_jack(void *v)
                    339: {
                    340:        struct zaudio_softc *sc = v;
                    341:
                    342:        switch (sc->sc_state) {
                    343:        case ZAUDIO_JACK_STATE_OUT:
                    344:                if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
                    345:                        sc->sc_state = ZAUDIO_JACK_STATE_INS;
                    346:                        sc->sc_icount = 0;
                    347:                }
                    348:                break;
                    349:        case ZAUDIO_JACK_STATE_INS:
                    350:                if (sc->sc_icount++ > 2) {
                    351:                        if (pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
                    352:                                sc->sc_state = ZAUDIO_JACK_STATE_IN;
                    353:                                sc->sc_unmute[ZAUDIO_OP_SPKR] = 0;
                    354:                                sc->sc_unmute[ZAUDIO_OP_HP] = 1;
                    355:                                goto update_mutes;
                    356:                        } else
                    357:                                sc->sc_state = ZAUDIO_JACK_STATE_OUT;
                    358:                }
                    359:                break;
                    360:        case ZAUDIO_JACK_STATE_IN:
                    361:                if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
                    362:                        sc->sc_state = ZAUDIO_JACK_STATE_REM;
                    363:                        sc->sc_icount = 0;
                    364:                }
                    365:                break;
                    366:        case ZAUDIO_JACK_STATE_REM:
                    367:                if (sc->sc_icount++ > 2) {
                    368:                        if (!pxa2x0_gpio_get_bit(GPIO_HP_IN_C3000)) {
                    369:                                sc->sc_state = ZAUDIO_JACK_STATE_OUT;
                    370:                                sc->sc_unmute[ZAUDIO_OP_SPKR] = 1;
                    371:                                sc->sc_unmute[ZAUDIO_OP_HP] = 0;
                    372:                                goto update_mutes;
                    373:                        } else
                    374:                                sc->sc_state = ZAUDIO_JACK_STATE_IN;
                    375:                }
                    376:                break;
                    377:        }
                    378:
                    379:        timeout_add(&sc->sc_to, hz/4);
                    380:        return;
                    381:
                    382: update_mutes:
                    383:        timeout_del(&sc->sc_to);
                    384:
                    385:        if (sc->sc_playing) {
                    386:                pxa2x0_i2c_open(&sc->sc_i2c);
                    387:                zaudio_update_mutes(sc);
                    388:                pxa2x0_i2c_close(&sc->sc_i2c);
                    389:        }
                    390: }
                    391:
                    392: void
                    393: zaudio_standby(struct zaudio_softc *sc)
                    394: {
                    395:        pxa2x0_i2c_open(&sc->sc_i2c);
                    396:
                    397:        /* Switch codec to standby power only */
                    398:        wm8750_write(sc, PWRMGMT1_REG, PWRMGMT1_SET_VMIDSEL(2));
                    399:        wm8750_write(sc, PWRMGMT2_REG, 0);
                    400:
                    401:        scoop_set_headphone(0);
                    402:
                    403:        pxa2x0_i2c_close(&sc->sc_i2c);
                    404: }
                    405:
                    406: void
                    407: zaudio_update_volume(struct zaudio_softc *sc, int output)
                    408: {
                    409:        switch(output) {
                    410:        case ZAUDIO_OP_SPKR:
                    411:                wm8750_write(sc, LOUT2VOL_REG, LOUT2VOL_LO2VU | LOUT2VOL_LO2ZC |
                    412:                    LOUT2VOL_SET_LOUT2VOL(sc->sc_volume[ZAUDIO_OP_SPKR
                    413:                    ].left >> 1));
                    414:                wm8750_write(sc, ROUT2VOL_REG, ROUT2VOL_RO2VU | ROUT2VOL_RO2ZC |
                    415:                    ROUT2VOL_SET_ROUT2VOL(sc->sc_volume[ZAUDIO_OP_SPKR
                    416:                    ].left >> 1));
                    417:                break;
                    418:        case ZAUDIO_OP_HP:
                    419:                wm8750_write(sc, LOUT1VOL_REG, LOUT1VOL_LO1VU | LOUT1VOL_LO1ZC |
                    420:                    LOUT1VOL_SET_LOUT1VOL(sc->sc_volume[ZAUDIO_OP_HP
                    421:                    ].left >> 1));
                    422:                wm8750_write(sc, ROUT1VOL_REG, ROUT1VOL_RO1VU | ROUT1VOL_RO1ZC |
                    423:                    ROUT1VOL_SET_ROUT1VOL(sc->sc_volume[ZAUDIO_OP_HP
                    424:                    ].right >> 1));
                    425:                break;
                    426:        }
                    427: }
                    428:
                    429: void
                    430: zaudio_update_mutes(struct zaudio_softc *sc)
                    431: {
                    432:        unsigned short val;
                    433:
                    434:        val = PWRMGMT2_DACL | PWRMGMT2_DACR;
                    435:
                    436:        if (sc->sc_unmute[ZAUDIO_OP_SPKR])
                    437:                val |= PWRMGMT2_LOUT2 | PWRMGMT2_ROUT2;
                    438:
                    439:        if (sc->sc_unmute[ZAUDIO_OP_HP])
                    440:                val |= PWRMGMT2_LOUT1 | PWRMGMT2_ROUT1;
                    441:
                    442:        wm8750_write(sc, PWRMGMT2_REG, val);
                    443:
                    444:        scoop_set_headphone(sc->sc_unmute[ZAUDIO_OP_HP]);
                    445: }
                    446:
                    447: void
                    448: zaudio_play_setup(struct zaudio_softc *sc)
                    449: {
                    450:        int i = 0;
                    451:
                    452:        pxa2x0_i2c_open(&sc->sc_i2c);
                    453:
                    454:        /* Program the codec with playback settings */
                    455:        while (playback_registers[i][0] != 0xffff) {
                    456:                wm8750_write(sc, playback_registers[i][0],
                    457:                    playback_registers[i][1]);
                    458:                i++;
                    459:        }
                    460:        zaudio_update_mutes(sc);
                    461:
                    462:        pxa2x0_i2c_close(&sc->sc_i2c);
                    463: }
                    464:
                    465: int
                    466: zaudio_open(void *hdl, int flags)
                    467: {
                    468:        struct zaudio_softc *sc = hdl;
                    469:
                    470:        /* Power on the I2S bus and codec */
                    471:        pxa2x0_i2s_open(&sc->sc_i2s);
                    472:
                    473:        return 0;
                    474: }
                    475:
                    476: void
                    477: zaudio_close(void *hdl)
                    478: {
                    479:        struct zaudio_softc *sc = hdl;
                    480:
                    481:        /* Power off the I2S bus and codec */
                    482:        pxa2x0_i2s_close(&sc->sc_i2s);
                    483: }
                    484:
                    485: int
                    486: zaudio_query_encoding(void *hdl, struct audio_encoding *aep)
                    487: {
                    488:        switch (aep->index) {
                    489:        case 0:
                    490:                strlcpy(aep->name, AudioEulinear, sizeof(aep->name));
                    491:                aep->encoding = AUDIO_ENCODING_ULINEAR;
                    492:                aep->precision = 8;
                    493:                aep->flags = 0;
                    494:                return (0);
                    495:        case 1:
                    496:                strlcpy(aep->name, AudioEmulaw, sizeof(aep->name));
                    497:                aep->encoding = AUDIO_ENCODING_ULAW;
                    498:                aep->precision = 8;
                    499:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    500:                return (0);
                    501:        case 2:
                    502:                strlcpy(aep->name, AudioEalaw, sizeof(aep->name));
                    503:                aep->encoding = AUDIO_ENCODING_ALAW;
                    504:                aep->precision = 8;
                    505:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    506:                return (0);
                    507:        case 3:
                    508:                strlcpy(aep->name, AudioEslinear, sizeof(aep->name));
                    509:                aep->encoding = AUDIO_ENCODING_SLINEAR;
                    510:                aep->precision = 8;
                    511:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    512:                return (0);
                    513:        case 4:
                    514:                strlcpy(aep->name, AudioEslinear_le, sizeof(aep->name));
                    515:                aep->encoding = AUDIO_ENCODING_SLINEAR_LE;
                    516:                aep->precision = 16;
                    517:                aep->flags = 0;
                    518:                return (0);
                    519:        case 5:
                    520:                strlcpy(aep->name, AudioEulinear_le, sizeof(aep->name));
                    521:                aep->encoding = AUDIO_ENCODING_ULINEAR_LE;
                    522:                aep->precision = 16;
                    523:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    524:                return (0);
                    525:        case 6:
                    526:                strlcpy(aep->name, AudioEslinear_be, sizeof(aep->name));
                    527:                aep->encoding = AUDIO_ENCODING_SLINEAR_BE;
                    528:                aep->precision = 16;
                    529:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    530:                return (0);
                    531:        case 7:
                    532:                strlcpy(aep->name, AudioEulinear_be, sizeof(aep->name));
                    533:                aep->encoding = AUDIO_ENCODING_ULINEAR_BE;
                    534:                aep->precision = 16;
                    535:                aep->flags = AUDIO_ENCODINGFLAG_EMULATED;
                    536:                return (0);
                    537:        default:
                    538:                return (EINVAL);
                    539:        }
                    540: }
                    541:
                    542: int
                    543: zaudio_set_params(void *hdl, int setmode, int usemode,
                    544:     struct audio_params *play, struct audio_params *rec)
                    545: {
                    546:        struct zaudio_softc *sc = hdl;
                    547:
                    548:        if (setmode & AUMODE_PLAY) {
                    549:                play->factor = 1;
                    550:                play->sw_code = NULL;
                    551:                switch(play->encoding) {
                    552:                case AUDIO_ENCODING_ULAW:
                    553:                        switch (play->channels) {
                    554:                        case 1:
                    555:                                play->factor = 4;
                    556:                                play->sw_code = mulaw_to_slinear16_mts;
                    557:                                break;
                    558:                        case 2:
                    559:                                play->factor = 2;
                    560:                                play->sw_code = mulaw_to_slinear16;
                    561:                                break;
                    562:                        default:
                    563:                                return (EINVAL);
                    564:                        }
                    565:                        break;
                    566:                case AUDIO_ENCODING_SLINEAR_LE:
                    567:                        switch (play->precision) {
                    568:                        case 8:
                    569:                                switch (play->channels) {
                    570:                                case 1:
                    571:                                        play->factor = 4;
                    572:                                        play->sw_code = linear8_to_linear16_mts;
                    573:                                        break;
                    574:                                case 2:
                    575:                                        play->factor = 2;
                    576:                                        play->sw_code = linear8_to_linear16;
                    577:                                        break;
                    578:                                default:
                    579:                                        return (EINVAL);
                    580:                                }
                    581:                                break;
                    582:                        case 16:
                    583:                                switch (play->channels) {
                    584:                                case 1:
                    585:                                        play->factor = 2;
                    586:                                        play->sw_code = noswap_bytes_mts;
                    587:                                        break;
                    588:                                case 2:
                    589:                                        break;
                    590:                                default:
                    591:                                        return (EINVAL);
                    592:                                }
                    593:                                break;
                    594:                        default:
                    595:                                return (EINVAL);
                    596:                        }
                    597:                        break;
                    598:                case AUDIO_ENCODING_ULINEAR_LE:
                    599:                        switch (play->precision) {
                    600:                        case 8:
                    601:                                switch (play->channels) {
                    602:                                case 1:
                    603:                                        play->factor = 4;
                    604:                                        play->sw_code =
                    605:                                            ulinear8_to_linear16_mts;
                    606:                                        break;
                    607:                                case 2:
                    608:                                        play->factor = 2;
                    609:                                        play->sw_code = ulinear8_to_linear16;
                    610:                                        break;
                    611:                                default:
                    612:                                        return (EINVAL);
                    613:                                }
                    614:                                break;
                    615:                        case 16:
                    616:                                switch (play->channels) {
                    617:                                case 1:
                    618:                                        play->factor = 2;
                    619:                                        play->sw_code = change_sign16_mts;
                    620:                                        break;
                    621:                                case 2:
                    622:                                        play->sw_code = change_sign16;
                    623:                                        break;
                    624:                                default:
                    625:                                        return (EINVAL);
                    626:                                }
                    627:                                break;
                    628:                        default:
                    629:                                return (EINVAL);
                    630:                        }
                    631:                        break;
                    632:                case AUDIO_ENCODING_ALAW:
                    633:                        switch (play->channels) {
                    634:                        case 1:
                    635:                                play->factor = 4;
                    636:                                play->sw_code = alaw_to_slinear16_mts;
                    637:                        case 2:
                    638:                                play->factor = 2;
                    639:                                play->sw_code = alaw_to_slinear16;
                    640:                        default:
                    641:                                return (EINVAL);
                    642:                        }
                    643:                        break;
                    644:                case AUDIO_ENCODING_SLINEAR_BE:
                    645:                        switch (play->precision) {
                    646:                        case 8:
                    647:                                switch (play->channels) {
                    648:                                case 1:
                    649:                                        play->factor = 4;
                    650:                                        play->sw_code =
                    651:                                            linear8_to_linear16_mts;
                    652:                                        break;
                    653:                                case 2:
                    654:                                        play->factor = 2;
                    655:                                        play->sw_code = linear8_to_linear16;
                    656:                                        break;
                    657:                                default:
                    658:                                        return (EINVAL);
                    659:                                }
                    660:                                break;
                    661:                        case 16:
                    662:                                switch (play->channels) {
                    663:                                case 1:
                    664:                                        play->factor = 2;
                    665:                                        play->sw_code = swap_bytes_mts;
                    666:                                        break;
                    667:                                case 2:
                    668:                                        play->sw_code = swap_bytes;
                    669:                                        break;
                    670:                                default:
                    671:                                        return (EINVAL);
                    672:                                }
                    673:                                break;
                    674:                        default:
                    675:                                return (EINVAL);
                    676:                        }
                    677:                        break;
                    678:                case AUDIO_ENCODING_ULINEAR_BE:
                    679:                        switch (play->precision) {
                    680:                        case 8:
                    681:                                switch (play->channels) {
                    682:                                case 1:
                    683:                                        play->factor = 4;
                    684:                                        play->sw_code =
                    685:                                            ulinear8_to_linear16_mts;
                    686:                                        break;
                    687:                                case 2:
                    688:                                        play->factor = 2;
                    689:                                        play->sw_code = ulinear8_to_linear16;
                    690:                                        break;
                    691:                                default:
                    692:                                        return (EINVAL);
                    693:                                }
                    694:                                break;
                    695:                        case 16:
                    696:                                switch (play->channels) {
                    697:                                case 1:
                    698:                                        play->factor = 2;
                    699:                                        play->sw_code =
                    700:                                            change_sign16_swap_bytes_mts;
                    701:                                        break;
                    702:                                case 2:
                    703:                                        play->sw_code =
                    704:                                            change_sign16_swap_bytes;
                    705:                                        break;
                    706:                                default:
                    707:                                        return (EINVAL);
                    708:                                }
                    709:                                break;
                    710:                        default:
                    711:                                return (EINVAL);
                    712:                        }
                    713:                        break;
                    714:                default:
                    715:                        return (EINVAL);
                    716:                }
                    717:
                    718:                pxa2x0_i2s_setspeed(&sc->sc_i2s, &play->sample_rate);
                    719:        }
                    720:
                    721: #if RECORD_XXX_NOT_YET
                    722:        if (setmode & AUMODE_RECORD) {
                    723:                rec->factor = 1;
                    724:                rec->sw_code = NULL;
                    725:                switch(rec->encoding) {
                    726:                case AUDIO_ENCODING_ULAW:
                    727:                        rec->sw_code = ulinear8_to_mulaw;
                    728:                        break;
                    729:                case AUDIO_ENCODING_SLINEAR_LE:
                    730:                        if (rec->precision == 8)
                    731:                                rec->sw_code = change_sign8;
                    732:                        break;
                    733:                case AUDIO_ENCODING_ULINEAR_LE:
                    734:                        if (rec->precision == 16)
                    735:                                rec->sw_code = change_sign16;
                    736:                        break;
                    737:                case AUDIO_ENCODING_ALAW:
                    738:                        rec->sw_code = ulinear8_to_alaw;
                    739:                        break;
                    740:                case AUDIO_ENCODING_SLINEAR_BE:
                    741:                        if (rec->precision == 16)
                    742:                                rec->sw_code = swap_bytes;
                    743:                        else
                    744:                                rec->sw_code = change_sign8;
                    745:                        break;
                    746:                case AUDIO_ENCODING_ULINEAR_BE:
                    747:                        if (rec->precision == 16)
                    748:                                rec->sw_code = swap_bytes_change_sign16;
                    749:                        break;
                    750:                default:
                    751:                        return (EINVAL);
                    752:                }
                    753:
                    754:                pxa2x0_i2s_setspeed(sc, &rec->sample_rate);
                    755:        }
                    756: #endif
                    757:
                    758:        return (0);
                    759: }
                    760:
                    761: int
                    762: zaudio_halt_output(void *hdl)
                    763: {
                    764:        struct zaudio_softc *sc = hdl;
                    765:
                    766:        /* XXX forcibly stop output DMA? */
                    767:
                    768:        zaudio_standby(sc);
                    769:        sc->sc_playing = 0;
                    770:
                    771:        return 0;
                    772: }
                    773:
                    774: int
                    775: zaudio_halt_input(void *hdl)
                    776: {
                    777:        /* struct zaudio_softc *sc = hdl; */
                    778:
                    779:        return 0;
                    780: }
                    781:
                    782: int
                    783: zaudio_getdev(void *hdl, struct audio_device *ret)
                    784: {
                    785:        /* struct zaudio_softc *sc = hdl; */
                    786:
                    787:        *ret = wm8750_device;
                    788:        return 0;
                    789: }
                    790:
                    791: #define ZAUDIO_SPKR_LVL                0
                    792: #define ZAUDIO_SPKR_MUTE       1
                    793: #define ZAUDIO_HP_LVL          2
                    794: #define ZAUDIO_HP_MUTE         3
                    795: #define ZAUDIO_OUTPUT_CLASS    4
                    796:
                    797: int
                    798: zaudio_set_port(void *hdl, struct mixer_ctrl *mc)
                    799: {
                    800:        struct zaudio_softc *sc = hdl;
                    801:        int error = EINVAL, s;
                    802:
                    803:        s = splbio();
                    804:        pxa2x0_i2c_open(&sc->sc_i2c);
                    805:
                    806:        switch (mc->dev) {
                    807:        case ZAUDIO_SPKR_LVL:
                    808:                if (mc->type != AUDIO_MIXER_VALUE)
                    809:                        break;
                    810:                if (mc->un.value.num_channels == 1)
                    811:                        sc->sc_volume[ZAUDIO_OP_SPKR].left =
                    812:                            mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                    813:                else
                    814:                        break;
                    815:                zaudio_update_volume(sc, ZAUDIO_OP_SPKR);
                    816:                error = 0;
                    817:                break;
                    818:        case ZAUDIO_SPKR_MUTE:
                    819:                if (mc->type != AUDIO_MIXER_ENUM)
                    820:                        break;
                    821:                sc->sc_unmute[ZAUDIO_OP_SPKR] = mc->un.ord ? 1 : 0;
                    822:                zaudio_update_mutes(sc);
                    823:                error = 0;
                    824:                break;
                    825:        case ZAUDIO_HP_LVL:
                    826:                if (mc->type != AUDIO_MIXER_VALUE)
                    827:                        break;
                    828:                if (mc->un.value.num_channels == 1) {
                    829:                        sc->sc_volume[ZAUDIO_OP_HP].left =
                    830:                            mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                    831:                        sc->sc_volume[ZAUDIO_OP_HP].right =
                    832:                            mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
                    833:                } else if (mc->un.value.num_channels == 2) {
                    834:                        sc->sc_volume[ZAUDIO_OP_HP].left =
                    835:                            mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
                    836:                        sc->sc_volume[ZAUDIO_OP_HP].right =
                    837:                            mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT];
                    838:                }
                    839:                else
                    840:                        break;
                    841:                zaudio_update_volume(sc, ZAUDIO_OP_HP);
                    842:                error = 0;
                    843:                break;
                    844:        case ZAUDIO_HP_MUTE:
                    845:                if (mc->type != AUDIO_MIXER_ENUM)
                    846:                        break;
                    847:                sc->sc_unmute[ZAUDIO_OP_HP] = mc->un.ord ? 1 : 0;
                    848:                zaudio_update_mutes(sc);
                    849:                error = 0;
                    850:                break;
                    851:        }
                    852:
                    853:        pxa2x0_i2c_close(&sc->sc_i2c);
                    854:        splx(s);
                    855:
                    856:        return error;
                    857: }
                    858:
                    859: int
                    860: zaudio_get_port(void *hdl, struct mixer_ctrl *mc)
                    861: {
                    862:        struct zaudio_softc *sc = hdl;
                    863:        int error = EINVAL;
                    864:
                    865:        switch (mc->dev) {
                    866:        case ZAUDIO_SPKR_LVL:
                    867:                if (mc->type != AUDIO_MIXER_VALUE)
                    868:                        break;
                    869:                if (mc->un.value.num_channels == 1)
                    870:                        mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                    871:                            sc->sc_volume[ZAUDIO_OP_SPKR].left;
                    872:                else
                    873:                        break;
                    874:                error = 0;
                    875:                break;
                    876:        case ZAUDIO_SPKR_MUTE:
                    877:                if (mc->type != AUDIO_MIXER_ENUM)
                    878:                        break;
                    879:                mc->un.ord = sc->sc_unmute[ZAUDIO_OP_SPKR] ? 1 : 0;
                    880:                error = 0;
                    881:                break;
                    882:        case ZAUDIO_HP_LVL:
                    883:                if (mc->type != AUDIO_MIXER_VALUE)
                    884:                        break;
                    885:                if (mc->un.value.num_channels == 1)
                    886:                        mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] =
                    887:                            sc->sc_volume[ZAUDIO_OP_HP].left;
                    888:                else if (mc->un.value.num_channels == 2) {
                    889:                        mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] =
                    890:                            sc->sc_volume[ZAUDIO_OP_HP].left;
                    891:                        mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] =
                    892:                            sc->sc_volume[ZAUDIO_OP_HP].right;
                    893:                }
                    894:                else
                    895:                        break;
                    896:                error = 0;
                    897:                break;
                    898:        case ZAUDIO_HP_MUTE:
                    899:                if (mc->type != AUDIO_MIXER_ENUM)
                    900:                        break;
                    901:                mc->un.ord = sc->sc_unmute[ZAUDIO_OP_HP] ? 1 : 0;
                    902:                error = 0;
                    903:                break;
                    904:        }
                    905:
                    906:        return error;
                    907: }
                    908:
                    909: int
                    910: zaudio_query_devinfo(void *hdl, struct mixer_devinfo *di)
                    911: {
                    912:        /* struct zaudio_softc *sc = hdl; */
                    913:
                    914:        switch (di->index) {
                    915:        case ZAUDIO_SPKR_LVL:
                    916:                di->type = AUDIO_MIXER_VALUE;
                    917:                di->mixer_class = ZAUDIO_OUTPUT_CLASS;
                    918:                di->prev = AUDIO_MIXER_LAST;
                    919:                di->next = ZAUDIO_SPKR_MUTE;
                    920:                strlcpy(di->label.name, AudioNspeaker,
                    921:                    sizeof(di->label.name));
                    922:                strlcpy(di->un.v.units.name, AudioNvolume,
                    923:                    sizeof(di->un.v.units.name));
                    924:                di->un.v.num_channels = 1;
                    925:                break;
                    926:        case ZAUDIO_SPKR_MUTE:
                    927:                di->type = AUDIO_MIXER_ENUM;
                    928:                di->mixer_class = ZAUDIO_OUTPUT_CLASS;
                    929:                di->prev = ZAUDIO_SPKR_LVL;
                    930:                di->next = AUDIO_MIXER_LAST;
                    931:                goto mute;
                    932:        case ZAUDIO_HP_LVL:
                    933:                di->type = AUDIO_MIXER_VALUE;
                    934:                di->mixer_class = ZAUDIO_OUTPUT_CLASS;
                    935:                di->prev = AUDIO_MIXER_LAST;
                    936:                di->next = ZAUDIO_HP_MUTE;
                    937:                strlcpy(di->label.name, AudioNheadphone,
                    938:                    sizeof(di->label.name));
                    939:                di->un.v.num_channels = 1;
                    940:                strlcpy(di->un.v.units.name, AudioNvolume,
                    941:                    sizeof(di->un.v.units.name));
                    942:                break;
                    943:        case ZAUDIO_HP_MUTE:
                    944:                di->type = AUDIO_MIXER_ENUM;
                    945:                di->mixer_class = ZAUDIO_OUTPUT_CLASS;
                    946:                di->prev = ZAUDIO_HP_LVL;
                    947:                di->next = AUDIO_MIXER_LAST;
                    948: mute:
                    949:                strlcpy(di->label.name, AudioNmute, sizeof(di->label.name));
                    950:                di->un.e.num_mem = 2;
                    951:                strlcpy(di->un.e.member[0].label.name, AudioNon,
                    952:                    sizeof(di->un.e.member[0].label.name));
                    953:                di->un.e.member[0].ord = 0;
                    954:                strlcpy(di->un.e.member[1].label.name, AudioNoff,
                    955:                    sizeof(di->un.e.member[1].label.name));
                    956:                di->un.e.member[1].ord = 1;
                    957:                break;
                    958:        case ZAUDIO_OUTPUT_CLASS:
                    959:                di->type = AUDIO_MIXER_CLASS;
                    960:                di->mixer_class = ZAUDIO_OUTPUT_CLASS;
                    961:                di->prev = AUDIO_MIXER_LAST;
                    962:                di->next = AUDIO_MIXER_LAST;
                    963:                strlcpy(di->label.name, AudioCoutputs,
                    964:                    sizeof(di->label.name));
                    965:                break;
                    966:        default:
                    967:                return ENXIO;
                    968:        }
                    969:
                    970:        return 0;
                    971: }
                    972:
                    973: int
                    974: zaudio_get_props(void *hdl)
                    975: {
                    976:        return AUDIO_PROP_MMAP | AUDIO_PROP_INDEPENDENT | AUDIO_PROP_FULLDUPLEX;
                    977: }
                    978:
                    979: int
                    980: zaudio_start_output(void *hdl, void *block, int bsize, void (*intr)(void *),
                    981:     void *intrarg)
                    982: {
                    983:        struct zaudio_softc *sc = hdl;
                    984:        int err;
                    985:
                    986:        /* Power up codec if we are not already playing. */
                    987:        if (!sc->sc_playing) {
                    988:                sc->sc_playing = 1;
                    989:                zaudio_play_setup(sc);
                    990:        }
                    991:
                    992:        /* Start DMA via I2S */
                    993:        err = pxa2x0_i2s_start_output(&sc->sc_i2s, block, bsize, intr, intrarg);
                    994:        if (err) {
                    995:                zaudio_standby(sc);
                    996:                sc->sc_playing = 0;
                    997:        }
                    998:        return err;
                    999: }
                   1000:
                   1001: int
                   1002: zaudio_start_input(void *hdl, void *block, int bsize, void (*intr)(void *),
                   1003:     void *intrarg)
                   1004: {
                   1005:        return ENXIO;
                   1006: }

CVSweb