示例#1
0
static void omap24xxcam_dmahw_transfer_chain(void __iomem *base, int dmach,
					     int free_dmach)
{
	int prev_dmach, ch;

	if (dmach == 0)
		prev_dmach = NUM_CAMDMA_CHANNELS - 1;
	else
		prev_dmach = dmach - 1;
	omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(prev_dmach),
			    CAMDMA_CLNK_CTRL_ENABLE_LNK | dmach);
	/* Did we chain the DMA transfer before the previous one
	 * finished?
	 */
	ch = (dmach + free_dmach) % NUM_CAMDMA_CHANNELS;
	while (!(omap24xxcam_reg_in(base, CAMDMA_CCR(ch))
		 & CAMDMA_CCR_ENABLE)) {
		if (ch == dmach) {
			/* The previous transfer has ended and this one
			 * hasn't started, so we must not have chained
			 * to the previous one in time.  We'll have to
			 * start it now.
			 */
			omap24xxcam_dmahw_transfer_start(base, dmach);
			break;
		} else
			ch = (ch + 1) % NUM_CAMDMA_CHANNELS;
	}
}
示例#2
0
/* 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;
}
示例#3
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;
}
示例#4
0
static void omap24xxcam_dmahw_transfer_chain(unsigned long base, int dmach,
					     int free_dmach)
{
	int prev_dmach, ch;

	if (dmach == 0)
		prev_dmach = NUM_CAMDMA_CHANNELS - 1;
	else
		prev_dmach = dmach - 1;
	omap24xxcam_reg_out(base, CAMDMA_CLNK_CTRL(prev_dmach),
			    CAMDMA_CLNK_CTRL_ENABLE_LNK | dmach);
	
	ch = (dmach + free_dmach) % NUM_CAMDMA_CHANNELS;
	while (!(omap24xxcam_reg_in(base, CAMDMA_CCR(ch))
		 & CAMDMA_CCR_ENABLE)) {
		if (ch == dmach) {
			
			omap24xxcam_dmahw_transfer_start(base, dmach);
			break;
		} else
			ch = (ch + 1) % NUM_CAMDMA_CHANNELS;
	}
}