summaryrefslogtreecommitdiff
path: root/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c')
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
index 8c29a1c9309a..2311672cedb1 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
@@ -936,8 +936,8 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
sink_pad = &isp->pads[RKISP1_ISP_PAD_SINK_VIDEO];
source_pad = media_pad_remote_pad_unique(sink_pad);
if (IS_ERR(source_pad)) {
- dev_dbg(rkisp1->dev, "Failed to get source for ISP: %ld\n",
- PTR_ERR(source_pad));
+ dev_dbg(rkisp1->dev, "Failed to get source for ISP: %pe\n",
+ source_pad);
return -EPIPE;
}
@@ -965,6 +965,7 @@ static int rkisp1_isp_s_stream(struct v4l2_subdev *sd, int enable)
}
isp->frame_sequence = -1;
+ isp->frame_active = false;
sd_state = v4l2_subdev_lock_and_get_active_state(sd);
@@ -1086,12 +1087,15 @@ void rkisp1_isp_unregister(struct rkisp1_device *rkisp1)
* Interrupt handlers
*/
-static void rkisp1_isp_queue_event_sof(struct rkisp1_isp *isp)
+static void rkisp1_isp_sof(struct rkisp1_isp *isp)
{
struct v4l2_event event = {
.type = V4L2_EVENT_FRAME_SYNC,
};
+ isp->frame_sequence++;
+ isp->frame_active = true;
+
event.u.frame_sync.frame_sequence = isp->frame_sequence;
v4l2_event_queue(isp->sd.devnode, &event);
}
@@ -1111,15 +1115,20 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
rkisp1_write(rkisp1, RKISP1_CIF_ISP_ICR, status);
- /* Vertical sync signal, starting generating new frame */
- if (status & RKISP1_CIF_ISP_V_START) {
- rkisp1->isp.frame_sequence++;
- rkisp1_isp_queue_event_sof(&rkisp1->isp);
+ /*
+ * Vertical sync signal, starting new frame. Defer handling of vsync
+ * after RKISP1_CIF_ISP_FRAME if the previous frame was not completed
+ * yet.
+ */
+ if (status & RKISP1_CIF_ISP_V_START && !rkisp1->isp.frame_active) {
+ status &= ~RKISP1_CIF_ISP_V_START;
+ rkisp1_isp_sof(&rkisp1->isp);
if (status & RKISP1_CIF_ISP_FRAME) {
WARN_ONCE(1, "irq delay is too long, buffers might not be in sync\n");
rkisp1->debug.irq_delay++;
}
}
+
if (status & RKISP1_CIF_ISP_PIC_SIZE_ERROR) {
/* Clear pic_size_error */
isp_err = rkisp1_read(rkisp1, RKISP1_CIF_ISP_ERR);
@@ -1138,6 +1147,7 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
if (status & RKISP1_CIF_ISP_FRAME) {
u32 isp_ris;
+ rkisp1->isp.frame_active = false;
rkisp1->debug.complete_frames++;
/* New frame from the sensor received */
@@ -1152,5 +1162,12 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
rkisp1_params_isr(rkisp1);
}
+ /*
+ * Deferred handling of vsync if RKISP1_CIF_ISP_V_START and
+ * RKISP1_CIF_ISP_FRAME occurred in the same irq.
+ */
+ if (status & RKISP1_CIF_ISP_V_START)
+ rkisp1_isp_sof(&rkisp1->isp);
+
return IRQ_HANDLED;
}