static void hist_enable(struct ispstat *hist, int enable) { if (enable) { isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ISPHIST_PCR_ENABLE); isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_HIST_CLK_EN); } else { isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ISPHIST_PCR_ENABLE); isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, ISPCTRL_HIST_CLK_EN); } }
/* * ispccp2_if_enable - Enable CCP2 interface. * @ccp2: pointer to ISP CCP2 device * @enable: enable/disable flag */ static void ispccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity); int i; if (enable && ccp2->vdds_csib) regulator_enable(ccp2->vdds_csib); /* Enable/Disable all the LCx channels */ for (i = 0; i < CCP2_LCx_CHANS_NUM; i++) isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i), ISPCCP2_LCx_CTRL_CHAN_EN, enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0); /* Enable/Disable ccp2 interface in ccp2 mode */ isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL, ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN, enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0); /* For frame count propagation */ if (pipe->do_propagation) { /* We may want the Frame Start IRQ from LC0 */ if (enable) isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); else isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); } if (!enable && ccp2->vdds_csib) regulator_disable(ccp2->vdds_csib); }
static int hist_buf_pio(struct ispstat *hist) { struct isp_device *isp = hist->isp; u32 *buf = hist->active_buf->virt_addr; unsigned int i; if (!buf) { dev_dbg(isp->dev, "hist: invalid PIO buffer address\n"); hist_reset_mem(hist); return STAT_NO_BUF; } isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR); isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); for (i = hist->buf_size / 16; i > 0; i--) { *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); } isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); return STAT_BUF_DONE; }
/* * hist_reset_mem - clear Histogram memory before start stats engine. */ static void hist_reset_mem(struct ispstat *hist) { struct isp_device *isp = hist->isp; struct omap3isp_hist_config *conf = hist->priv; unsigned int i; isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR); /* * By setting it, the histogram internal buffer is being cleared at the * same time it's being read. This bit must be cleared afterwards. */ isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); /* * We'll clear 4 words at each iteration for optimization. It avoids * 3/4 of the jumps. We also know HIST_MEM_SIZE is divisible by 4. */ for (i = OMAP3ISP_HIST_MEM_SIZE / 4; i > 0; i--) { isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); } isp_reg_clr(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); hist->wait_acc_frames = conf->num_acc_frames; }
static void hist_enable(struct ispstat *hist, int enable) { if (enable) { isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ISPHIST_PCR_ENABLE); omap3isp_subclk_enable(hist->isp, OMAP3_ISP_SUBCLK_HIST); } else { isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR, ISPHIST_PCR_ENABLE); omap3isp_subclk_disable(hist->isp, OMAP3_ISP_SUBCLK_HIST); } }
static void hist_dma_cb(void *data) { struct ispstat *hist = data; /* FIXME: The DMA engine API can't report transfer errors :-/ */ isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); omap3isp_stat_dma_isr(hist); if (hist->state != ISPSTAT_DISABLED) omap3isp_hist_dma_done(hist->isp); }
/* * 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); } }
static void hist_dma_cb(int lch, u16 ch_status, void *data) { struct ispstat *hist = data; if (ch_status & ~OMAP_DMA_BLOCK_IRQ) { dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n", ch_status); omap_stop_dma(lch); hist_reset_mem(hist); atomic_set(&hist->buf_err, 1); } isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); omap3isp_stat_dma_isr(hist); if (hist->state != ISPSTAT_DISABLED) omap3isp_hist_dma_done(hist->isp); }
/* * 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); } }
static void hist_reset_mem(struct ispstat *hist) { struct isp_device *isp = hist->isp; struct omap3isp_hist_config *conf = hist->priv; unsigned int i; isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR); isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); for (i = OMAP3ISP_HIST_MEM_SIZE / 4; i > 0; i--) { isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); } isp_reg_clr(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); hist->wait_acc_frames = conf->num_acc_frames; }
static int hist_buf_pio(struct ispstat *hist) { struct isp_device *isp = hist->isp; u32 *buf = hist->active_buf->virt_addr; unsigned int i; if (!buf) { dev_dbg(isp->dev, "hist: invalid PIO buffer address\n"); hist_reset_mem(hist); return STAT_NO_BUF; } isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR); /* * By setting it, the histogram internal buffer is being cleared at the * same time it's being read. This bit must be cleared just after all * data is acquired. */ isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); /* * We'll read 4 times a 4-bytes-word at each iteration for * optimization. It avoids 3/4 of the jumps. We also know buf_size is * divisible by 16. */ for (i = hist->buf_size / 16; i > 0; i--) { *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); *buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA); } isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR); return STAT_BUF_DONE; }
static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable) { struct isp_device *isp = to_isp_device(ccp2); struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity); int i; if (enable && ccp2->vdds_csib) regulator_enable(ccp2->vdds_csib); for (i = 0; i < CCP2_LCx_CHANS_NUM; i++) isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i), ISPCCP2_LCx_CTRL_CHAN_EN, enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0); isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL, ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN, enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0); if (pipe->do_propagation) { if (enable) isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); else isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ); } if (!enable && ccp2->vdds_csib) regulator_disable(ccp2->vdds_csib); }