static paddr_t yds_mappage(void *addr, void *mem, off_t off, int prot) { struct yds_softc *sc; struct yds_dma *p; if (off < 0) return -1; sc = addr; p = yds_find_dma(sc, mem); if (p == NULL) return -1; return bus_dmamem_mmap(sc->sc_dmatag, p->segs, p->nsegs, off, prot, BUS_DMA_WAITOK); }
static void yds_dump_play_slot(struct yds_softc *sc, int bank) { int i, j; u_int32_t *p; u_int32_t num; struct yds_dma *dma; for (i = 0; i < N_PLAY_SLOTS; i++) { printf("pbankp[%d] = %p,", i*2, sc->pbankp[i*2]); printf("pbankp[%d] = %p\n", i*2+1, sc->pbankp[i*2+1]); } p = (u_int32_t*)sc->ptbl; for (i = 0; i < N_PLAY_SLOTS+1; i++) { printf("ptbl + %d:0x%x\n", i, *p); p++; } num = *(u_int32_t*)sc->ptbl; printf("num = %d\n", num); for (i = 0; i < num; i++) { p = (u_int32_t *)sc->pbankp[i]; dma = yds_find_dma(sc,(void *)p); for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t); j++) { printf(" 0x%02x: 0x%08x\n", (unsigned) (j * sizeof(u_int32_t)), (unsigned) *p++); } /* p = (u_int32_t *)sc->pbankp[i*2 + 1]; printf(" pbankp[%d] : %p\n", i*2 + 1, p); for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t); j++) { printf(" 0x%02x: 0x%08x\n", j * sizeof(u_int32_t), *p++); delay(1); } */ } }
int yds_trigger_input(void *addr, void *start, void *end, int blksize, void (*intr)(void *), void *arg, struct audio_params *param) { struct yds_softc *sc = addr; struct yds_dma *p; u_int srate, format; struct rec_slot_ctrl_bank *rsb; bus_addr_t s; size_t l; mtx_enter(&audio_lock); #ifdef DIAGNOSTIC if (sc->sc_rec.intr) panic("yds_trigger_input: already running"); #endif sc->sc_rec.intr = intr; sc->sc_rec.intr_arg = arg; sc->sc_rec.offset = 0; sc->sc_rec.blksize = blksize; DPRINTFN(1, ("yds_trigger_input: " "sc=%p start=%p end=%p blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); DPRINTFN(1, (" parameters: rate=%lu, precision=%u, channels=%u\n", param->sample_rate, param->precision, param->channels)); p = yds_find_dma(sc, start); if (!p) { printf("yds_trigger_input: bad addr %p\n", start); mtx_leave(&audio_lock); return (EINVAL); } sc->sc_rec.dma = p; s = DMAADDR(p); l = ((char *)end - (char *)start); sc->sc_rec.length = l; sc->sc_rec.factor = 1; if (param->channels == 2) sc->sc_rec.factor *= 2; if (param->precision != 8) sc->sc_rec.factor *= 2; rsb = &sc->rbank[0]; memset(rsb, 0, sizeof(*rsb)); rsb->pgbase = s; rsb->pgloopendadr = l; /* Seems all 4 banks must be set up... */ sc->rbank[1] = *rsb; sc->rbank[2] = *rsb; sc->rbank[3] = *rsb; YWRITE4(sc, YDS_ADC_IN_VOLUME, 0x3fff3fff); YWRITE4(sc, YDS_REC_IN_VOLUME, 0x3fff3fff); srate = 48000 * 4096 / param->sample_rate - 1; format = ((param->precision == 8 ? YDS_FORMAT_8BIT : 0) | (param->channels == 2 ? YDS_FORMAT_STEREO : 0)); DPRINTF(("srate=%d, format=%08x\n", srate, format)); #ifdef YDS_USE_REC_SLOT YWRITE4(sc, YDS_DAC_REC_VOLUME, 0x3fff3fff); YWRITE4(sc, YDS_P44_REC_VOLUME, 0x3fff3fff); YWRITE4(sc, YDS_MAPOF_REC, YDS_RECSLOT_VALID); YWRITE4(sc, YDS_REC_SAMPLE_RATE, srate); YWRITE4(sc, YDS_REC_FORMAT, format); #else YWRITE4(sc, YDS_MAPOF_REC, YDS_ADCSLOT_VALID); YWRITE4(sc, YDS_ADC_SAMPLE_RATE, srate); YWRITE4(sc, YDS_ADC_FORMAT, format); #endif /* Now the rec slot for the next frame is set up!! */ /* Sync record slot control data */ bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map, sc->rbankoff, sizeof(struct rec_slot_ctrl_bank)* N_REC_SLOT_CTRL* N_REC_SLOT_CTRL_BANK, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); /* Sync ring buffer */ bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize, BUS_DMASYNC_PREREAD); /* HERE WE GO!! */ YWRITE4(sc, YDS_MODE, YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2); mtx_leave(&audio_lock); return 0; }
int yds_trigger_output(void *addr, void *start, void *end, int blksize, void (*intr)(void *), void *arg, struct audio_params *param) #define P44 (sc->sc_flags & YDS_CAP_HAS_P44) { struct yds_softc *sc = addr; struct yds_dma *p; struct play_slot_ctrl_bank *psb; const u_int gain = 0x40000000; bus_addr_t s; size_t l; int i; int p44, channels; mtx_enter(&audio_lock); #ifdef DIAGNOSTIC if (sc->sc_play.intr) panic("yds_trigger_output: already running"); #endif sc->sc_play.intr = intr; sc->sc_play.intr_arg = arg; sc->sc_play.offset = 0; sc->sc_play.blksize = blksize; DPRINTFN(1, ("yds_trigger_output: sc=%p start=%p end=%p " "blksize=%d intr=%p(%p)\n", addr, start, end, blksize, intr, arg)); p = yds_find_dma(sc, start); if (!p) { printf("yds_trigger_output: bad addr %p\n", start); mtx_leave(&audio_lock); return (EINVAL); } sc->sc_play.dma = p; #ifdef DIAGNOSTIC { u_int32_t ctrlsize; if ((ctrlsize = YREAD4(sc, YDS_PLAY_CTRLSIZE)) != sizeof(struct play_slot_ctrl_bank) / sizeof(u_int32_t)) panic("%s: invalid play slot ctrldata %d %d", sc->sc_dev.dv_xname, ctrlsize, sizeof(struct play_slot_ctrl_bank)); } #endif #ifdef YDS_USE_P44 /* The document says the P44 SRC supports only stereo, 16bit PCM. */ if (P44) p44 = ((param->sample_rate == 44100) && (param->channels == 2) && (param->precision == 16)); else #endif p44 = 0; channels = p44 ? 1 : param->channels; s = DMAADDR(p); l = ((char *)end - (char *)start); sc->sc_play.length = l; *sc->ptbl = channels; /* Num of play */ sc->sc_play.factor = 1; if (param->channels == 2) sc->sc_play.factor *= 2; if (param->precision != 8) sc->sc_play.factor *= 2; l /= sc->sc_play.factor; psb = sc->pbankp[0]; memset(psb, 0, sizeof(*psb)); psb->format = ((channels == 2 ? PSLT_FORMAT_STEREO : 0) | (param->precision == 8 ? PSLT_FORMAT_8BIT : 0) | (p44 ? PSLT_FORMAT_SRC441 : 0)); psb->pgbase = s; psb->pgloopend = l; if (!p44) { psb->pgdeltaend = (param->sample_rate * 65536 / 48000) << 12; psb->lpfkend = yds_get_lpfk(param->sample_rate); psb->eggainend = gain; psb->lpfq = yds_get_lpfq(param->sample_rate); psb->pgdelta = psb->pgdeltaend; psb->lpfk = yds_get_lpfk(param->sample_rate); psb->eggain = gain; } for (i = 0; i < channels; i++) { /* i == 0: left or mono, i == 1: right */ psb = sc->pbankp[i*2]; if (i) /* copy from left */ *psb = *(sc->pbankp[0]); if (channels == 2) { /* stereo */ if (i == 0) { psb->lchgain = psb->lchgainend = gain; } else { psb->lchgain = psb->lchgainend = 0; psb->rchgain = psb->rchgainend = gain; psb->format |= PSLT_FORMAT_RCH; } } else if (!p44) { /* mono */ psb->lchgain = psb->rchgain = gain; psb->lchgainend = psb->rchgainend = gain; } /* copy to the other bank */ *(sc->pbankp[i*2+1]) = *psb; } YDS_DUMP_PLAY_SLOT(5, sc, 0); YDS_DUMP_PLAY_SLOT(5, sc, 1); if (p44) YWRITE4(sc, YDS_P44_OUT_VOLUME, 0x3fff3fff); else YWRITE4(sc, YDS_DAC_OUT_VOLUME, 0x3fff3fff); /* Now the play slot for the next frame is set up!! */ /* Sync play slot control data for both directions */ bus_dmamap_sync(sc->sc_dmatag, sc->sc_ctrldata.map, sc->ptbloff, sizeof(struct play_slot_ctrl_bank) * channels * N_PLAY_SLOT_CTRL_BANK, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD); /* Sync ring buffer */ bus_dmamap_sync(sc->sc_dmatag, p->map, 0, blksize, BUS_DMASYNC_PREWRITE); /* HERE WE GO!! */ YWRITE4(sc, YDS_MODE, YREAD4(sc, YDS_MODE) | YDS_MODE_ACTV | YDS_MODE_ACTV2); mtx_leave(&audio_lock); return 0; }