static void dma_callback(void) { dma_sub_addr += play_sub_size; dma_rem_size -= play_sub_size; play_sub_size = 0; /* Might get called again if locked */ if(locked) { play_callback_pending = is_playing; return; } if(!dma_rem_size) { pcm_play_get_more_callback(&dma_start_addr, &dma_start_size); if (!dma_start_size) return; dma_sub_addr = dma_start_addr; dma_rem_size = dma_start_size; /* force writeback */ commit_dcache_range(dma_start_addr, dma_start_size); play_start_pcm(); pcm_play_dma_started_callback(); } else { play_start_pcm(); } }
void DMA0(void) { unsigned long res = DSR0; void *start; size_t size; and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */ DSR0 = 1; /* Clear interrupt and errors */ if (res & 0x70) { logf("DMA0 err: %02x", res); #if 0 logf(" SAR0: %08x", SAR0); logf(" DAR0: %08x", DAR0); logf(" BCR0: %08x", BCR0); logf(" DCR0: %08x", DCR0); #endif } /* Force stop on error */ pcm_play_get_more_callback((res & 0x70) ? NULL : &start, &size); if (size != 0) { SAR0 = (unsigned long)start; /* Source address */ BCR0 = size; /* Bytes to transfer */ or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */ /* Call buffer callback */ pcm_play_dma_started_callback(); } /* else inished playing */ } /* DMA0 */
void INT_DMAC0C0(void) { DMAC0INTTCCLR = 1; if (!pcm_remaining) { pcm_play_get_more_callback((void**)&dataptr, &pcm_remaining); pcm_chunksize = pcm_remaining; } if (!pcm_remaining) { pcm_lli->nextlli = NULL; pcm_lli->control = 0x75249000; clean_dcache(); return; } uint32_t lastsize = MIN(PCM_WATERMARK * 4, pcm_remaining / 2 + 1) & ~1; pcm_remaining -= lastsize; if (pcm_remaining) lastlli = &pcm_lli[ARRAYLEN(pcm_lli) - 1]; else lastlli = pcm_lli; uint32_t chunksize = MIN(PCM_CHUNKSIZE * 4 - lastsize, pcm_remaining); if (pcm_remaining > chunksize && chunksize > pcm_remaining - PCM_WATERMARK * 8) chunksize = pcm_remaining - PCM_WATERMARK * 8; pcm_remaining -= chunksize; bool last = !chunksize; int i = 0; while (chunksize) { uint32_t thislli = MIN(PCM_LLIMAX * 4, chunksize); chunksize -= thislli; pcm_lli[i].srcaddr = (void*)dataptr; pcm_lli[i].dstaddr = (void*)((int)&I2STXDB0); pcm_lli[i].nextlli = chunksize ? &pcm_lli[i + 1] : lastlli; pcm_lli[i].control = (chunksize ? 0x75249000 : 0xf5249000) | (thislli / 2); dataptr += thislli; i++; } if (!pcm_remaining) { memcpy(dblbuf[active_dblbuf], dataptr, lastsize); lastlli->srcaddr = dblbuf[active_dblbuf]; active_dblbuf ^= 1; } else lastlli->srcaddr = dataptr; lastlli->dstaddr = (void*)((int)&I2STXDB0); lastlli->nextlli = last ? NULL : pcm_lli; lastlli->control = (last ? 0xf5249000 : 0x75249000) | (lastsize / 2); dataptr += lastsize; clean_dcache(); if (!(DMAC0C0CONFIG & 1) && (pcm_lli[0].control & 0xfff)) { DMAC0C0LLI = pcm_lli[0]; DMAC0C0CONFIG = 0x8a81; } else DMAC0C0NEXTLLI = pcm_lli; pcm_play_dma_started_callback(); }
void DSPHINT(void) { unsigned int i; size_t size; IO_INTC_FIQ0 = INTR_IRQ0_IMGBUF; switch (dsp_message.msg) { case MSG_DEBUGF: /* DSP stores one character per word. */ for (i = 0; i < sizeof(buffer); i++) { buffer[i] = dsp_message.payload.debugf.buffer[i]; } DEBUGF("DSP: %s", buffer); break; case MSG_REFILL: /* Buffer empty. Try to get more. */ pcm_play_get_more_callback(&start, &size); if (size != 0) { unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START; /* Flush any pending cache writes */ commit_dcache_range(start, size); /* set the new DMA values */ DSP_(_sdem_addrl) = sdem_addr & 0xffff; DSP_(_sdem_addrh) = sdem_addr >> 16; DSP_(_sdem_dsp_size) = size; DEBUGF("pcm_sdram at 0x%08lx, sdem_addr 0x%08lx", (unsigned long)start, (unsigned long)sdem_addr); pcm_play_dma_started_callback(); } break; default: DEBUGF("DSP: unknown msg 0x%04x", dsp_message.msg); break; }
static void feed_data(GstElement * appsrc, guint size_hint, void *unused) { (void)size_hint; (void)unused; lock_audio(); /* Make sure we don't trigger a gst_element_set_state() call from inside gstreamer's stream thread as it will deadlock */ inside_feed_data = 1; pcm_play_get_more_callback((void **)&pcm_data, &pcm_data_size); if (pcm_data_size != 0) { GstBuffer *buffer = gst_buffer_new (); GstFlowReturn ret; GST_BUFFER_DATA (buffer) = pcm_data; GST_BUFFER_SIZE (buffer) = pcm_data_size; g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret); gst_buffer_unref (buffer); if (ret != 0) DEBUGF("push-buffer error result: %d\n", ret); pcm_play_dma_started_callback(); } else { DEBUGF("feed_data: No Data.\n"); g_signal_emit_by_name (appsrc, "end-of-stream", NULL); } inside_feed_data = 0; unlock_audio(); }