OSDN Git Service

ais: sync clk status and tasklet
authorAndy Sun <bins@codeaurora.org>
Mon, 12 Mar 2018 09:47:44 +0000 (17:47 +0800)
committerAndy Sun <bins@codeaurora.org>
Wed, 14 Mar 2018 09:36:46 +0000 (17:36 +0800)
1. add set_clk_status user interface;
2. exit delayed tasklet without processing if clk disabled;
3. protect process_halt_irq();

Change-Id: I66c933ac9b9e2dacd4dec20b646ef297cd18920d
Signed-off-by: Andy Sun <bins@codeaurora.org>
drivers/media/platform/msm/ais/isp/msm_isp.h
drivers/media/platform/msm/ais/isp/msm_isp47.c
drivers/media/platform/msm/ais/isp/msm_isp_util.c
include/uapi/media/ais/msm_ais_isp.h

index 419615c..856bf55 100644 (file)
@@ -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;
index 6ca91b4..221aa70 100644 (file)
@@ -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)
index 5ca3b8d..5f5b461 100644 (file)
@@ -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",
index f323d3b..55bc529 100644 (file)
@@ -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__ */