static int auacer_trigger_output(void *v, void *start, void *end, int blksize, void (*intr)(void *), void *arg, const audio_params_t *param) { struct auacer_softc *sc; struct auacer_dma *p; uint32_t size; DPRINTF(ALI_DEBUG_DMA, ("auacer_trigger_output(%p, %p, %d, %p, %p, %p)\n", start, end, blksize, intr, arg, param)); sc = v; for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) continue; if (!p) { printf("auacer_trigger_output: bad addr %p\n", start); return (EINVAL); } size = (char *)end - (char *)start; auacer_setup_chan(sc, &sc->sc_pcmo, DMAADDR(p), size, blksize, intr, arg); return 0; }
static int auich_trigger_input(void *v, void *start, void *end, int blksize, void (*intr)(void *), void *arg, const audio_params_t *param) { struct auich_softc *sc; struct auich_dma *p; size_t size; DPRINTF(ICH_DEBUG_DMA, ("auich_trigger_input(%p, %p, %d, %p, %p, %p)\n", start, end, blksize, intr, arg, param)); sc = v; for (p = sc->sc_dmas; p && KERNADDR(p) != start; p = p->next) continue; if (!p) { printf("auich_trigger_input: bad addr %p\n", start); return EINVAL; } size = (size_t)((char *)end - (char *)start); sc->pcmi.intr = intr; sc->pcmi.arg = arg; sc->pcmi.start = DMAADDR(p); sc->pcmi.p = sc->pcmi.start; sc->pcmi.end = sc->pcmi.start + size; sc->pcmi.blksize = blksize; bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR, sc->sc_cddma + ICH_PCMI_OFF(0)); auich_trigger_pipe(sc, ICH_PCMI, &sc->pcmi); return 0; }
static int saa7231_ts2dtl_run_prepare(struct saa7231_stream *stream) { unsigned long run = 0; u32 delay; u32 reg; struct saa7231_dev *saa7231 = stream->saa7231; struct saa7231_dtl *dtl = &stream->dtl; struct saa7231_ring *ring = stream->ring; struct saa7231_dmabuf *dmabuf = ring->dmabuf; u32 module = dtl->module; int port = stream->port_id; int ch = DMACH(port); SAA7231_WR(DMAADDR(0, port, dmabuf, 0), SAA7231_BAR0, module, S2D_CHx_B0_B_START_ADDRESS(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 1), SAA7231_BAR0, module, S2D_CHx_B1_B_START_ADDRESS(0)); reg = SAA7231_RD(SAA7231_BAR0, MMU, MMU_DMA_CONFIG(ch)); reg &= ~0x40; SAA7231_WR(reg, SAA7231_BAR0, MMU, MMU_DMA_CONFIG(ch)); SAA7231_WR((reg | 0x40), SAA7231_BAR0, MMU, MMU_DMA_CONFIG(ch)); dtl->addr_prev = 0xffffff; delay = 1000; do { if (!run) { msleep(10); delay--; } run = SAA7231_RD(SAA7231_BAR0, MMU, MMU_DMA_CONFIG(ch)) & 0x80; } while (!run && delay); if (!run) { dprintk(SAA7231_ERROR, 1, "ERROR, Preload PTA failed"); return -EINVAL; } #if 0 reg = SAA7231_RD(SAA7231_BAR0, module, S2D_CHx_CTRL(0)); SAA7231_WR(reg | 0x1, SAA7231_BAR0, module, S2D_CHx_CTRL(0)); #endif return 0; }
static void yds_dump_play_slot(struct yds_softc *sc, int bank) { int i, j; uint32_t *p; uint32_t num; bus_addr_t pa; 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]); } pa = DMAADDR(&sc->sc_ctrldata) + sc->pbankoff; p = sc->ptbl; printf("ptbl + 0: %d\n", *p++); for (i = 0; i < N_PLAY_SLOTS; i++) { printf("ptbl + %d: %#x, should be %#" PRIxPADDR "\n", i+1, *p, pa + i * sizeof(struct play_slot_ctrl_bank) * N_PLAY_SLOT_CTRL_BANK); p++; } num = le32toh(*(uint32_t*)sc->ptbl); printf("numofplay = %d\n", num); for (i = 0; i < num; i++) { p = (uint32_t *)sc->pbankp[i*2]; printf(" pbankp[%d], bank 0 : %p\n", i*2, p); for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / sizeof(uint32_t); j++) { printf(" 0x%02x: 0x%08x\n", (unsigned)(j * sizeof(uint32_t)), (unsigned)*p++); } p = (uint32_t *)sc->pbankp[i*2 + 1]; printf(" pbankp[%d], bank 1 : %p\n", i*2 + 1, p); for (j = 0; j < sizeof(struct play_slot_ctrl_bank) / sizeof(uint32_t); j++) { printf(" 0x%02x: 0x%08x\n", (unsigned)(j * sizeof(uint32_t)), (unsigned)*p++); } } }
static int coram_risc_field(struct coram_softc *sc, uint32_t *rm, uint32_t bpl) { struct coram_dma *p; for (p = sc->sc_dma; p && KERNADDR(p) != sc->sc_tsbuf; p = p->next) continue; if (p == NULL) { printf("%s: coram_risc_field: bad addr %p\n", device_xname(sc->sc_dev), sc->sc_tsbuf); return ENOENT; } memset(sc->sc_riscbuf, 0, sc->sc_riscbufsz); rm = sc->sc_riscbuf; /* htole32 will be done when program is copied to chip sram */ /* XXX */ *(rm++) = (CX_RISC_SYNC|0); *(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ1|bpl); *(rm++) = (DMAADDR(p) + 0 * bpl); *(rm++) = 0; /* high dword */ *(rm++) = (CX_RISC_WRITE|CX_RISC_SOL|CX_RISC_EOL|CX_RISC_IRQ2|bpl); *(rm++) = (DMAADDR(p) + 1 * bpl); *(rm++) = 0; *(rm++) = (CX_RISC_JUMP|1); *(rm++) = (coram_sram_chs[CORAM_SRAM_CH6].csc_risc + 4); *(rm++) = 0; return 0; }
void* fbinit(int set, int *width, int *height, int *depth) { Fbinfo *fi; uintptr va; if(!set) fbdefault(width, height, depth); /* Screen width must be a multiple of 16 */ *width &= ~0xF; fi = (Fbinfo*)(VCBUFFER); memset(fi, 0, sizeof(*fi)); fi->xres = fi->xresvirtual = *width; fi->yres = fi->yresvirtual = *height; fi->bpp = *depth; cachedwbinvse(fi, sizeof(*fi)); vcwrite(ChanFb, DMAADDR(fi)); if(vcread(ChanFb) != 0) return 0; va = mmukmap(FRAMEBUFFER, PADDR(fi->base), fi->screensize); if(va) memset((char*)va, 0x7F, fi->screensize); return (void*)va; }
static int saa7231_ts2dtl_setparams(struct saa7231_stream *stream) { struct saa7231_dev *saa7231 = stream->saa7231; struct saa7231_dtl *dtl = &stream->dtl; struct stream_params *params = &stream->params; struct saa7231_ring *ring = stream->ring; struct saa7231_dmabuf *dmabuf = ring->dmabuf; u32 module = dtl->module; int port = stream->port_id; int id; u32 buf_size = params->pitch * params->lines; u32 stride = 0; u32 x_length = 0; u32 y_length = 0; u32 block_control; u32 channel_control; switch (port) { case STREAM_PORT_TS2D_DTV0: SAA7231_WR(0x1, SAA7231_BAR0, STREAM, STREAM_RA_TS0_LOC_CLGATE); break; case STREAM_PORT_TS2D_DTV1: SAA7231_WR(0x1, SAA7231_BAR0, STREAM, STREAM_RA_TS1_LOC_CLGATE); break; case STREAM_PORT_TS2D_EXTERN0: SAA7231_WR(stream->clk, SAA7231_BAR0, STREAM, STREAM_RA_TS0_EXT_CLGATE); SAA7231_WR((stream->config & 0x7f), SAA7231_BAR0, STREAM, STREAM_RA_PS2P_0_EXT_CFG); break; case STREAM_PORT_TS2D_EXTERN1: SAA7231_WR(stream->clk, SAA7231_BAR0, STREAM, STREAM_RA_TS1_EXT_CLGATE); SAA7231_WR((stream->config & 0x7f), SAA7231_BAR0, STREAM, STREAM_RA_PS2P_1_EXT_CFG); break; case STREAM_PORT_TS2D_CAM: SAA7231_WR(0x1, SAA7231_BAR0, STREAM, STREAM_RA_TSCA_EXT_CLGATE); SAA7231_WR((stream->config & 0x7f), SAA7231_BAR0, STREAM, STREAM_RA_PS2P_CA_EXT_CFG); SAA7231_WR(0x1, SAA7231_BAR0, STREAM, STREAM_RA_TSMUX_CLGATE); SAA7231_WR(((stream->config >> 7) & 0x1ff), SAA7231_BAR0, STREAM, STREAM_RA_TS_OUT_CONFIG); SAA7231_WR(dtl->cur_input, SAA7231_BAR0, STREAM, STREAM_RA_TS_SEL); break; default: dprintk(SAA7231_ERROR, 1, "Invalid port: 0x%02x", stream->port_id); return -EINVAL; } SAA7231_WR(0x1, SAA7231_BAR0, module, S2D_SW_RST); saa7231_init_ptables(stream); id = SAA7231_RD(SAA7231_BAR0, module, S2D_MODULE_ID); if (params->type != STREAM_TS) return -EINVAL; stride = params->pitch; x_length = params->pitch; y_length = params->lines; block_control = 0; SAA7231_SETFIELD(block_control, S2D_CHx_B0_CTRL_DFOT, 0x1); SAA7231_SETFIELD(block_control, S2D_CHx_B0_CTRL_BTAG, 0x0); channel_control = 0x29c; if ((id & ~0x00000F00) != 0xA0B11000) dprintk(SAA7231_ERROR, 1, "ERROR: TS Module ID: 0x%02x unsupported",id); SAA7231_WR(0x0, SAA7231_BAR0, module, S2D_S2D_CTRL); SAA7231_WR(0x0, SAA7231_BAR0, module, S2D_CFG_CTRL); SAA7231_WR((TS2D_BUFFERS - 1), SAA7231_BAR0, module, S2D_S2D_MAX_B_START); SAA7231_WR(0x2, SAA7231_BAR0, module, S2D_CLK_GATING); SAA7231_WR(block_control, SAA7231_BAR0, module, S2D_CHx_B0_CTRL(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 0), SAA7231_BAR0, module, S2D_CHx_B0_B_START_ADDRESS(0)); SAA7231_WR(buf_size, SAA7231_BAR0, module, S2D_CHx_B0_B_LENGTH(0)); SAA7231_WR(stride, SAA7231_BAR0, module, S2D_CHx_B0_STRIDE(0)); SAA7231_WR(x_length, SAA7231_BAR0, module, S2D_CHx_B0_X_LENGTH(0)); SAA7231_WR(y_length, SAA7231_BAR0, module, S2D_CHx_B0_Y_LENGTH(0)); SAA7231_WR(block_control, SAA7231_BAR0, module, S2D_CHx_B1_CTRL(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 1), SAA7231_BAR0, module, S2D_CHx_B1_B_START_ADDRESS(0)); SAA7231_WR(buf_size, SAA7231_BAR0, module, S2D_CHx_B1_B_LENGTH(0)); SAA7231_WR(stride, SAA7231_BAR0, module, S2D_CHx_B1_STRIDE(0)); SAA7231_WR(x_length, SAA7231_BAR0, module, S2D_CHx_B1_X_LENGTH(0)); SAA7231_WR(y_length, SAA7231_BAR0, module, S2D_CHx_B1_Y_LENGTH(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 2), SAA7231_BAR0, module, S2D_CHx_B2_B_START_ADDRESS(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 3), SAA7231_BAR0, module, S2D_CHx_B3_B_START_ADDRESS(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 4), SAA7231_BAR0, module, S2D_CHx_B4_B_START_ADDRESS(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 5), SAA7231_BAR0, module, S2D_CHx_B5_B_START_ADDRESS(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 6), SAA7231_BAR0, module, S2D_CHx_B6_B_START_ADDRESS(0)); SAA7231_WR(DMAADDR(0, port, dmabuf, 7), SAA7231_BAR0, module, S2D_CHx_B7_B_START_ADDRESS(0)); SAA7231_WR(channel_control, SAA7231_BAR0, module, S2D_CHx_CTRL(0)); return 0; }
static int saa7231_ts2dtl_set_buffer(struct saa7231_stream *stream, u32 index, struct saa7231_dmabuf *dmabuf) { struct saa7231_dev *saa7231 = stream->saa7231; struct saa7231_dtl *dtl = &stream->dtl; u32 module = dtl->module; int port = stream->port_id; int ch = DMACH(port); int ret; switch (index) { case 0: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 0), SAA7231_BAR0, module, S2D_CHx_B0_B_START_ADDRESS(0)); break; case 1: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 1), SAA7231_BAR0, module, S2D_CHx_B1_B_START_ADDRESS(0)); break; case 2: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 2), SAA7231_BAR0, module, S2D_CHx_B2_B_START_ADDRESS(0)); break; case 3: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 3), SAA7231_BAR0, module, S2D_CHx_B3_B_START_ADDRESS(0)); break; case 4: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 4), SAA7231_BAR0, module, S2D_CHx_B4_B_START_ADDRESS(0)); break; case 5: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 5), SAA7231_BAR0, module, S2D_CHx_B5_B_START_ADDRESS(0)); break; case 6: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 6), SAA7231_BAR0, module, S2D_CHx_B6_B_START_ADDRESS(0)); break; case 7: SAA7231_WR(PTA_LSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(LSB, index, ch)); SAA7231_WR(PTA_MSB(dmabuf->pt_phys), SAA7231_BAR0, MMU, MMU_PTA(MSB, index, ch)); SAA7231_WR(DMAADDR(0, port, dmabuf, 7), SAA7231_BAR0, module, S2D_CHx_B7_B_START_ADDRESS(0)); break; default: dprintk(SAA7231_ERROR, 1, "Invalid Index:%d", index); ret = -EINVAL; goto exit; } exit: return ret; }
static int yds_allocate_slots(struct yds_softc *sc, int resuming) { size_t pcs, rcs, ecs, ws, memsize; void *mp; u_int32_t da; /* DMA address */ char *va; /* KVA */ off_t cb; int i; struct yds_dma *p; /* Alloc DSP Control Data */ pcs = YREAD4(sc, YDS_PLAY_CTRLSIZE) * sizeof(u_int32_t); rcs = YREAD4(sc, YDS_REC_CTRLSIZE) * sizeof(u_int32_t); ecs = YREAD4(sc, YDS_EFFECT_CTRLSIZE) * sizeof(u_int32_t); ws = WORK_SIZE; YWRITE4(sc, YDS_WORK_SIZE, ws / sizeof(u_int32_t)); DPRINTF(("play control size : %d\n", (unsigned int)pcs)); DPRINTF(("rec control size : %d\n", (unsigned int)rcs)); DPRINTF(("eff control size : %d\n", (unsigned int)ecs)); DPRINTF(("work size : %d\n", (unsigned int)ws)); #ifdef DIAGNOSTIC if (pcs != sizeof(struct play_slot_ctrl_bank)) { printf("%s: invalid play slot ctrldata %d != %d\n", sc->sc_dev.dv_xname, (unsigned int)pcs, (unsigned int)sizeof(struct play_slot_ctrl_bank)); } if (rcs != sizeof(struct rec_slot_ctrl_bank)) { printf("%s: invalid rec slot ctrldata %d != %d\n", sc->sc_dev.dv_xname, (unsigned int)rcs, (unsigned int)sizeof(struct rec_slot_ctrl_bank)); } #endif memsize = N_PLAY_SLOTS*N_PLAY_SLOT_CTRL_BANK*pcs + N_REC_SLOT_CTRL*N_REC_SLOT_CTRL_BANK*rcs + ws; memsize += (N_PLAY_SLOTS+1)*sizeof(u_int32_t); p = &sc->sc_ctrldata; if (!resuming) { i = yds_allocmem(sc, memsize, 16, p); if (i) { printf("%s: couldn't alloc/map DSP DMA buffer, reason %d\n", sc->sc_dev.dv_xname, i); free(p, M_DEVBUF); return 1; } } mp = KERNADDR(p); da = DMAADDR(p); DPRINTF(("mp:%p, DMA addr:%p\n", mp, (void *) sc->sc_ctrldata.map->dm_segs[0].ds_addr)); bzero(mp, memsize); /* Work space */ cb = 0; va = (u_int8_t*)mp; YWRITE4(sc, YDS_WORK_BASE, da + cb); cb += ws; /* Play control data table */ sc->ptbl = (u_int32_t *)(va + cb); sc->ptbloff = cb; YWRITE4(sc, YDS_PLAY_CTRLBASE, da + cb); cb += (N_PLAY_SLOT_CTRL + 1) * sizeof(u_int32_t); /* Record slot control data */ sc->rbank = (struct rec_slot_ctrl_bank *)(va + cb); YWRITE4(sc, YDS_REC_CTRLBASE, da + cb); sc->rbankoff = cb; cb += N_REC_SLOT_CTRL * N_REC_SLOT_CTRL_BANK * rcs; #if 0 /* Effect slot control data -- unused */ YWRITE4(sc, YDS_EFFECT_CTRLBASE, da + cb); cb += N_EFFECT_SLOT_CTRL * N_EFFECT_SLOT_CTRL_BANK * ecs; #endif /* Play slot control data */ sc->pbankoff = da + cb; for (i=0; i<N_PLAY_SLOT_CTRL; i++) { sc->pbankp[i*2] = (struct play_slot_ctrl_bank *)(va + cb); *(sc->ptbl + i+1) = da + cb; cb += pcs; sc->pbankp[i*2+1] = (struct play_slot_ctrl_bank *)(va + cb); cb += pcs; } /* Sync play control data table */ bus_dmamap_sync(sc->sc_dmatag, p->map, sc->ptbloff, (N_PLAY_SLOT_CTRL+1) * sizeof(u_int32_t), BUS_DMASYNC_PREWRITE); return 0; }
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; }
/* * Calibrate card (some boards are overclocked and need scaling) */ static void auich_calibrate(struct auich_softc *sc) { struct timeval t1, t2; uint8_t ociv, nciv; uint64_t wait_us; uint32_t actual_48k_rate, bytes, ac97rate; void *temp_buffer; struct auich_dma *p; u_int rate; /* * Grab audio from input for fixed interval and compare how * much we actually get with what we expect. Interval needs * to be sufficiently short that no interrupts are * generated. */ /* Force the codec to a known state first. */ sc->codec_if->vtbl->set_clock(sc->codec_if, 48000); rate = sc->sc_ac97_clock = 48000; sc->codec_if->vtbl->set_rate(sc->codec_if, AC97_REG_PCM_LR_ADC_RATE, &rate); /* Setup a buffer */ bytes = 64000; temp_buffer = auich_allocm(sc, AUMODE_RECORD, bytes); for (p = sc->sc_dmas; p && KERNADDR(p) != temp_buffer; p = p->next) continue; if (p == NULL) { printf("auich_calibrate: bad address %p\n", temp_buffer); return; } sc->pcmi.dmalist[0].base = DMAADDR(p); sc->pcmi.dmalist[0].len = (bytes >> sc->sc_sample_shift); /* * our data format is stereo, 16 bit so each sample is 4 bytes. * assuming we get 48000 samples per second, we get 192000 bytes/sec. * we're going to start recording with interrupts disabled and measure * the time taken for one block to complete. we know the block size, * we know the time in microseconds, we calculate the sample rate: * * actual_rate [bps] = bytes / (time [s] * 4) * actual_rate [bps] = (bytes * 1000000) / (time [us] * 4) * actual_rate [Hz] = (bytes * 250000) / time [us] */ /* prepare */ ociv = bus_space_read_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CIV); bus_space_write_4(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_BDBAR, sc->sc_cddma + ICH_PCMI_OFF(0)); bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_LVI, (0 - 1) & ICH_LVI_MASK); /* start */ kpreempt_disable(); microtime(&t1); bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RPBM); /* wait */ nciv = ociv; do { microtime(&t2); if (t2.tv_sec - t1.tv_sec > 1) break; nciv = bus_space_read_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CIV); } while (nciv == ociv); microtime(&t2); /* stop */ bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, 0); kpreempt_enable(); /* reset */ DELAY(100); bus_space_write_1(sc->iot, sc->aud_ioh, ICH_PCMI + ICH_CTRL, ICH_RR); /* turn time delta into us */ wait_us = ((t2.tv_sec - t1.tv_sec) * 1000000) + t2.tv_usec - t1.tv_usec; auich_freem(sc, temp_buffer, bytes); if (nciv == ociv) { printf("%s: ac97 link rate calibration timed out after %" PRIu64 " us\n", device_xname(sc->sc_dev), wait_us); return; } actual_48k_rate = (bytes * UINT64_C(250000)) / wait_us; if (actual_48k_rate < 50000) ac97rate = 48000; else ac97rate = ((actual_48k_rate + 500) / 1000) * 1000; aprint_verbose_dev(sc->sc_dev, "measured ac97 link rate at %d Hz", actual_48k_rate); if (ac97rate != actual_48k_rate) aprint_verbose(", will use %d Hz", ac97rate); aprint_verbose("\n"); sc->sc_ac97_clock = ac97rate; }
void dmastart(int chan, int dev, int dir, void *src, void *dst, int len) { Ctlr *ctlr; Cb *cb; int ti; ctlr = &dma[chan]; if(ctlr->regs == nil){ ctlr->regs = (u32int*)(DMAREGS + chan*Regsize); ctlr->cb = xspanalloc(sizeof(Cb), Cbalign, 0); assert(ctlr->cb != nil); dmaregs[Enable] |= 1<<chan; ctlr->regs[Cs] = Reset; while(ctlr->regs[Cs] & Reset) ; intrenable(IRQDMA(chan), dmainterrupt, ctlr, 0, "dma"); } cb = ctlr->cb; ti = 0; switch(dir){ case DmaD2M: cachedwbinvse(dst, len); ti = Srcdreq | Destinc; cb->sourcead = DMAIO(src); cb->destad = DMAADDR(dst); break; case DmaM2D: cachedwbse(src, len); ti = Destdreq | Srcinc; cb->sourcead = DMAADDR(src); cb->destad = DMAIO(dst); break; case DmaM2M: cachedwbse(src, len); cachedwbinvse(dst, len); ti = Srcinc | Destinc; cb->sourcead = DMAADDR(src); cb->destad = DMAADDR(dst); break; } cb->ti = ti | dev<<Permapshift | Inten; cb->txfrlen = len; cb->stride = 0; cb->nextconbk = 0; cachedwbse(cb, sizeof(Cb)); ctlr->regs[Cs] = 0; microdelay(1); ctlr->regs[Conblkad] = DMAADDR(cb); DBG print("dma start: %ux %ux %ux %ux %ux %ux\n", cb->ti, cb->sourcead, cb->destad, cb->txfrlen, cb->stride, cb->nextconbk); DBG print("intstatus %ux\n", dmaregs[Intstatus]); dmaregs[Intstatus] = 0; ctlr->regs[Cs] = Int; microdelay(1); coherence(); DBG dumpdregs("before Active", ctlr->regs); ctlr->regs[Cs] = Active; DBG dumpdregs("after Active", ctlr->regs); }