summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp.h1
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp47.c23
-rw-r--r--drivers/media/platform/msm/ais/isp/msm_isp_util.c18
-rw-r--r--include/uapi/media/ais/msm_ais_isp.h5
4 files changed, 44 insertions, 3 deletions
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__ */