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; }
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; } }
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; } }
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; }
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; }