Example #1
0
static void isp_csi2_isr_ctx(struct isp_csi2_device *csi2,
			     struct isp_csi2_ctx_cfg *ctx)
{
	struct isp_device *isp = csi2->isp;
	unsigned int n = ctx->ctxnum;
	u32 status;

	status = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
	isp_reg_writel(isp, status, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));

	/* Propagate frame number */
	if (status & ISPCSI2_CTX_IRQSTATUS_FS_IRQ) {
		struct isp_pipeline *pipe =
				     to_isp_pipeline(&csi2->subdev.entity);
		if (pipe->do_propagation)
			atomic_inc(&pipe->frame_number);
	}

	if (!(status & ISPCSI2_CTX_IRQSTATUS_FE_IRQ))
		return;

	/* Skip interrupts until we reach the frame skip count. The CSI2 will be
	 * automatically disabled, as the frame skip count has been programmed
	 * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
	 *
	 * It would have been nice to rely on the FRAME_NUMBER interrupt instead
	 * but it turned out that the interrupt is only generated when the CSI2
	 * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
	 * correctly and reaches 0 when data is forwarded to the video port only
	 * but no interrupt arrives). Maybe a CSI2 hardware bug.
	 */
	if (csi2->frame_skip) {
		csi2->frame_skip--;
		if (csi2->frame_skip == 0) {
			ctx->format_id = isp_csi2_ctx_map_format(csi2);
			isp_csi2_ctx_config(isp, csi2, ctx);
			isp_csi2_ctx_enable(isp, csi2, n, 1);
		}
		return;
	}

	if (csi2->output & CSI2_OUTPUT_MEMORY)
		isp_csi2_isr_buffer(csi2);
}
Example #2
0
/*
 * csi2_irq_ctx_set - Enables CSI2 Context IRQs.
 * @enable: Enable/disable CSI2 Context interrupts
 */
static void csi2_irq_ctx_set(struct isp_device *isp,
                             struct isp_csi2_device *csi2, int enable)
{
    int i;

    for (i = 0; i < 8; i++) {
        isp_reg_writel(isp, ISPCSI2_CTX_IRQSTATUS_FE_IRQ, csi2->regs1,
                       ISPCSI2_CTX_IRQSTATUS(i));
        if (enable)
            isp_reg_set(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
                        ISPCSI2_CTX_IRQSTATUS_FE_IRQ);
        else
            isp_reg_clr(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
                        ISPCSI2_CTX_IRQSTATUS_FE_IRQ);
    }
}
Example #3
0
/*
 * isp_csi2_irq_ctx_set - Enables CSI2 Context IRQs.
 * @enable: Enable/disable CSI2 Context interrupts
 */
static void isp_csi2_irq_ctx_set(struct isp_device *isp,
				 struct isp_csi2_device *csi2, int enable)
{
	u32 reg = ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
	int i;

	if (csi2->use_fs_irq)
		reg |= ISPCSI2_CTX_IRQSTATUS_FS_IRQ;

	for (i = 0; i < 8; i++) {
		isp_reg_writel(isp, reg, csi2->regs1,
			       ISPCSI2_CTX_IRQSTATUS(i));
		if (enable)
			isp_reg_set(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
				    reg);
		else
			isp_reg_clr(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
				    reg);
	}
}