camera: ispif: Improve start/stop/reset sequence.
Halt ispif immediately before stopping sensor streaming,
and start ispif before start sensor streaming.
Handle ispif reset properly using wait_for_completion*
instead of msleep().
Signed-off-by: Shuzhen Wang <shuzhenw@codeaurora.org>
diff --git a/drivers/media/video/msm/msm_ispif.c b/drivers/media/video/msm/msm_ispif.c
index 8683d3b..c5e38ef 100644
--- a/drivers/media/video/msm/msm_ispif.c
+++ b/drivers/media/video/msm/msm_ispif.c
@@ -70,8 +70,8 @@
#define RAW_INTF_1_OVERFLOW_IRQ 25
#define RESET_DONE_IRQ 27
-#define ISPIF_IRQ_STATUS_MASK 0x2493000
-#define ISPIF_IRQ_1_STATUS_MASK 0x2493000
+#define ISPIF_IRQ_STATUS_MASK 0xA493000
+#define ISPIF_IRQ_1_STATUS_MASK 0xA493000
#define ISPIF_IRQ_STATUS_RDI_SOF_MASK 0x492000
#define MAX_CID 15
@@ -80,61 +80,57 @@
static uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
-static void msm_ispif_swreg_misc_reset(void)
+static int msm_ispif_intf_reset(uint8_t intftype)
{
- uint32_t data = 0x01, data1 = 0x01;
+ int rc = 0;
+ uint32_t data;
- data |= 0x1 << SW_REG_RST_STB;
- msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
- data1 |= 0x1 << MISC_LOGIC_RST_STB;
- msm_io_w(data1, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
-}
-
-static void msm_ispif_intf_reset(uint8_t intftype)
-{
- uint32_t data = 0x01 , data1 = 0x01;
-
- msm_io_w(0x1<<STROBED_RST_EN, ispif->base + ISPIF_RST_CMD_ADDR);
switch (intftype) {
case PIX0:
- data |= 0x1 << PIX_VFE_RST_STB;
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << PIX_VFE_RST_STB) +
+ (0x1 << PIX_CSID_RST_STB);
msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
- data1 |= 0x1 << PIX_CSID_RST_STB;
- msm_io_w(data1, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
break;
case RDI0:
- data |= 0x1 << RDI_VFE_RST_STB;
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << RDI_VFE_RST_STB) +
+ (0x1 << RDI_CSID_RST_STB);
msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
- data1 |= 0x1 << RDI_CSID_RST_STB;
- msm_io_w(data1, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
break;
case RDI1:
- data |= 0x1 << RDI_1_VFE_RST_STB;
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << RDI_1_VFE_RST_STB) +
+ (0x1 << RDI_1_CSID_RST_STB);
msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
- data1 |= 0x1 << RDI_1_CSID_RST_STB;
- msm_io_w(data1, ispif->base + ISPIF_RST_CMD_ADDR);
- usleep_range(11000, 12000);
break;
default:
+ rc = -EINVAL;
break;
}
+ if (rc >= 0)
+ rc = wait_for_completion_interruptible(
+ &ispif->reset_complete);
+
+ return rc;
}
-static void msm_ispif_reset(void)
+static int msm_ispif_reset(void)
{
- msm_ispif_swreg_misc_reset();
- msm_ispif_intf_reset(PIX0);
- msm_ispif_intf_reset(RDI0);
+ uint32_t data = (0x1 << STROBED_RST_EN) +
+ (0x1 << SW_REG_RST_STB) +
+ (0x1 << MISC_LOGIC_RST_STB) +
+ (0x1 << PIX_VFE_RST_STB) +
+ (0x1 << PIX_CSID_RST_STB) +
+ (0x1 << RDI_VFE_RST_STB) +
+ (0x1 << RDI_CSID_RST_STB) +
+ (0x1 << RDI_1_VFE_RST_STB) +
+ (0x1 << RDI_1_CSID_RST_STB);
+ msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
+ return wait_for_completion_interruptible(&ispif->reset_complete);
}
static int msm_ispif_subdev_g_chip_ident(struct v4l2_subdev *sd,
@@ -279,7 +275,7 @@
CDBG("abort stream request\n");
mutex_lock(&ispif->mutex);
msm_ispif_intf_cmd(intf, intf_cmd_mask);
- msm_ispif_intf_reset(intf);
+ rc = msm_ispif_intf_reset(intf);
global_intf_cmd_mask |= 0xFF<<(intf * 8);
mutex_unlock(&ispif->mutex);
return rc;
@@ -393,6 +389,8 @@
CDBG("ispif->irq: Irq_status0 = 0x%x\n",
out->ispifIrqStatus0);
if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
+ if (out->ispifIrqStatus0 & (0x1 << RESET_DONE_IRQ))
+ complete(&ispif->reset_complete);
if (out->ispifIrqStatus0 & (0x1 << PIX_INTF_0_OVERFLOW_IRQ))
pr_err("%s: pix intf 0 overflow.\n", __func__);
if (out->ispifIrqStatus0 & (0x1 << RAW_INTF_0_OVERFLOW_IRQ))
@@ -471,10 +469,11 @@
goto ispif_irq_fail;
global_intf_cmd_mask = 0xFFFFFFFF;
+ init_completion(&ispif->reset_complete);
- msm_ispif_reset();
+ rc = msm_ispif_reset();
*sd = &(ispif->subdev);
- return 0;
+ return rc;
ispif_irq_fail:
iounmap(ispif->base);
diff --git a/drivers/media/video/msm/msm_ispif.h b/drivers/media/video/msm/msm_ispif.h
index 601e9ea..3b923ea 100644
--- a/drivers/media/video/msm/msm_ispif.h
+++ b/drivers/media/video/msm/msm_ispif.h
@@ -41,6 +41,7 @@
void __iomem *base;
struct mutex mutex;
uint8_t start_ack_pending;
+ struct completion reset_complete;
};
#define VIDIOC_MSM_ISPSF_CFG \
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index f684b4f..acd5214 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -183,17 +183,15 @@
VIDIOC_MSM_ISPSF_CFG, &ispif_params);
if (rc < 0)
return rc;
-
- rc = v4l2_subdev_call(p_mctl->ispif_sdev, video,
- s_stream, ISPIF_STREAM(PIX0,
- ISPIF_ON_FRAME_BOUNDARY));
- if (rc < 0)
- return rc;
}
break;
case NOTIFY_ISPIF_STREAM:
/* call ISPIF stream on/off */
- rc = 0;
+ rc = v4l2_subdev_call(p_mctl->ispif_sdev, video,
+ s_stream, (int)arg);
+ if (rc < 0)
+ return rc;
+
break;
case NOTIFY_ISP_MSG_EVT:
case NOTIFY_VFE_MSG_OUT:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 9e558d2..9122d1a 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -373,12 +373,9 @@
vfe32_ctrl->vfebase + VFE_IRQ_CMD);
/* in either continuous or snapshot mode, stop command can be issued
- * at any time. stop ispif & camif immediately. */
- v4l2_subdev_notify(vfe32_ctrl->subdev, NOTIFY_ISPIF_STREAM,
- (void *)ISPIF_STREAM(PIX0, ISPIF_OFF_IMMEDIATELY));
+ * at any time. stop camif immediately. */
msm_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
- wmb();
/* axi halt command. */
msm_io_w(AXI_HALT,
@@ -690,8 +687,6 @@
msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
msm_io_w_mb(1, vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
- v4l2_subdev_notify(vfe32_ctrl->subdev, NOTIFY_ISPIF_STREAM,
- (void *)ISPIF_STREAM(PIX0, ISPIF_ON_FRAME_BOUNDARY));
atomic_set(&vfe32_ctrl->vstate, 1);
}
@@ -2094,10 +2089,6 @@
vfe32_AXI_WM_CFG[vfe32_ctrl->
outpath.out1.ch1]);
}
-
- v4l2_subdev_notify(vfe32_ctrl->subdev,
- NOTIFY_ISPIF_STREAM, (void *)
- ISPIF_STREAM(PIX0, ISPIF_OFF_FRAME_BOUNDARY));
msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
@@ -2180,9 +2171,6 @@
if (vfe32_ctrl->vfe_capture_count == 0) {
/* Ensure the write order while writing
to the command register using the barrier */
- v4l2_subdev_notify(vfe32_ctrl->subdev,
- NOTIFY_ISPIF_STREAM, (void *)
- ISPIF_STREAM(PIX0, ISPIF_OFF_FRAME_BOUNDARY));
msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
}
@@ -2833,10 +2821,6 @@
if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
&& (vfe32_ctrl->outpath.out1.
capture_cnt == 0)) {
- v4l2_subdev_notify(vfe32_ctrl->subdev,
- NOTIFY_ISPIF_STREAM, (void *)
- ISPIF_STREAM(PIX0,
- ISPIF_OFF_IMMEDIATELY));
msm_io_w_mb(
CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe32_ctrl->vfebase +
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 0797982..2e0df74 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -11,6 +11,8 @@
*/
#include "msm_sensor.h"
+#include "msm.h"
+#include "msm_ispif.h"
/*=============================================================*/
@@ -220,6 +222,10 @@
int update_type, int res)
{
int32_t rc = 0;
+
+ v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
+ PIX0, ISPIF_OFF_IMMEDIATELY));
s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
msleep(30);
if (update_type == MSM_SENSOR_REG_INIT) {
@@ -240,6 +246,10 @@
mb();
msleep(20);
}
+
+ v4l2_subdev_notify(s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
+ PIX0, ISPIF_ON_FRAME_BOUNDARY));
s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
msleep(30);
}