/* Start a DMA transfer from the camera to memory. * Returns zero if the transfer was successfully started, or non-zero if all * DMA channels are already in use or starting is currently inhibited. */ static int omap24xxcam_dma_start(struct omap24xxcam_dma *dma, dma_addr_t start, u32 len, dma_callback_t callback, void *arg) { unsigned long flags; int dmach; spin_lock_irqsave(&dma->lock, flags); if (!dma->free_dmach || atomic_read(&dma->dma_stop)) { spin_unlock_irqrestore(&dma->lock, flags); return -EBUSY; } dmach = dma->next_dmach; dma->ch_state[dmach].callback = callback; dma->ch_state[dmach].arg = arg; omap24xxcam_dmahw_transfer_setup(dma->base, dmach, start, len); /* We're ready to start the DMA transfer. */ if (dma->free_dmach < NUM_CAMDMA_CHANNELS) { /* A transfer is already in progress, so try to chain to it. */ omap24xxcam_dmahw_transfer_chain(dma->base, dmach, dma->free_dmach); } else { /* No transfer is in progress, so we'll just start this one * now. */ omap24xxcam_dmahw_transfer_start(dma->base, dmach); } dma->next_dmach = (dma->next_dmach + 1) % NUM_CAMDMA_CHANNELS; dma->free_dmach--; spin_unlock_irqrestore(&dma->lock, flags); return 0; }
static int omap24xxcam_dma_start(struct omap24xxcam_dma *dma, dma_addr_t start, u32 len, dma_callback_t callback, void *arg) { unsigned long flags; int dmach; spin_lock_irqsave(&dma->lock, flags); if (!dma->free_dmach || atomic_read(&dma->dma_stop)) { spin_unlock_irqrestore(&dma->lock, flags); return -EBUSY; } dmach = dma->next_dmach; dma->ch_state[dmach].callback = callback; dma->ch_state[dmach].arg = arg; omap24xxcam_dmahw_transfer_setup(dma->base, dmach, start, len); if (dma->free_dmach < NUM_CAMDMA_CHANNELS) { omap24xxcam_dmahw_transfer_chain(dma->base, dmach, dma->free_dmach); } else { omap24xxcam_dmahw_transfer_start(dma->base, dmach); } dma->next_dmach = (dma->next_dmach + 1) % NUM_CAMDMA_CHANNELS; dma->free_dmach--; spin_unlock_irqrestore(&dma->lock, flags); return 0; }