static void csi2_isr_ctx(struct iss_csi2_device *csi2, struct iss_csi2_ctx_cfg *ctx) { unsigned int n = ctx->ctxnum; u32 status; status = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n)); iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n), status); /* Propagate frame number */ if (status & CSI2_CTX_IRQ_FS) { struct iss_pipeline *pipe = to_iss_pipeline(&csi2->subdev.entity); if (pipe->do_propagation) atomic_inc(&pipe->frame_number); } if (!(status & CSI2_CTX_IRQ_FE)) 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 = csi2_ctx_map_format(csi2); csi2_ctx_config(csi2, ctx); csi2_ctx_enable(csi2, n, 1); } return; } if (csi2->output & CSI2_OUTPUT_MEMORY) csi2_isr_buffer(csi2); }
/* * csi2_irq_ctx_set - Enables CSI2 Context IRQs. * @enable: Enable/disable CSI2 Context interrupts */ static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable) { u32 reg = CSI2_CTX_IRQ_FE; int i; if (csi2->use_fs_irq) reg |= CSI2_CTX_IRQ_FS; for (i = 0; i < 8; i++) { iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(i), reg); if (enable) iss_reg_set(csi2->iss, csi2->regs1, CSI2_CTX_IRQENABLE(i), reg); else iss_reg_clr(csi2->iss, csi2->regs1, CSI2_CTX_IRQENABLE(i), reg); } }
/* * csi2_irq_ctx_set - Enables CSI2 Context IRQs. * @enable: Enable/disable CSI2 Context interrupts */ static void csi2_irq_ctx_set(struct iss_csi2_device *csi2, int enable) { u32 reg = CSI2_CTX_IRQ_FE; int i; if (csi2->use_fs_irq) reg |= CSI2_CTX_IRQ_FS; for (i = 0; i < 8; i++) { writel(reg, csi2->regs1 + CSI2_CTX_IRQSTATUS(i)); if (enable) writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) | reg, csi2->regs1 + CSI2_CTX_IRQENABLE(i)); else writel(readl(csi2->regs1 + CSI2_CTX_IRQENABLE(i)) & ~reg, csi2->regs1 + CSI2_CTX_IRQENABLE(i)); } }