int buf_pop (circbuf_t * buf, char *dest, unsigned int len)
{
    unsigned int i;
    char *p = buf->top;
    char *end = buf->end;
    char *data = buf->data;
    char *q = dest;
    //u32 dma_con = 0;

    if (len == 0)
        return 0;

    /* Cap to number of bytes in buffer */
    if (len > buf->size)
        len = buf->size;

#if 0
    /* dma setting */
    __raw_writel (p, DMA_SRC (USB_FULL_DMA1_BASE));     /* SOURCE */
    __raw_writel (dest, DMA_DST (USB_FULL_DMA1_BASE));  /* DESTINATION */
    __raw_writel (end - p, DMA_WPPT (USB_FULL_DMA1_BASE));      /* wrapping point */
    __raw_writel (data, DMA_WPTO (USB_FULL_DMA1_BASE)); /* wrapping destination */

    __raw_writel (len, DMA_COUNT (USB_FULL_DMA1_BASE));
    dma_con = DMA_CON_WPEN | DMA_CON_BURST_16BEAT | DMA_CON_SINC
        | DMA_CON_DINC | DMA_CON_SIZE_BYTE;
    __raw_writel (dma_con, DMA_CON (USB_FULL_DMA1_BASE));

    __raw_writel (DMA_START_BIT, DMA_START (USB_FULL_DMA1_BASE));
    //printf("USB DMA Start!\n");
    while (__raw_readl (DMA_GLBSTA_L) & DMA_GLBSTA_RUN (1));
    //printf("USB DMA Complete\n");
    __raw_writel (DMA_STOP_BIT, DMA_START (USB_FULL_DMA1_BASE));
    __raw_writel (DMA_ACKINT_BIT, DMA_ACKINT (USB_FULL_DMA1_BASE));

    p += len;
    if (p >= end)
        p = data + (p - end);
#else
    for (i = 0; i < len; i++)
    {
        *q = *p;
        p++;
        if (p == end)
            p = data;
        q++;
    }
#endif

    /* Update 'top' pointer */
    buf->top = p;
    buf->size -= len;

    return len;
}
int buf_push (circbuf_t * buf, const char *src, unsigned int len)
{
    /* NOTE:  this function allows push to overwrite old data. */
    unsigned int i;
    //u32 dma_con = 0;
    char *p = buf->tail;
    char *end = buf->end;
    char *data = buf->data;
    char *q = (char *)src;
#if 0
    /* dma setting */
    __raw_writel (src, DMA_SRC (USB_FULL_DMA0_BASE));   /* source */
    __raw_writel (p, DMA_DST (USB_FULL_DMA0_BASE));     /* destination */
    __raw_writel (end - p, DMA_WPPT (USB_FULL_DMA0_BASE));      /* wrapping point */
    __raw_writel (data, DMA_WPTO (USB_FULL_DMA0_BASE)); /* wrapping destination */


    __raw_writel (len, DMA_COUNT (USB_FULL_DMA0_BASE));
    dma_con =
        DMA_CON_WPEN | DMA_CON_WPSD | DMA_CON_BURST_16BEAT | DMA_CON_SINC |
        DMA_CON_DINC | DMA_CON_SIZE_BYTE;

    __raw_writel (dma_con, DMA_CON (USB_FULL_DMA0_BASE));

    __raw_writel (DMA_START_BIT, DMA_START (USB_FULL_DMA0_BASE));
    //printf("USB DMA Start!\n");
    while (__raw_readl (DMA_GLBSTA_L) & DMA_GLBSTA_RUN (0));
    //printf("USB DMA Complete\n");
    __raw_writel (DMA_STOP_BIT, DMA_START (USB_FULL_DMA0_BASE));
    __raw_writel (DMA_ACKINT_BIT, DMA_ACKINT (USB_FULL_DMA0_BASE));

    p += len;
    if (p >= end)
    {
        p = data + (p - end);
    }
#else
    for (i = 0; i < len; i++)
    {
        *p = *q;
        p++;
        if (p == end)
            p = data;
        q++;
    }
#endif

    buf->size += len;

    /* Update 'tail' pointer */
    buf->tail = p;

    return len;
}
Beispiel #3
0
static void audio_process_dma(audio_stream_t *s)
{
	int ret;

	DPRINTK(__FUNCTION__ ": pending_frags = %d, usr_head = %d, dma_head = %d, dma_tail = %d, bytecount = %d, fragcount = %d\n",
		s->pending_frags, s->usr_head, s->dma_head, s->dma_tail, s->bytecount, s->fragcount);
	if (s->stopped)
		goto spin;

	if (s->dma_spinref > 0 && s->pending_frags) {
		s->dma_spinref = 0;
		DMA_CLEAR(s);
	}

	while (s->pending_frags) {
		audio_buf_t *b = &s->buffers[s->dma_head];
		u_int dma_size = s->fragsize - b->offset;
		if (dma_size > MAX_DMA_SIZE)
			dma_size = CUT_DMA_SIZE;
		ret = DMA_START(s, b->dma_addr + b->offset, dma_size);
		if (ret)
			return;
		b->dma_ref++;
		b->offset += dma_size;
		if (b->offset >= s->fragsize) {
			s->pending_frags--;
			if (++s->dma_head >= s->nbfrags)
				s->dma_head = 0;
		}
	}

spin:
	if (s->spin_idle) {
		int spincnt = 0;
		while (DMA_START(s, SPIN_ADDR, SPIN_SIZE) == 0)
			spincnt++;
		/*
		 * Note: if there is still a data buffer being
		 * processed then the ref count is negative.  This
		 * allows for the DMA termination to be accounted in
		 * the proper order.  Of course dma_spinref can't be
		 * greater than 0 if dma_ref is not 0 since we kill
		 * the spinning above as soon as there is real data to process.
		 */
		if (s->buffers && s->buffers[s->dma_tail].dma_ref)
			spincnt = -spincnt;
		s->dma_spinref += spincnt;
	}
}
Beispiel #4
0
static void audio_stop_dma(audio_stream_t *s)
{
	u_int pos;
	unsigned long flags;
	audio_buf_t *b;

	if (s->dma_spinref > 0 || !s->buffers)
		return;

	local_irq_save(flags);
	s->stopped = 1;
	DMA_STOP(s);
	pos = audio_get_dma_pos(s);
	DMA_CLEAR(s);
	if (s->spin_idle) {
		DMA_START(s, SPIN_ADDR, SPIN_SIZE);
		DMA_START(s, SPIN_ADDR, SPIN_SIZE);
		s->dma_spinref = 2;
	} else
		s->dma_spinref = 0;
	local_irq_restore(flags);

	/* back up pointers to be ready to restart from the same spot */
	while (s->dma_head != s->dma_tail) {
		b = &s->buffers[s->dma_head];
		if (b->dma_ref) {
			b->dma_ref = 0;
			b->offset = 0;
		}
		s->pending_frags++;
		if (s->dma_head == 0)
			s->dma_head = s->nbfrags;
		s->dma_head--;
	}
	b = &s->buffers[s->dma_head];
	if (b->dma_ref) {
		b->offset = pos;
		b->dma_ref = 0;
	}
}
Beispiel #5
0
int mt65xx_start_gdma(int channel)
{
    if ((channel < GDMA_START) || (channel >= (GDMA_START + NR_GDMA_CHANNEL))) {
        return -DMA_ERR_INVALID_CH;
    }else if (dma_ctrl[channel].in_use == 0) {
        return -DMA_ERR_CH_FREE;
    }

    writel(DMA_INT_FLAG_CLR_BIT, DMA_INT_FLAG(DMA_BASE_CH(channel)));
    mt65xx_reg_sync_writel(DMA_START_BIT, DMA_START(DMA_BASE_CH(channel)));

    return 0;
}
Beispiel #6
0
int mt65xx_stop_gdma(int channel)
{
    if (channel < GDMA_START) {
        return -DMA_ERR_INVALID_CH;
    }

    if (channel >= (GDMA_START + NR_GDMA_CHANNEL)) {
        return -DMA_ERR_INVALID_CH;
    }

    if (dma_ctrl[channel].in_use == 0) {
        return -DMA_ERR_CH_FREE;
    }

    writel(DMA_FLUSH_BIT, DMA_FLUSH(DMA_BASE_CH(channel)));
    while (readl(DMA_START(DMA_BASE_CH(channel))));
    writel(DMA_FLUSH_CLR_BIT, DMA_FLUSH(DMA_BASE_CH(channel)));
    mt65xx_reg_sync_writel(DMA_INT_FLAG_CLR_BIT, DMA_INT_FLAG(DMA_BASE_CH(channel)));

    return 0;
}