void omap24xxcam_sgdma_sync(struct omap24xxcam_sgdma *sgdma) { unsigned long flags; int sgslot; struct sgdma_state *sg_state; u32 csr = CAMDMA_CSR_TRANS_ERR; omap24xxcam_dma_stop(&sgdma->dma, csr); spin_lock_irqsave(&sgdma->lock, flags); if (sgdma->free_sgdma < NUM_SG_DMA) { sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA; sg_state = sgdma->sg_state + sgslot; if (sg_state->next_sglist != 0) { sgdma_callback_t callback = sg_state->callback; void *arg = sg_state->arg; sgdma->free_sgdma++; if (callback) { spin_unlock(&sgdma->lock); (*callback) (sgdma, csr, arg); spin_lock(&sgdma->lock); } } } spin_unlock_irqrestore(&sgdma->lock, flags); }
/* Sync scatter-gather DMA by aborting any DMA transfers currently in progress. * Any queued scatter-gather DMA transactions that have not yet been started * will remain queued. The DMA controller will be idle after this routine * completes. When the scatter-gather queue is restarted, the next * scatter-gather DMA transfer will begin at the start of a new transaction. */ void omap24xxcam_sgdma_sync(struct omap24xxcam_sgdma *sgdma) { unsigned long flags; int sgslot; struct sgdma_state *sg_state; u32 csr = CAMDMA_CSR_TRANS_ERR; /* stop any DMA transfers in progress */ omap24xxcam_dma_stop(&sgdma->dma, csr); spin_lock_irqsave(&sgdma->lock, flags); if (sgdma->free_sgdma < NUM_SG_DMA) { sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA; sg_state = sgdma->sg_state + sgslot; if (sg_state->next_sglist != 0) { /* This DMA transfer was in progress, so abort it. */ sgdma_callback_t callback = sg_state->callback; void *arg = sg_state->arg; sgdma->free_sgdma++; if (callback) { /* leave interrupts masked */ spin_unlock(&sgdma->lock); (*callback) (sgdma, csr, arg); spin_lock(&sgdma->lock); } } } spin_unlock_irqrestore(&sgdma->lock, flags); }
/* Camera DMA interrupt service routine. */ void omap24xxcam_dma_isr(struct omap24xxcam_dma *dma) { int dmach; dma_callback_t callback; void *arg; u32 csr; const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP; spin_lock(&dma->lock); if (dma->free_dmach == NUM_CAMDMA_CHANNELS) { /* A camera DMA interrupt occurred while all channels * are idle, so we'll acknowledge the interrupt in the * IRQSTATUS register and exit. */ omap24xxcam_dmahw_ack_all(dma->base); spin_unlock(&dma->lock); return; } while (dma->free_dmach < NUM_CAMDMA_CHANNELS) { dmach = (dma->next_dmach + dma->free_dmach) % NUM_CAMDMA_CHANNELS; if (omap24xxcam_dmahw_running(dma->base, dmach)) { /* This buffer hasn't finished yet, so we're done. */ break; } csr = omap24xxcam_dmahw_ack_ch(dma->base, dmach); if (csr & csr_error) { /* A DMA error occurred, so stop all DMA * transfers in progress. */ spin_unlock(&dma->lock); omap24xxcam_dma_stop(dma, csr); return; } else { callback = dma->ch_state[dmach].callback; arg = dma->ch_state[dmach].arg; dma->free_dmach++; if (callback) { spin_unlock(&dma->lock); (*callback) (dma, csr, arg); spin_lock(&dma->lock); } } } spin_unlock(&dma->lock); omap24xxcam_sgdma_process( container_of(dma, struct omap24xxcam_sgdma, dma)); }
void omap24xxcam_dma_isr(struct omap24xxcam_dma *dma) { int dmach; dma_callback_t callback; void *arg; u32 csr; const u32 csr_error = CAMDMA_CSR_MISALIGNED_ERR | CAMDMA_CSR_SUPERVISOR_ERR | CAMDMA_CSR_SECURE_ERR | CAMDMA_CSR_TRANS_ERR | CAMDMA_CSR_DROP; spin_lock(&dma->lock); if (dma->free_dmach == NUM_CAMDMA_CHANNELS) { omap24xxcam_dmahw_ack_all(dma->base); spin_unlock(&dma->lock); return; } while (dma->free_dmach < NUM_CAMDMA_CHANNELS) { dmach = (dma->next_dmach + dma->free_dmach) % NUM_CAMDMA_CHANNELS; if (omap24xxcam_dmahw_running(dma->base, dmach)) { break; } csr = omap24xxcam_dmahw_ack_ch(dma->base, dmach); if (csr & csr_error) { spin_unlock(&dma->lock); omap24xxcam_dma_stop(dma, csr); return; } else { callback = dma->ch_state[dmach].callback; arg = dma->ch_state[dmach].arg; dma->free_dmach++; if (callback) { spin_unlock(&dma->lock); (*callback) (dma, csr, arg); spin_lock(&dma->lock); } } } spin_unlock(&dma->lock); omap24xxcam_sgdma_process( container_of(dma, struct omap24xxcam_sgdma, dma)); }
/* Sync scatter-gather DMA by aborting any DMA transfers currently in progress. * Any queued scatter-gather DMA transactions that have not yet been started * will remain queued. The DMA controller will be idle after this routine * completes. When the scatter-gather queue is restarted, the next * scatter-gather DMA transfer will begin at the start of a new transaction. */ void omap24xxcam_sgdma_sync(struct omap24xxcam_sgdma *sgdma) { unsigned long flags; int sgslot; struct sgdma_state *sg_state; u32 csr = CAMDMA_CSR_TRANS_ERR; /* stop any DMA transfers in progress */ omap24xxcam_dma_stop(&sgdma->dma, csr); spin_lock_irqsave(&sgdma->lock, flags); if (sgdma->free_sgdma < NUM_SG_DMA) { sgslot = (sgdma->next_sgdma + sgdma->free_sgdma) % NUM_SG_DMA; sg_state = sgdma->sg_state + sgslot; if (sg_state->next_sglist != 0) { /* This DMA transfer was in progress, so abort it. */ sgdma_callback_t callback = sg_sta