예제 #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
/*
 * Reset camera block to power-on state.
 */
static void omap24xxcam_poweron_reset(struct omap24xxcam_device *cam)
{
	int max_loop = RESET_TIMEOUT_NS;

	/* Reset whole camera subsystem */
	omap24xxcam_reg_out(cam->mmio_base,
			    CAM_SYSCONFIG,
			    CAM_SYSCONFIG_SOFTRESET);

	/* Wait till it's finished */
	while (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS)
		 & CAM_SYSSTATUS_RESETDONE)
	       && --max_loop) {
		ndelay(1);
	}

	if (!(omap24xxcam_reg_in(cam->mmio_base, CAM_SYSSTATUS)
	      & CAM_SYSSTATUS_RESETDONE))
		dev_err(cam->dev, "camera soft reset timeout\n");
}
예제 #3
0
/* Ack dmach on CSR and IRQSTATUS_L0 */
static u32 omap24xxcam_dmahw_ack_ch(void __iomem *base, int dmach)
{
	u32 csr;

	csr = omap24xxcam_reg_in(base, CAMDMA_CSR(dmach));
	/* ack interrupt in CSR */
	omap24xxcam_reg_out(base, CAMDMA_CSR(dmach), csr);
	/* ack interrupt in IRQSTATUS */
	omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, (1 << dmach));

	return csr;
}
예제 #4
0
/* Ack all interrupt on CSR and IRQSTATUS_L0 */
static void omap24xxcam_dmahw_ack_all(void __iomem *base)
{
	u32 csr;
	int i;

	for (i = 0; i < NUM_CAMDMA_CHANNELS; ++i) {
		csr = omap24xxcam_reg_in(base, CAMDMA_CSR(i));
		/* ack interrupt in CSR */
		omap24xxcam_reg_out(base, CAMDMA_CSR(i), csr);
	}
	omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, 0xf);
}
예제 #5
0
static u32 omap24xxcam_dmahw_ack_ch(unsigned long base, int dmach)
{
	u32 csr;

	csr = omap24xxcam_reg_in(base, CAMDMA_CSR(dmach));
	
	omap24xxcam_reg_out(base, CAMDMA_CSR(dmach), csr);
	
	omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, (1 << dmach));

	return csr;
}
예제 #6
0
static void omap24xxcam_dmahw_ack_all(unsigned long base)
{
	u32 csr;
	int i;

	for (i = 0; i < NUM_CAMDMA_CHANNELS; ++i) {
		csr = omap24xxcam_reg_in(base, CAMDMA_CSR(i));
		
		omap24xxcam_reg_out(base, CAMDMA_CSR(i), csr);
	}
	omap24xxcam_reg_out(base, CAMDMA_IRQSTATUS_L0, 0xf);
}
예제 #7
0
/* Interrupt service routine for camera core interrupts. */
static void omap24xxcam_core_isr(struct omap24xxcam_device *cam)
{
	u32 cc_irqstatus;
	const u32 cc_irqstatus_err =
		CC_IRQSTATUS_FW_ERR_IRQ
		| CC_IRQSTATUS_FSC_ERR_IRQ
		| CC_IRQSTATUS_SSC_ERR_IRQ
		| CC_IRQSTATUS_FIFO_UF_IRQ
		| CC_IRQSTATUS_FIFO_OF_IRQ;

	cc_irqstatus = omap24xxcam_reg_in(cam->mmio_base + CC_REG_OFFSET,
					  CC_IRQSTATUS);
	omap24xxcam_reg_out(cam->mmio_base + CC_REG_OFFSET, CC_IRQSTATUS,
			    cc_irqstatus);

	if (cc_irqstatus & cc_irqstatus_err
	    && !atomic_read(&cam->in_reset)) {
		dev_dbg(cam->dev, "resetting camera, cc_irqstatus 0x%x\n",
			cc_irqstatus);
		omap24xxcam_reset(cam);
	}
}
예제 #8
0
/*
 * The main interrupt handler.
 */
static irqreturn_t omap24xxcam_isr(int irq, void *arg)
{
	struct omap24xxcam_device *cam = (struct omap24xxcam_device *)arg;
	u32 irqstatus;
	unsigned int irqhandled = 0;

	irqstatus = omap24xxcam_reg_in(cam->mmio_base, CAM_IRQSTATUS);

	if (irqstatus &
	    (CAM_IRQSTATUS_DMA_IRQ2 | CAM_IRQSTATUS_DMA_IRQ1
	     | CAM_IRQSTATUS_DMA_IRQ0)) {
		omap24xxcam_dma_isr(&cam->sgdma.dma);
		irqhandled = 1;
	}
	if (irqstatus & CAM_IRQSTATUS_CC_IRQ) {
		omap24xxcam_core_isr(cam);
		irqhandled = 1;
	}
	if (irqstatus & CAM_IRQSTATUS_MMU_IRQ)
		dev_err(cam->dev, "unhandled camera MMU interrupt!\n");

	return IRQ_RETVAL(irqhandled);
}
예제 #9
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;
	}
}
예제 #10
0
static int omap24xxcam_dmahw_running(void __iomem *base, int dmach)
{
	return omap24xxcam_reg_in(base, CAMDMA_CCR(dmach)) & CAMDMA_CCR_ENABLE;
}
예제 #11
0
static int omap24xxcam_dmahw_running(unsigned long base, int dmach)
{
	return omap24xxcam_reg_in(base, CAMDMA_CCR(dmach)) & CAMDMA_CCR_ENABLE;
}