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();
    }
}
Beispiel #2
0
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 */
Beispiel #3
0
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;
    }
Beispiel #5
0
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();
}