/* * vs interrupt handler */ static int vs_dmaintr(void *hdl) { struct vs_softc *sc; DPRINTF(2, ("vs_dmaintr\n")); sc = hdl; mutex_spin_enter(&sc->sc_intr_lock); if (sc->sc_pintr) { /* start next transfer */ sc->sc_current.dmap += sc->sc_current.blksize; if (sc->sc_current.dmap + sc->sc_current.blksize > sc->sc_current.bufsize) sc->sc_current.dmap -= sc->sc_current.bufsize; dmac_start_xfer_offset(sc->sc_dma_ch->ch_softc, sc->sc_current.xfer, sc->sc_current.dmap, sc->sc_current.blksize); sc->sc_pintr(sc->sc_parg); } else if (sc->sc_rintr) { /* start next transfer */ sc->sc_current.dmap += sc->sc_current.blksize; if (sc->sc_current.dmap + sc->sc_current.blksize > sc->sc_current.bufsize) sc->sc_current.dmap -= sc->sc_current.bufsize; dmac_start_xfer_offset(sc->sc_dma_ch->ch_softc, sc->sc_current.xfer, sc->sc_current.dmap, sc->sc_current.blksize); sc->sc_rintr(sc->sc_rarg); } else { printf("vs_dmaintr: spurious interrupt\n"); } mutex_spin_exit(&sc->sc_intr_lock); return 1; }
static int vs_trigger_output(void *hdl, void *start, void *end, int bsize, void (*intr)(void *), void *arg, const audio_params_t *p) { struct vs_softc *sc; struct vs_dma *vd; struct dmac_dma_xfer *xf; struct dmac_channel_stat *chan; DPRINTF(2, ("vs_trigger_output: start=%p, bsize=%d, intr=%p, arg=%p\n", start, bsize, intr, arg)); sc = hdl; chan = sc->sc_dma_ch; sc->sc_pintr = intr; sc->sc_parg = arg; sc->sc_current.blksize = bsize; sc->sc_current.bufsize = (char *)end - (char *)start; sc->sc_current.dmap = 0; /* Find DMA buffer. */ for (vd = sc->sc_dmas; vd != NULL && KVADDR(vd) != start; vd = vd->vd_next) continue; if (vd == NULL) { printf("%s: trigger_output: bad addr %p\n", device_xname(sc->sc_dev), start); return EINVAL; } vs_set_sr(sc, sc->sc_current.prate); vs_set_po(sc, VS_PANOUT_LR); xf = dmac_alloc_xfer(chan, sc->sc_dmat, vd->vd_map); sc->sc_current.xfer = xf; chan->ch_dcr = (DMAC_DCR_XRM_CSWOH | DMAC_DCR_OTYP_EASYNC | DMAC_DCR_OPS_8BIT); chan->ch_ocr = DMAC_OCR_REQG_EXTERNAL; xf->dx_ocr = DMAC_OCR_DIR_MTD; xf->dx_scr = DMAC_SCR_MAC_COUNT_UP | DMAC_SCR_DAC_NO_COUNT; xf->dx_device = sc->sc_addr + MSM6258_DATA*2 + 1; dmac_load_xfer(chan->ch_softc, xf); dmac_start_xfer_offset(chan->ch_softc, xf, 0, sc->sc_current.blksize); bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSM6258_STAT, 2); return 0; }
/* * Do the actual transfer. */ int dmac_start_xfer(struct dmac_softc *dmac, struct dmac_dma_xfer *xf) { return dmac_start_xfer_offset(dmac, xf, 0, 0); }