예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
0
파일: yds.c 프로젝트: ryoon/netbsd-xhci
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++);
		}
	}
}
예제 #5
0
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;
}
예제 #6
0
파일: vcore.c 프로젝트: 99years/plan9
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;
}
예제 #7
0
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;
}
예제 #8
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;
}
예제 #9
0
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;
}
예제 #10
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;
}
예제 #11
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;
}
예제 #12
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;
}
예제 #13
0
파일: dma.c 프로젝트: carriercomm/plan9-gpl
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);
}