media: camss: ispif: Correctly reset based on the VFE ID
authorAngeloGioacchino Del Regno <kholk11@gmail.com>
Thu, 22 Oct 2020 17:47:00 +0000 (19:47 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Wed, 25 Nov 2020 13:54:07 +0000 (14:54 +0100)
Resetting the ISPIF VFE0 context is wrong if we are using the VFE1
for dual-camera or simply because a secondary camera is connected
to it: in this case the reset will always happen on the VFE0 ctx
of the ISPIF, which is .. useless.

Fix this usecase by adding the ISPIF_RST_CMD_1 address and choose
where to do the (or what to) reset based on the VFE line id.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
Reviewed-by: Robert Foss <robert.foss@linaro.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/platform/qcom/camss/camss-ispif.c
drivers/media/platform/qcom/camss/camss-ispif.h

index db94cfd..754f0d0 100644 (file)
@@ -26,6 +26,7 @@
 #define MSM_ISPIF_NAME "msm_ispif"
 
 #define ISPIF_RST_CMD_0                        0x008
+#define ISPIF_RST_CMD_1                        0x00c
 #define ISPIF_RST_CMD_0_STROBED_RST_EN         (1 << 0)
 #define ISPIF_RST_CMD_0_MISC_LOGIC_RST         (1 << 1)
 #define ISPIF_RST_CMD_0_SW_REG_RST             (1 << 2)
@@ -179,7 +180,10 @@ static irqreturn_t ispif_isr_8x96(int irq, void *dev)
        writel(0x1, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD);
 
        if ((value0 >> 27) & 0x1)
-               complete(&ispif->reset_complete);
+               complete(&ispif->reset_complete[0]);
+
+       if ((value3 >> 27) & 0x1)
+               complete(&ispif->reset_complete[1]);
 
        if (unlikely(value0 & ISPIF_VFE_m_IRQ_STATUS_0_PIX0_OVERFLOW))
                dev_err_ratelimited(to_device(ispif), "VFE0 pix0 overflow\n");
@@ -237,7 +241,7 @@ static irqreturn_t ispif_isr_8x16(int irq, void *dev)
        writel(0x1, ispif->base + ISPIF_IRQ_GLOBAL_CLEAR_CMD);
 
        if ((value0 >> 27) & 0x1)
-               complete(&ispif->reset_complete);
+               complete(&ispif->reset_complete[0]);
 
        if (unlikely(value0 & ISPIF_VFE_m_IRQ_STATUS_0_PIX0_OVERFLOW))
                dev_err_ratelimited(to_device(ispif), "VFE0 pix0 overflow\n");
@@ -257,33 +261,18 @@ static irqreturn_t ispif_isr_8x16(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-/*
- * ispif_reset - Trigger reset on ISPIF module and wait to complete
- * @ispif: ISPIF device
- *
- * Return 0 on success or a negative error code otherwise
- */
-static int ispif_reset(struct ispif_device *ispif)
+static int ispif_vfe_reset(struct ispif_device *ispif, u8 vfe_id)
 {
        unsigned long time;
        u32 val;
-       int ret;
-
-       ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE0);
-       if (ret < 0)
-               return ret;
 
-       ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE1);
-       if (ret < 0)
-               return ret;
-
-       ret = camss_enable_clocks(ispif->nclocks_for_reset,
-                                 ispif->clock_for_reset,
-                                 to_device(ispif));
-       if (ret < 0)
-               return ret;
+       if (vfe_id > (to_camss(ispif)->vfe_num - 1)) {
+               dev_err(to_device(ispif),
+                       "Error: asked reset for invalid VFE%d\n", vfe_id);
+               return -ENOENT;
+       }
 
-       reinit_completion(&ispif->reset_complete);
+       reinit_completion(&ispif->reset_complete[vfe_id]);
 
        val = ISPIF_RST_CMD_0_STROBED_RST_EN |
                ISPIF_RST_CMD_0_MISC_LOGIC_RST |
@@ -303,15 +292,50 @@ static int ispif_reset(struct ispif_device *ispif)
                ISPIF_RST_CMD_0_RDI_OUTPUT_1_MISR_RST |
                ISPIF_RST_CMD_0_RDI_OUTPUT_2_MISR_RST;
 
-       writel_relaxed(val, ispif->base + ISPIF_RST_CMD_0);
+       if (vfe_id == 1)
+               writel_relaxed(val, ispif->base + ISPIF_RST_CMD_1);
+       else
+               writel_relaxed(val, ispif->base + ISPIF_RST_CMD_0);
 
-       time = wait_for_completion_timeout(&ispif->reset_complete,
+       time = wait_for_completion_timeout(&ispif->reset_complete[vfe_id],
                msecs_to_jiffies(ISPIF_RESET_TIMEOUT_MS));
        if (!time) {
-               dev_err(to_device(ispif), "ISPIF reset timeout\n");
-               ret = -EIO;
+               dev_err(to_device(ispif),
+                       "ISPIF for VFE%d reset timeout\n", vfe_id);
+               return -EIO;
        }
 
+       return 0;
+}
+
+/*
+ * ispif_reset - Trigger reset on ISPIF module and wait to complete
+ * @ispif: ISPIF device
+ *
+ * Return 0 on success or a negative error code otherwise
+ */
+static int ispif_reset(struct ispif_device *ispif, u8 vfe_id)
+{
+       int ret;
+
+       ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE0);
+       if (ret < 0)
+               return ret;
+
+       ret = camss_pm_domain_on(to_camss(ispif), PM_DOMAIN_VFE1);
+       if (ret < 0)
+               return ret;
+
+       ret = camss_enable_clocks(ispif->nclocks_for_reset,
+                                 ispif->clock_for_reset,
+                                 to_device(ispif));
+       if (ret < 0)
+               return ret;
+
+       ret = ispif_vfe_reset(ispif, vfe_id);
+       if (ret)
+               dev_dbg(to_device(ispif), "ISPIF Reset failed\n");
+
        camss_disable_clocks(ispif->nclocks_for_reset, ispif->clock_for_reset);
 
        camss_pm_domain_off(to_camss(ispif), PM_DOMAIN_VFE0);
@@ -355,7 +379,7 @@ static int ispif_set_power(struct v4l2_subdev *sd, int on)
                        goto exit;
                }
 
-               ret = ispif_reset(ispif);
+               ret = ispif_reset(ispif, line->vfe_id);
                if (ret < 0) {
                        pm_runtime_put_sync(dev);
                        camss_disable_clocks(ispif->nclocks, ispif->clock);
@@ -1192,7 +1216,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
 
        mutex_init(&ispif->config_lock);
 
-       init_completion(&ispif->reset_complete);
+       for (i = 0; i < MSM_ISPIF_VFE_NUM; i++)
+               init_completion(&ispif->reset_complete[i]);
 
        return 0;
 }
index 1a5ba24..4132174 100644 (file)
@@ -56,7 +56,7 @@ struct ispif_device {
        int nclocks;
        struct camss_clock  *clock_for_reset;
        int nclocks_for_reset;
-       struct completion reset_complete;
+       struct completion reset_complete[MSM_ISPIF_VFE_NUM];
        int power_count;
        struct mutex power_lock;
        struct ispif_intf_cmd_reg intf_cmd[MSM_ISPIF_VFE_NUM];