int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable) { struct ispstat *stat = v4l2_get_subdevdata(subdev); if (enable) { /* * Only set enable PCR bit if the module was previously * enabled through ioct. */ isp_stat_try_enable(stat); } else { unsigned long flags; /* Disable PCR bit and config enable field */ omap3isp_stat_enable(stat, 0); spin_lock_irqsave(&stat->isp->stat_lock, flags); stat->ops->enable(stat, 0); spin_unlock_irqrestore(&stat->isp->stat_lock, flags); /* * If module isn't busy, a new interrupt may come or not to * set the state to DISABLED. As Histogram needs to read its * internal memory to clear it, let interrupt handler * responsible of changing state to DISABLED. If the last * interrupt is coming, it's still safe as the handler will * ignore the second time when state is already set to DISABLED. * It's necessary to synchronize Histogram with streamoff, once * the module may be considered idle before last SDMA transfer * starts if we return here. */ if (!omap3isp_stat_pcr_busy(stat)) omap3isp_stat_isr(stat); dev_dbg(stat->isp->dev, "%s: module is being disabled\n", stat->subdev.name); } return 0; }
int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable) { struct ispstat *stat = v4l2_get_subdevdata(subdev); if (enable) { isp_stat_try_enable(stat); } else { unsigned long flags; omap3isp_stat_enable(stat, 0); spin_lock_irqsave(&stat->isp->stat_lock, flags); stat->ops->enable(stat, 0); spin_unlock_irqrestore(&stat->isp->stat_lock, flags); if (!omap3isp_stat_pcr_busy(stat)) omap3isp_stat_isr(stat); dev_dbg(stat->isp->dev, "%s: module is being disabled\n", stat->subdev.name); } return 0; }
/* * isp_isr - Interrupt Service Routine for Camera ISP module. * @irq: Not used currently. * @_isp: Pointer to the OMAP3 ISP device * * Handles the corresponding callback if plugged in. * * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the * IRQ wasn't handled. */ static irqreturn_t isp_isr(int irq, void *_isp) { static const u32 ccdc_events = IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ | IRQ0STATUS_CCDC_LSC_DONE_IRQ | IRQ0STATUS_CCDC_VD0_IRQ | IRQ0STATUS_CCDC_VD1_IRQ | IRQ0STATUS_HS_VS_IRQ; struct isp_device *isp = _isp; u32 irqstatus; int ret; irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); isp_isr_sbl(isp); if (irqstatus & IRQ0STATUS_CSIA_IRQ) { ret = omap3isp_csi2_isr(&isp->isp_csi2a); if (ret) isp->isp_ccdc.error = 1; } if (irqstatus & IRQ0STATUS_CSIB_IRQ) { ret = omap3isp_ccp2_isr(&isp->isp_ccp2); if (ret) isp->isp_ccdc.error = 1; } if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) { if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW) omap3isp_preview_isr_frame_sync(&isp->isp_prev); if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER) omap3isp_resizer_isr_frame_sync(&isp->isp_res); omap3isp_stat_isr_frame_sync(&isp->isp_aewb); omap3isp_stat_isr_frame_sync(&isp->isp_af); omap3isp_stat_isr_frame_sync(&isp->isp_hist); } if (irqstatus & ccdc_events) omap3isp_ccdc_isr(&isp->isp_ccdc, irqstatus & ccdc_events); if (irqstatus & IRQ0STATUS_PRV_DONE_IRQ) { if (isp->isp_prev.output & PREVIEW_OUTPUT_RESIZER) omap3isp_resizer_isr_frame_sync(&isp->isp_res); omap3isp_preview_isr(&isp->isp_prev); } if (irqstatus & IRQ0STATUS_RSZ_DONE_IRQ) omap3isp_resizer_isr(&isp->isp_res); if (irqstatus & IRQ0STATUS_H3A_AWB_DONE_IRQ) omap3isp_stat_isr(&isp->isp_aewb); if (irqstatus & IRQ0STATUS_H3A_AF_DONE_IRQ) omap3isp_stat_isr(&isp->isp_af); if (irqstatus & IRQ0STATUS_HIST_DONE_IRQ) omap3isp_stat_isr(&isp->isp_hist); omap3isp_flush(isp); #if defined(DEBUG) && defined(ISP_ISR_DEBUG) isp_isr_dbg(isp, irqstatus); #endif return IRQ_HANDLED; }