[PATCH 16/16] media: rkisp1: Allow a live stream to suspend and resume

Daniel Scally dan.scally at ideasonboard.com
Mon Nov 2 23:40:52 PST 2026


At present the rkisp1 driver makes no provision in its suspend and
resume operations for a live stream. The effect of this is that if
userspace is streaming images through the ISP and suspends to RAM,
upon resuming the system that stream has died, but userspace has no
visibility of that.

To resolve the problem check if a VB2 queue is streaming in runtime
suspend and if so, tell connected subdevices to stop streaming and
mark all buffers as returned to userspace. On runtime resume, check
again if a VB2 queue is streaming and if so set tell the connected
subdevices to stream again. Userspace will - when unfrozen - process
the returned buffers and requeue them ready to receive images.

Because the hardware will have been power-cycled and therefore lost
its configuration, reapply the parameters buffer to restore as much
of that as possible.

Signed-off-by: Daniel Scally <dan.scally at ideasonboard.com>
---
This patch re-applies the last-applied params buffer.

The driver can use the extensible parameters format, in which case
the majority of frames will not have the full configuration. Most of
them will only contain rapidly changing settings like AWB gains, and
in that case unless the scene has not changed at all (which does not
seem very likely) then they will be out of date anyway. If userspace
has configured the extensible format then at this stage the
reapplication of parameters is probably not that useful, but I have a
follow-up series which will handle that more fully.
---
 .../media/platform/rockchip/rkisp1/rkisp1-common.h |  1 +
 .../media/platform/rockchip/rkisp1/rkisp1-dev.c    | 28 ++++++++++++++++++++++
 .../media/platform/rockchip/rkisp1/rkisp1-params.c | 18 ++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
index 8f379a783da1fa97a330a7ec547354eb936cfadd..94f03310e92f110062313bf2a34afb0692d9122c 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-common.h
@@ -697,6 +697,7 @@ void rkisp1_stats_vb2_return_all_buffers(struct rkisp1_stats *stats);
 void rkisp1_params_vb2_return_buffers(struct rkisp1_params *params);
 void rkisp1_return_all_buffers(struct rkisp1_capture *cap,
 			       enum vb2_buffer_state state);
+void rkisp1_params_reapply_config(struct rkisp1_params *params);
 int rkisp1_pipeline_stream_enable(struct rkisp1_capture *cap);
 void rkisp1_pipeline_stream_disable(struct rkisp1_capture *cap);
 
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
index 9f1d0f72ee9bf4364c696d9fdd8febea80d2bcde..d9c7500c92d810763775417a32f6850f48825398 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
@@ -307,6 +307,22 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
 static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
 {
 	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
+	bool active_stream = false;
+
+	for (unsigned int i = 0; i < rkisp1_path_count(rkisp1); i++) {
+		struct rkisp1_capture *cap = &rkisp1->capture_devs[i];
+
+		if (rkisp1_vb2_is_streaming(cap)) {
+			active_stream = true;
+			rkisp1_pipeline_stream_disable(cap);
+			rkisp1_return_all_buffers(cap, VB2_BUF_STATE_ERROR);
+		}
+	}
+
+	if (active_stream) {
+		rkisp1_stats_vb2_return_all_buffers(&rkisp1->stats);
+		rkisp1_params_vb2_return_buffers(&rkisp1->params);
+	}
 
 	rkisp1->irqs_enabled = false;
 	/* Make sure the IRQ handler will see the above */
@@ -333,6 +349,7 @@ static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
 static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
 {
 	struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
+	unsigned int sequence;
 	int ret;
 
 	ret = pinctrl_pm_select_default_state(dev);
@@ -346,6 +363,17 @@ static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
 	/* Make sure the IRQ handler will see the above */
 	mb();
 
+	for (unsigned int i = 0; i < rkisp1_path_count(rkisp1); i++) {
+		struct rkisp1_capture *cap = &rkisp1->capture_devs[i];
+
+		if (rkisp1_vb2_is_streaming(cap)) {
+			sequence = rkisp1->isp.frame_sequence;
+			rkisp1_pipeline_stream_enable(cap);
+			rkisp1_params_reapply_config(&rkisp1->params);
+			rkisp1->isp.frame_sequence = sequence;
+		}
+	}
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
index 1f08b57e616159a389411e13f9217c4f4fcddd57..f440e15afc74c029510e0777a9ec2f6ea4d5be88 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
@@ -2326,6 +2326,24 @@ static void rkisp1_ext_params_config(struct rkisp1_params *params,
 	}
 }
 
+void rkisp1_params_reapply_config(struct rkisp1_params *params)
+{
+	guard(spinlock)(&params->buf.lock);
+
+	if (!params->buf.curr)
+		return;
+
+	if (params->metafmt->dataformat == V4L2_META_FMT_RK_ISP1_PARAMS) {
+		rkisp1_isp_isr_other_config(params, params->buf.curr->cfg);
+		rkisp1_isp_isr_lsc_config(params, params->buf.curr->cfg);
+		rkisp1_isp_isr_meas_config(params, params->buf.curr->cfg);
+	} else {
+		rkisp1_ext_params_config(params, params->buf.curr->cfg,
+					 RKISP1_EXT_PARAMS_BLOCK_GROUP_OTHERS |
+					 RKISP1_EXT_PARAMS_BLOCK_GROUP_LSC);
+	}
+}
+
 static void rkisp1_params_complete_buffer(struct rkisp1_params *params,
 					  struct rkisp1_params_buffer *buf,
 					  unsigned int frame_sequence)

-- 
2.43.0




More information about the linux-arm-kernel mailing list