diff --git a/drivers/media/platform/msm/ais/isp/msm_isp.h b/drivers/media/platform/msm/ais/isp/msm_isp.h index 419615cc9b4a..856bf55f8c29 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp.h +++ b/drivers/media/platform/msm/ais/isp/msm_isp.h @@ -782,6 +782,7 @@ struct vfe_device { uint32_t is_split; uint32_t dual_vfe_enable; unsigned long page_fault_addr; + bool clk_enabled; /* Debug variables */ int dump_reg; diff --git a/drivers/media/platform/msm/ais/isp/msm_isp47.c b/drivers/media/platform/msm/ais/isp/msm_isp47.c index 6ca91b4fcf83..221aa700421a 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp47.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp47.c @@ -2423,9 +2423,30 @@ void msm_vfe47_put_clks(struct vfe_device *vfe_dev) int msm_vfe47_enable_clks(struct vfe_device *vfe_dev, int enable) { - return msm_camera_clk_enable(&vfe_dev->pdev->dev, + unsigned long flags; + int rc; + + if (!enable) { + spin_lock_irqsave(&vfe_dev->tasklet_lock, flags); + vfe_dev->clk_enabled = false; + spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); + } + + rc = msm_camera_clk_enable(&vfe_dev->pdev->dev, vfe_dev->vfe_clk_info, vfe_dev->vfe_clk, vfe_dev->num_clk, enable); + if (rc < 0) { + pr_err("%s: clk set %d failed %d\n", __func__, enable, rc); + return rc; + } + + if (enable) { + spin_lock_irqsave(&vfe_dev->tasklet_lock, flags); + vfe_dev->clk_enabled = true; + spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); + } + + return rc; } int msm_vfe47_set_clk_rate(struct vfe_device *vfe_dev, long *rate) diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_util.c index 5ca3b8d531a2..5f5b4610f2f0 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_util.c @@ -851,6 +851,7 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, { long rc = 0; long rc2 = 0; + unsigned long flags; struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); if (!vfe_dev || !vfe_dev->vfe_base) { @@ -1061,6 +1062,11 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, while (vfe_dev->vfe_open_cnt != 0) msm_isp_close_node(sd, NULL); break; + case VIDIOC_MSM_ISP_SET_CLK_STATUS: + spin_lock_irqsave(&vfe_dev->tasklet_lock, flags); + vfe_dev->clk_enabled = *((unsigned int *)arg); + spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); + break; default: pr_err_ratelimited("%s: Invalid ISP command %d\n", __func__, @@ -2113,11 +2119,21 @@ void msm_isp_do_tasklet(unsigned long data) } atomic_sub(1, &vfe_dev->irq_cnt); list_del(&queue_cmd->list); + + if (!vfe_dev->clk_enabled) { + /* client closed, delayed task should exit directly */ + spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); + return; + } + queue_cmd->cmd_used = 0; irq_status0 = queue_cmd->vfeInterruptStatus0; irq_status1 = queue_cmd->vfeInterruptStatus1; pingpong_status = queue_cmd->vfePingPongStatus; ts = queue_cmd->ts; + /* related to rw reg, need to be protected */ + irq_ops->process_halt_irq(vfe_dev, + irq_status0, irq_status1); spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n", __func__, vfe_dev->pdev->id, irq_status0, irq_status1); @@ -2141,8 +2157,6 @@ void msm_isp_do_tasklet(unsigned long data) } irq_ops->process_reset_irq(vfe_dev, irq_status0, irq_status1); - irq_ops->process_halt_irq(vfe_dev, - irq_status0, irq_status1); if (atomic_read(&vfe_dev->error_info.overflow_state) != NO_OVERFLOW) { ISP_DBG("%s: Recovery in processing, Ignore IRQs!!!\n", diff --git a/include/uapi/media/ais/msm_ais_isp.h b/include/uapi/media/ais/msm_ais_isp.h index f323d3bf7baf..55bc5290ce28 100644 --- a/include/uapi/media/ais/msm_ais_isp.h +++ b/include/uapi/media/ais/msm_ais_isp.h @@ -973,6 +973,8 @@ enum msm_isp_ioctl_cmd_code { MSM_ISP_AXI_OUTPUT_CFG, MSM_ISP_START, MSM_ISP_STOP, + + MSM_ISP_SET_CLK_STATUS, }; @@ -1104,5 +1106,8 @@ enum msm_isp_ioctl_cmd_code { _IOWR('V', MSM_ISP_CAMIF_CFG, \ struct msm_vfe_camif_cfg) +#define VIDIOC_MSM_ISP_SET_CLK_STATUS \ + _IOWR('V', MSM_ISP_SET_CLK_STATUS, \ + unsigned int) #endif /* __UAPI_MSM_AIS_ISP__ */