[v3,37/41] libipa: algorithm: Add a initialize parameter to prepare
diff mbox series

Message ID 20260914140309.3354666-38-stefan.klug@ideasonboard.com
State New
Headers show
Series
  • rkisp1: pipeline rework for PFC
Related show

Commit Message

Stefan Klug Sept. 14, 2026, 2:02 p.m. UTC
In prepare() the paremeters for the ISP block are assembled. Usually there
is an initial step involved when enabling the ISP block for the first time
which is often handled by checking if frame == 0.

In cases of a FCQueue overflow we basically have the same condition as we don't
know the last parameters that were applied to the ISP block.

Add a initialize flag to the prepare function() that can be used to trigger
a full initialization of an ISP block. For now it is only set in case of
frame == 0.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
---
 src/ipa/ipu3/algorithms/af.cpp           | 3 ++-
 src/ipa/ipu3/algorithms/af.h             | 3 ++-
 src/ipa/ipu3/algorithms/agc.cpp          | 3 ++-
 src/ipa/ipu3/algorithms/agc.h            | 3 ++-
 src/ipa/ipu3/algorithms/awb.cpp          | 3 ++-
 src/ipa/ipu3/algorithms/awb.h            | 3 ++-
 src/ipa/ipu3/algorithms/blc.cpp          | 4 +++-
 src/ipa/ipu3/algorithms/blc.h            | 3 ++-
 src/ipa/ipu3/algorithms/tone_mapping.cpp | 4 +++-
 src/ipa/ipu3/algorithms/tone_mapping.h   | 3 ++-
 src/ipa/ipu3/ipu3.cpp                    | 2 +-
 src/ipa/libipa/algorithm.cpp             | 6 ++++++
 src/ipa/libipa/algorithm.h               | 3 ++-
 src/ipa/mali-c55/algorithms/agc.cpp      | 7 ++++---
 src/ipa/mali-c55/algorithms/agc.h        | 3 ++-
 src/ipa/mali-c55/algorithms/awb.cpp      | 7 ++++---
 src/ipa/mali-c55/algorithms/awb.h        | 3 ++-
 src/ipa/mali-c55/algorithms/blc.cpp      | 6 +++---
 src/ipa/mali-c55/algorithms/blc.h        | 3 ++-
 src/ipa/mali-c55/algorithms/ccm.cpp      | 5 +++--
 src/ipa/mali-c55/algorithms/ccm.h        | 3 ++-
 src/ipa/mali-c55/algorithms/lsc.cpp      | 4 ++--
 src/ipa/mali-c55/algorithms/lsc.h        | 3 ++-
 src/ipa/mali-c55/mali-c55.cpp            | 3 ++-
 src/ipa/rkisp1/algorithms/agc.cpp        | 7 ++++---
 src/ipa/rkisp1/algorithms/agc.h          | 3 ++-
 src/ipa/rkisp1/algorithms/awb.cpp        | 7 ++++---
 src/ipa/rkisp1/algorithms/awb.h          | 3 ++-
 src/ipa/rkisp1/algorithms/blc.cpp        | 7 ++++---
 src/ipa/rkisp1/algorithms/blc.h          | 3 ++-
 src/ipa/rkisp1/algorithms/ccm.cpp        | 3 ++-
 src/ipa/rkisp1/algorithms/ccm.h          | 3 ++-
 src/ipa/rkisp1/algorithms/compress.cpp   | 3 ++-
 src/ipa/rkisp1/algorithms/compress.h     | 3 ++-
 src/ipa/rkisp1/algorithms/cproc.cpp      | 5 +++--
 src/ipa/rkisp1/algorithms/cproc.h        | 3 ++-
 src/ipa/rkisp1/algorithms/dpcc.cpp       | 7 ++++---
 src/ipa/rkisp1/algorithms/dpcc.h         | 3 ++-
 src/ipa/rkisp1/algorithms/dpf.cpp        | 7 ++++---
 src/ipa/rkisp1/algorithms/dpf.h          | 3 ++-
 src/ipa/rkisp1/algorithms/filter.cpp     | 5 +++--
 src/ipa/rkisp1/algorithms/filter.h       | 3 ++-
 src/ipa/rkisp1/algorithms/goc.cpp        | 5 +++--
 src/ipa/rkisp1/algorithms/goc.h          | 3 ++-
 src/ipa/rkisp1/algorithms/gsl.cpp        | 7 ++++---
 src/ipa/rkisp1/algorithms/gsl.h          | 3 ++-
 src/ipa/rkisp1/algorithms/lsc.cpp        | 5 +++--
 src/ipa/rkisp1/algorithms/lsc.h          | 3 ++-
 src/ipa/rkisp1/algorithms/lux.cpp        | 3 ++-
 src/ipa/rkisp1/algorithms/lux.h          | 3 ++-
 src/ipa/rkisp1/algorithms/wdr.cpp        | 3 ++-
 src/ipa/rkisp1/algorithms/wdr.h          | 3 ++-
 src/ipa/rkisp1/rkisp1.cpp                | 4 +++-
 src/ipa/softisp/algorithms/adjust.cpp    | 3 ++-
 src/ipa/softisp/algorithms/adjust.h      | 3 ++-
 src/ipa/softisp/algorithms/agc.cpp       | 4 +++-
 src/ipa/softisp/algorithms/agc.h         | 3 ++-
 src/ipa/softisp/algorithms/awb.cpp       | 3 ++-
 src/ipa/softisp/algorithms/awb.h         | 3 ++-
 src/ipa/softisp/algorithms/blc.cpp       | 3 ++-
 src/ipa/softisp/algorithms/blc.h         | 3 ++-
 src/ipa/softisp/algorithms/ccm.cpp       | 4 +++-
 src/ipa/softisp/algorithms/ccm.h         | 3 ++-
 src/ipa/softisp/softisp.cpp              | 2 +-
 64 files changed, 157 insertions(+), 87 deletions(-)

Patch
diff mbox series

diff --git a/src/ipa/ipu3/algorithms/af.cpp b/src/ipa/ipu3/algorithms/af.cpp
index e796b06a2071..9437f45f9932 100644
--- a/src/ipa/ipu3/algorithms/af.cpp
+++ b/src/ipa/ipu3/algorithms/af.cpp
@@ -184,7 +184,8 @@  int Af::configure(IPAContext &context, const IPAConfigInfo &configInfo)
 void Af::prepare(IPAContext &context,
 		 [[maybe_unused]] const uint32_t frame,
 		 [[maybe_unused]] IPAFrameContext &frameContext,
-		 ipu3_uapi_params *params)
+		 ipu3_uapi_params *params,
+		 [[maybe_unused]] bool initialize)
 {
 	const struct ipu3_uapi_grid_config &grid = context.configuration.af.afGrid;
 	params->acc_param.af.grid_cfg = grid;
diff --git a/src/ipa/ipu3/algorithms/af.h b/src/ipa/ipu3/algorithms/af.h
index 320b674962ad..d616cd45a210 100644
--- a/src/ipa/ipu3/algorithms/af.h
+++ b/src/ipa/ipu3/algorithms/af.h
@@ -33,7 +33,8 @@  public:
 	int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     ipu3_uapi_params *params) override;
+		     ipu3_uapi_params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const ipu3_uapi_stats_3a *stats,
diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp
index 67c910049a6d..de5f47f7f587 100644
--- a/src/ipa/ipu3/algorithms/agc.cpp
+++ b/src/ipa/ipu3/algorithms/agc.cpp
@@ -109,7 +109,8 @@  void Agc::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t fram
  */
 void Agc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 		  IPAFrameContext &frameContext,
-		  [[maybe_unused]] ipu3_uapi_params *params)
+		  [[maybe_unused]] ipu3_uapi_params *params,
+		  [[maybe_unused]] bool initialize)
 {
 	agc_.prepare(context.configuration.agc, context.activeState.agc, frameContext.agc);
 }
diff --git a/src/ipa/ipu3/algorithms/agc.h b/src/ipa/ipu3/algorithms/agc.h
index 634b1f8a7a8f..e8034ce14105 100644
--- a/src/ipa/ipu3/algorithms/agc.h
+++ b/src/ipa/ipu3/algorithms/agc.h
@@ -36,7 +36,8 @@  public:
 			  IPAFrameContext &frameContext, const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     ipu3_uapi_params *params)  override;
+		     ipu3_uapi_params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const ipu3_uapi_stats_3a *stats,
diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp
index 55de05d9e39f..d5b20f890a9f 100644
--- a/src/ipa/ipu3/algorithms/awb.cpp
+++ b/src/ipa/ipu3/algorithms/awb.cpp
@@ -249,7 +249,8 @@  constexpr uint16_t Awb::gainValue(double gain)
 void Awb::prepare(IPAContext &context,
 		  [[maybe_unused]] const uint32_t frame,
 		  [[maybe_unused]] IPAFrameContext &frameContext,
-		  ipu3_uapi_params *params)
+		  ipu3_uapi_params *params,
+		  [[maybe_unused]] bool initialize)
 {
 	/*
 	 * Green saturation thresholds are reduced because we are using the
diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h
index dbf69c9073a1..0b26a669a034 100644
--- a/src/ipa/ipu3/algorithms/awb.h
+++ b/src/ipa/ipu3/algorithms/awb.h
@@ -43,7 +43,8 @@  public:
 	int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     ipu3_uapi_params *params) override;
+		     ipu3_uapi_params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const ipu3_uapi_stats_3a *stats,
diff --git a/src/ipa/ipu3/algorithms/blc.cpp b/src/ipa/ipu3/algorithms/blc.cpp
index 35748fb2ce85..6164738256dd 100644
--- a/src/ipa/ipu3/algorithms/blc.cpp
+++ b/src/ipa/ipu3/algorithms/blc.cpp
@@ -40,6 +40,7 @@  BlackLevelCorrection::BlackLevelCorrection()
  * \param[in] frame The frame context sequence number
  * \param[in] frameContext The FrameContext for this frame
  * \param[out] params The IPU3 parameters
+ * \param[in] initialize True if the ISP module should be reinitialzed
  *
  * Populate the IPU3 parameter structure with the correction values for each
  * channel and enable the corresponding ImgU block processing.
@@ -47,7 +48,8 @@  BlackLevelCorrection::BlackLevelCorrection()
 void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context,
 				   [[maybe_unused]] const uint32_t frame,
 				   [[maybe_unused]] IPAFrameContext &frameContext,
-				   ipu3_uapi_params *params)
+				   ipu3_uapi_params *params,
+				   [[maybe_unused]] bool initialize)
 {
 	/*
 	 * The Optical Black Level correction values
diff --git a/src/ipa/ipu3/algorithms/blc.h b/src/ipa/ipu3/algorithms/blc.h
index 6274804548bb..65ce3cbae0f2 100644
--- a/src/ipa/ipu3/algorithms/blc.h
+++ b/src/ipa/ipu3/algorithms/blc.h
@@ -20,7 +20,8 @@  public:
 
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     ipu3_uapi_params *params) override;
+		     ipu3_uapi_params *params,
+		     bool initialize) override;
 };
 
 } /* namespace ipa::ipu3::algorithms */
diff --git a/src/ipa/ipu3/algorithms/tone_mapping.cpp b/src/ipa/ipu3/algorithms/tone_mapping.cpp
index 160338c13944..74a30b729547 100644
--- a/src/ipa/ipu3/algorithms/tone_mapping.cpp
+++ b/src/ipa/ipu3/algorithms/tone_mapping.cpp
@@ -53,6 +53,7 @@  int ToneMapping::configure(IPAContext &context,
  * \param[in] frame The frame context sequence number
  * \param[in] frameContext The FrameContext for this frame
  * \param[out] params The IPU3 parameters
+ * \param[in] initialize True if the ISP module should be reinitialzed
  *
  * Populate the IPU3 parameter structure with our tone mapping look up table and
  * enable the gamma control module in the processing blocks.
@@ -60,7 +61,8 @@  int ToneMapping::configure(IPAContext &context,
 void ToneMapping::prepare([[maybe_unused]] IPAContext &context,
 			  [[maybe_unused]] const uint32_t frame,
 			  [[maybe_unused]] IPAFrameContext &frameContext,
-			  ipu3_uapi_params *params)
+			  ipu3_uapi_params *params,
+			  [[maybe_unused]] bool initialize)
 {
 	/* Copy the calculated LUT into the parameters buffer. */
 	memcpy(params->acc_param.gamma.gc_lut.lut,
diff --git a/src/ipa/ipu3/algorithms/tone_mapping.h b/src/ipa/ipu3/algorithms/tone_mapping.h
index b2b380108e01..f9615c6bec88 100644
--- a/src/ipa/ipu3/algorithms/tone_mapping.h
+++ b/src/ipa/ipu3/algorithms/tone_mapping.h
@@ -20,7 +20,8 @@  public:
 
 	int configure(IPAContext &context, const IPAConfigInfo &configInfo) override;
 	void prepare(IPAContext &context, const uint32_t frame,
-		     IPAFrameContext &frameContext, ipu3_uapi_params *params) override;
+		     IPAFrameContext &frameContext, ipu3_uapi_params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const ipu3_uapi_stats_3a *stats,
diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
index ed873784c730..0705cecc23b2 100644
--- a/src/ipa/ipu3/ipu3.cpp
+++ b/src/ipa/ipu3/ipu3.cpp
@@ -477,7 +477,7 @@  void IPAIPU3::computeParams(const uint32_t frame, const uint32_t bufferId)
 	ASSERT(frameContext);
 
 	for (const auto &algo : algorithms())
-		algo->prepare(context_, frame, *frameContext, params);
+		algo->prepare(context_, frame, *frameContext, params, frame == 0);
 
 	paramsComputed.emit(frame);
 }
diff --git a/src/ipa/libipa/algorithm.cpp b/src/ipa/libipa/algorithm.cpp
index e1869dc1fe78..72b47a42a890 100644
--- a/src/ipa/libipa/algorithm.cpp
+++ b/src/ipa/libipa/algorithm.cpp
@@ -99,6 +99,7 @@  namespace ipa {
  * \param[in] frame The frame context sequence number
  * \param[in] frameContext The FrameContext for this frame
  * \param[out] params The ISP specific parameters
+ * \param[in] initialize True if the ISP module should be reinitialzed
  *
  * This function is called for every frame when the camera is running before it
  * is processed by the ISP to prepare the ISP processing parameters and the
@@ -112,6 +113,11 @@  namespace ipa {
  * necessary to configure the sensor. After prepare() the \a frameContext for
  * this frame shall be treated read only.
  *
+ * The \a initialize parameter indicates if the ISP module should be fully
+ * initialized. This is always set on the first frame and in rare cases when
+ * frame contexts were overwritten and the ISP module has to be reinitialized to
+ * guarantee a defined state.
+ *
  * \todo: For offline ISPs there might be use cases where it is beneficial to
  * separate the calculation of sensor parameters from the calculation of ISP
  * paremeters. This is currently not supported.
diff --git a/src/ipa/libipa/algorithm.h b/src/ipa/libipa/algorithm.h
index 4ddb16ef3920..140148c81db5 100644
--- a/src/ipa/libipa/algorithm.h
+++ b/src/ipa/libipa/algorithm.h
@@ -48,7 +48,8 @@  public:
 	virtual void prepare([[maybe_unused]] typename Module::Context &context,
 			     [[maybe_unused]] const uint32_t frame,
 			     [[maybe_unused]] typename Module::FrameContext &frameContext,
-			     [[maybe_unused]] typename Module::Params *params)
+			     [[maybe_unused]] typename Module::Params *params,
+			     [[maybe_unused]] bool initialize)
 	{
 	}
 
diff --git a/src/ipa/mali-c55/algorithms/agc.cpp b/src/ipa/mali-c55/algorithms/agc.cpp
index 5684b4df954c..b5c86c44dd28 100644
--- a/src/ipa/mali-c55/algorithms/agc.cpp
+++ b/src/ipa/mali-c55/algorithms/agc.cpp
@@ -204,12 +204,13 @@  void Agc::fillWeightsArrayBuffer(MaliC55Params *params, const enum MaliC55Blocks
 	std::fill(weights.begin(), weights.end(), 1);
 }
 
-void Agc::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, MaliC55Params *params)
+void Agc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+		  IPAFrameContext &frameContext, MaliC55Params *params,
+		  bool initialize)
 {
 	agc_.prepare(context.configuration.agc, context.activeState.agc, frameContext.agc);
 
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	fillParamsBuffer(params, MaliC55Blocks::AexpHist);
diff --git a/src/ipa/mali-c55/algorithms/agc.h b/src/ipa/mali-c55/algorithms/agc.h
index 809a57c53acc..5c7312804e3b 100644
--- a/src/ipa/mali-c55/algorithms/agc.h
+++ b/src/ipa/mali-c55/algorithms/agc.h
@@ -57,7 +57,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     MaliC55Params *params) override;
+		     MaliC55Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const mali_c55_stats_buffer *stats,
diff --git a/src/ipa/mali-c55/algorithms/awb.cpp b/src/ipa/mali-c55/algorithms/awb.cpp
index 353a9f0d3f97..1d2dc5d0d981 100644
--- a/src/ipa/mali-c55/algorithms/awb.cpp
+++ b/src/ipa/mali-c55/algorithms/awb.cpp
@@ -151,8 +151,9 @@  void Awb::fillConfigParamBlock(MaliC55Params *params)
 /**
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
-void Awb::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, MaliC55Params *params)
+void Awb::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+		  IPAFrameContext &frameContext, MaliC55Params *params,
+		  bool initialize)
 {
 	awbAlgo_.prepare(context.activeState.awb, frameContext.awb);
 
@@ -176,7 +177,7 @@  void Awb::prepare(IPAContext &context, const uint32_t frame,
 	block->gain11 = UQ<4, 8>(static_cast<float>(frameContext.awb.gains.b()))
 				.quantized();
 
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	fillConfigParamBlock(params);
diff --git a/src/ipa/mali-c55/algorithms/awb.h b/src/ipa/mali-c55/algorithms/awb.h
index 4be7a5917ac5..c41f63daa4f1 100644
--- a/src/ipa/mali-c55/algorithms/awb.h
+++ b/src/ipa/mali-c55/algorithms/awb.h
@@ -39,7 +39,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     MaliC55Params *params) override;
+		     MaliC55Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const mali_c55_stats_buffer *stats,
diff --git a/src/ipa/mali-c55/algorithms/blc.cpp b/src/ipa/mali-c55/algorithms/blc.cpp
index 591a5eaf2dc8..2e6ff7f36be7 100644
--- a/src/ipa/mali-c55/algorithms/blc.cpp
+++ b/src/ipa/mali-c55/algorithms/blc.cpp
@@ -83,11 +83,11 @@  int BlackLevelCorrection::configure(IPAContext &context,
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
 void BlackLevelCorrection::prepare([[maybe_unused]] IPAContext &context,
-				   const uint32_t frame,
+				   [[maybe_unused]] const uint32_t frame,
 				   [[maybe_unused]] IPAFrameContext &frameContext,
-				   MaliC55Params *params)
+				   MaliC55Params *params, bool initialize)
 {
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	if (!tuningParameters_)
diff --git a/src/ipa/mali-c55/algorithms/blc.h b/src/ipa/mali-c55/algorithms/blc.h
index bce343e20c55..053a88e3b7b0 100644
--- a/src/ipa/mali-c55/algorithms/blc.h
+++ b/src/ipa/mali-c55/algorithms/blc.h
@@ -23,7 +23,8 @@  public:
 		      const IPACameraSensorInfo &configInfo) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     MaliC55Params *params) override;
+		     MaliC55Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const mali_c55_stats_buffer *stats,
diff --git a/src/ipa/mali-c55/algorithms/ccm.cpp b/src/ipa/mali-c55/algorithms/ccm.cpp
index b5196a7ee85b..994fa5bf3572 100644
--- a/src/ipa/mali-c55/algorithms/ccm.cpp
+++ b/src/ipa/mali-c55/algorithms/ccm.cpp
@@ -128,7 +128,8 @@  void Ccm::setParameters(MaliC55Params *params, const IPAFrameContext &frameConte
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
 void Ccm::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, MaliC55Params *params)
+		  IPAFrameContext &frameContext, MaliC55Params *params,
+		  bool initialize)
 {
 	if (!frameContext.awb.autoEnabled) {
 		setParameters(params, frameContext);
@@ -141,7 +142,7 @@  void Ccm::prepare(IPAContext &context, const uint32_t frame,
 	 * changes of a certain amount.
 	 */
 	float ct = frameContext.awb.colourTemperature * 1.0f;
-	if (frame > 0 && (ct < lastCt_ * 1.2 && ct > lastCt_ * 0.8)) {
+	if (!initialize && (ct < lastCt_ * 1.2 && ct > lastCt_ * 0.8)) {
 		frameContext.ccm.ccm = context.activeState.ccm.automatic.ccm;
 		frameContext.ccm.offsets = context.activeState.ccm.automatic.offsets;
 		lastCt_ = ct;
diff --git a/src/ipa/mali-c55/algorithms/ccm.h b/src/ipa/mali-c55/algorithms/ccm.h
index 73649204a7ee..4916f260b827 100644
--- a/src/ipa/mali-c55/algorithms/ccm.h
+++ b/src/ipa/mali-c55/algorithms/ccm.h
@@ -39,7 +39,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     MaliC55Params *params) override;
+		     MaliC55Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const mali_c55_stats_buffer *stats,
diff --git a/src/ipa/mali-c55/algorithms/lsc.cpp b/src/ipa/mali-c55/algorithms/lsc.cpp
index fff0dc7d0e64..a39089bdd429 100644
--- a/src/ipa/mali-c55/algorithms/lsc.cpp
+++ b/src/ipa/mali-c55/algorithms/lsc.cpp
@@ -183,7 +183,7 @@  std::tuple<uint8_t, uint8_t> Lsc::findBankAndAlpha(uint32_t ct) const
 
 void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 		  [[maybe_unused]] IPAFrameContext &frameContext,
-		  MaliC55Params *params)
+		  MaliC55Params *params, bool initialize)
 {
 	/*
 	 * For each frame we assess the colour temperature of the **last** frame
@@ -208,7 +208,7 @@  void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 
 	fillSelectionParamsBlock(params, bank, alpha);
 
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	/*
diff --git a/src/ipa/mali-c55/algorithms/lsc.h b/src/ipa/mali-c55/algorithms/lsc.h
index 5f752eebaef5..12069850a6e0 100644
--- a/src/ipa/mali-c55/algorithms/lsc.h
+++ b/src/ipa/mali-c55/algorithms/lsc.h
@@ -36,7 +36,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     MaliC55Params *params) override;
+		     MaliC55Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const mali_c55_stats_buffer *stats,
diff --git a/src/ipa/mali-c55/mali-c55.cpp b/src/ipa/mali-c55/mali-c55.cpp
index 7ee4a9349af1..8a93dec2f66c 100644
--- a/src/ipa/mali-c55/mali-c55.cpp
+++ b/src/ipa/mali-c55/mali-c55.cpp
@@ -249,7 +249,8 @@  void IPAMaliC55::fillParams(unsigned int request,
 	ASSERT(frameContext);
 
 	for (const auto &algo : algorithms())
-		algo->prepare(context_, request, *frameContext, &params);
+		algo->prepare(context_, request, *frameContext, &params,
+			      frameContext->frame() == 0);
 
 	paramsComputed.emit(request, params.bytesused());
 }
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index 34e186d8b68f..41680e5c4ffd 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -206,8 +206,9 @@  void Agc::queueRequest(IPAContext &context,
 /**
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
-void Agc::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, RkISP1Params *params)
+void Agc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+		  IPAFrameContext &frameContext, RkISP1Params *params,
+		  bool initialize)
 {
 	agc_.prepare(context.configuration.agc, context.activeState.agc, frameContext.agc);
 
@@ -216,7 +217,7 @@  void Agc::prepare(IPAContext &context, const uint32_t frame,
 		frameContext.compress.gain = frameContext.agc.quantizationGain;
 	}
 
-	if (frame > 0 && !frameContext.agc.updateMetering)
+	if (!initialize && !frameContext.agc.updateMetering)
 		return;
 
 	/*
diff --git a/src/ipa/rkisp1/algorithms/agc.h b/src/ipa/rkisp1/algorithms/agc.h
index b8d59352e70d..5704d162919b 100644
--- a/src/ipa/rkisp1/algorithms/agc.h
+++ b/src/ipa/rkisp1/algorithms/agc.h
@@ -35,7 +35,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp
index f39153355a12..bc4ace26624a 100644
--- a/src/ipa/rkisp1/algorithms/awb.cpp
+++ b/src/ipa/rkisp1/algorithms/awb.cpp
@@ -122,8 +122,9 @@  void Awb::queueRequest(IPAContext &context, const uint32_t frame,
 /**
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
-void Awb::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, RkISP1Params *params)
+void Awb::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+		  IPAFrameContext &frameContext, RkISP1Params *params,
+		  bool initialize)
 {
 	awbAlgo_.prepare(context.activeState.awb, frameContext.awb);
 
@@ -136,7 +137,7 @@  void Awb::prepare(IPAContext &context, const uint32_t frame,
 	gainConfig->gain_green_r = std::clamp<int>(256 * frameContext.awb.gains.g(), 0, 0x3ff);
 
 	/* If we have already set the AWB measurement parameters, return. */
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	auto awbConfig = params->block<BlockType::Awb>();
diff --git a/src/ipa/rkisp1/algorithms/awb.h b/src/ipa/rkisp1/algorithms/awb.h
index 89a3e37b20f9..f4d1b35eea03 100644
--- a/src/ipa/rkisp1/algorithms/awb.h
+++ b/src/ipa/rkisp1/algorithms/awb.h
@@ -39,7 +39,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/blc.cpp b/src/ipa/rkisp1/algorithms/blc.cpp
index 1ed700a205c8..b7c05c6d4892 100644
--- a/src/ipa/rkisp1/algorithms/blc.cpp
+++ b/src/ipa/rkisp1/algorithms/blc.cpp
@@ -127,14 +127,15 @@  int BlackLevelCorrection::configure(IPAContext &context,
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
 void BlackLevelCorrection::prepare(IPAContext &context,
-				   const uint32_t frame,
+				   [[maybe_unused]] const uint32_t frame,
 				   [[maybe_unused]] IPAFrameContext &frameContext,
-				   RkISP1Params *params)
+				   RkISP1Params *params,
+				   bool initialize)
 {
 	if (context.configuration.raw)
 		return;
 
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	if (!supported_)
diff --git a/src/ipa/rkisp1/algorithms/blc.h b/src/ipa/rkisp1/algorithms/blc.h
index 3b2b0ce6e2a8..6d0e9c2c7523 100644
--- a/src/ipa/rkisp1/algorithms/blc.h
+++ b/src/ipa/rkisp1/algorithms/blc.h
@@ -24,7 +24,8 @@  public:
 		      const IPACameraSensorInfo &configInfo) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/ccm.cpp b/src/ipa/rkisp1/algorithms/ccm.cpp
index 0e54c987104d..9c79c5f7eb18 100644
--- a/src/ipa/rkisp1/algorithms/ccm.cpp
+++ b/src/ipa/rkisp1/algorithms/ccm.cpp
@@ -92,7 +92,8 @@  void Ccm::setParameters(RkISP1Params *params, IPAFrameContext &context)
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
 void Ccm::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, RkISP1Params *params)
+		  IPAFrameContext &frameContext, RkISP1Params *params,
+		  [[maybe_unused]] bool initialize)
 {
 	if (frameContext.awb.autoEnabled)
 		ccmAlgo_.prepare(context.activeState.ccm, frameContext.ccm,
diff --git a/src/ipa/rkisp1/algorithms/ccm.h b/src/ipa/rkisp1/algorithms/ccm.h
index 6689c42092f3..fc855793ddfc 100644
--- a/src/ipa/rkisp1/algorithms/ccm.h
+++ b/src/ipa/rkisp1/algorithms/ccm.h
@@ -39,7 +39,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/compress.cpp b/src/ipa/rkisp1/algorithms/compress.cpp
index 2afa449608b7..9c9eb6acbfba 100644
--- a/src/ipa/rkisp1/algorithms/compress.cpp
+++ b/src/ipa/rkisp1/algorithms/compress.cpp
@@ -67,7 +67,8 @@  int Compress::configure(IPAContext &context,
 void Compress::prepare([[maybe_unused]] IPAContext &context,
 		       [[maybe_unused]] const uint32_t frame,
 		       IPAFrameContext &frameContext,
-		       RkISP1Params *params)
+		       RkISP1Params *params,
+		       [[maybe_unused]] bool initialize)
 {
 	if (!context.configuration.compress.supported)
 		return;
diff --git a/src/ipa/rkisp1/algorithms/compress.h b/src/ipa/rkisp1/algorithms/compress.h
index 87797b8ebcc5..758b82108a2b 100644
--- a/src/ipa/rkisp1/algorithms/compress.h
+++ b/src/ipa/rkisp1/algorithms/compress.h
@@ -23,7 +23,8 @@  public:
 		      const IPACameraSensorInfo &configInfo) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 };
 
 } /* namespace ipa::rkisp1::algorithms */
diff --git a/src/ipa/rkisp1/algorithms/cproc.cpp b/src/ipa/rkisp1/algorithms/cproc.cpp
index fae7510de07b..86fe29ac606f 100644
--- a/src/ipa/rkisp1/algorithms/cproc.cpp
+++ b/src/ipa/rkisp1/algorithms/cproc.cpp
@@ -198,10 +198,11 @@  void ColorProcessing::queueRequest(IPAContext &context,
 void ColorProcessing::prepare([[maybe_unused]] IPAContext &context,
 			      [[maybe_unused]] const uint32_t frame,
 			      IPAFrameContext &frameContext,
-			      RkISP1Params *params)
+			      RkISP1Params *params,
+			      bool initialize)
 {
 	/* Check if the algorithm configuration has been updated. */
-	if (!frameContext.cproc.update)
+	if (!frameContext.cproc.update && !initialize)
 		return;
 
 	auto config = params->block<BlockType::Cproc>();
diff --git a/src/ipa/rkisp1/algorithms/cproc.h b/src/ipa/rkisp1/algorithms/cproc.h
index 1387d4565d3f..cd01da57977c 100644
--- a/src/ipa/rkisp1/algorithms/cproc.h
+++ b/src/ipa/rkisp1/algorithms/cproc.h
@@ -29,7 +29,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/dpcc.cpp b/src/ipa/rkisp1/algorithms/dpcc.cpp
index 20b35d29cbcd..806c20e82b09 100644
--- a/src/ipa/rkisp1/algorithms/dpcc.cpp
+++ b/src/ipa/rkisp1/algorithms/dpcc.cpp
@@ -230,11 +230,12 @@  int DefectPixelClusterCorrection::init([[maybe_unused]] IPAContext &context,
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
 void DefectPixelClusterCorrection::prepare([[maybe_unused]] IPAContext &context,
-					   const uint32_t frame,
+					   [[maybe_unused]] const uint32_t frame,
 					   [[maybe_unused]] IPAFrameContext &frameContext,
-					   RkISP1Params *params)
+					   RkISP1Params *params,
+					   bool initialize)
 {
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	auto config = params->block<BlockType::Dpcc>();
diff --git a/src/ipa/rkisp1/algorithms/dpcc.h b/src/ipa/rkisp1/algorithms/dpcc.h
index 50b62e9bab3f..06c47035c8dd 100644
--- a/src/ipa/rkisp1/algorithms/dpcc.h
+++ b/src/ipa/rkisp1/algorithms/dpcc.h
@@ -22,7 +22,8 @@  public:
 	int init(IPAContext &context, const ValueNode &tuningData) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 
 private:
 	rkisp1_cif_isp_dpcc_config config_;
diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index b2c9ec568b97..9ad1fb84a75d 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -217,10 +217,11 @@  void Dpf::queueRequest(IPAContext &context,
 /**
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
-void Dpf::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, RkISP1Params *params)
+void Dpf::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+		  IPAFrameContext &frameContext, RkISP1Params *params,
+		  bool initialize)
 {
-	if (!frameContext.dpf.update && frame > 0)
+	if (!frameContext.dpf.update && !initialize)
 		return;
 
 	auto config = params->block<BlockType::Dpf>();
diff --git a/src/ipa/rkisp1/algorithms/dpf.h b/src/ipa/rkisp1/algorithms/dpf.h
index b07067cec0a5..5edb633d5100 100644
--- a/src/ipa/rkisp1/algorithms/dpf.h
+++ b/src/ipa/rkisp1/algorithms/dpf.h
@@ -27,7 +27,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 
 private:
 	struct rkisp1_cif_isp_dpf_config config_;
diff --git a/src/ipa/rkisp1/algorithms/filter.cpp b/src/ipa/rkisp1/algorithms/filter.cpp
index 2e9b4e285503..38bacce883ed 100644
--- a/src/ipa/rkisp1/algorithms/filter.cpp
+++ b/src/ipa/rkisp1/algorithms/filter.cpp
@@ -115,10 +115,11 @@  void Filter::queueRequest(IPAContext &context,
  */
 void Filter::prepare([[maybe_unused]] IPAContext &context,
 		     [[maybe_unused]] const uint32_t frame,
-		     IPAFrameContext &frameContext, RkISP1Params *params)
+		     IPAFrameContext &frameContext, RkISP1Params *params,
+		     bool initialize)
 {
 	/* Check if the algorithm configuration has been updated. */
-	if (!frameContext.filter.update)
+	if (!frameContext.filter.update && !initialize)
 		return;
 
 	static constexpr uint16_t filt_fac_sh0[] = {
diff --git a/src/ipa/rkisp1/algorithms/filter.h b/src/ipa/rkisp1/algorithms/filter.h
index 9f0188da7880..3b9eb87896e8 100644
--- a/src/ipa/rkisp1/algorithms/filter.h
+++ b/src/ipa/rkisp1/algorithms/filter.h
@@ -27,7 +27,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 };
 
 } /* namespace ipa::rkisp1::algorithms */
diff --git a/src/ipa/rkisp1/algorithms/goc.cpp b/src/ipa/rkisp1/algorithms/goc.cpp
index e8f64bf3d5e0..96e5d1ceb831 100644
--- a/src/ipa/rkisp1/algorithms/goc.cpp
+++ b/src/ipa/rkisp1/algorithms/goc.cpp
@@ -99,12 +99,13 @@  void GammaOutCorrection::queueRequest(IPAContext &context, const uint32_t frame,
 void GammaOutCorrection::prepare(IPAContext &context,
 				 [[maybe_unused]] const uint32_t frame,
 				 IPAFrameContext &frameContext,
-				 RkISP1Params *params)
+				 RkISP1Params *params,
+				 bool initialize)
 {
 	ASSERT(context.hw.numGammaOutSamples ==
 	       RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10);
 
-	if (!frameContext.goc.update)
+	if (!frameContext.goc.update && !initialize)
 		return;
 
 	/*
diff --git a/src/ipa/rkisp1/algorithms/goc.h b/src/ipa/rkisp1/algorithms/goc.h
index bd79fe19cc86..0cb419aa89aa 100644
--- a/src/ipa/rkisp1/algorithms/goc.h
+++ b/src/ipa/rkisp1/algorithms/goc.h
@@ -28,7 +28,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/gsl.cpp b/src/ipa/rkisp1/algorithms/gsl.cpp
index d83aab8506f3..cd505dce73cf 100644
--- a/src/ipa/rkisp1/algorithms/gsl.cpp
+++ b/src/ipa/rkisp1/algorithms/gsl.cpp
@@ -117,11 +117,12 @@  int GammaSensorLinearization::init([[maybe_unused]] IPAContext &context,
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
 void GammaSensorLinearization::prepare([[maybe_unused]] IPAContext &context,
-				       const uint32_t frame,
+				       [[maybe_unused]] const uint32_t frame,
 				       [[maybe_unused]] IPAFrameContext &frameContext,
-				       RkISP1Params *params)
+				       RkISP1Params *params,
+				       bool initialize)
 {
-	if (frame > 0)
+	if (!initialize)
 		return;
 
 	auto config = params->block<BlockType::Sdg>();
diff --git a/src/ipa/rkisp1/algorithms/gsl.h b/src/ipa/rkisp1/algorithms/gsl.h
index 3ef5630713ab..a9aefe501960 100644
--- a/src/ipa/rkisp1/algorithms/gsl.h
+++ b/src/ipa/rkisp1/algorithms/gsl.h
@@ -22,7 +22,8 @@  public:
 	int init(IPAContext &context, const ValueNode &tuningData) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 
 private:
 	uint32_t gammaDx_[2];
diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
index 36f9a344ed3b..e965dfb64239 100644
--- a/src/ipa/rkisp1/algorithms/lsc.cpp
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -206,13 +206,14 @@  void LensShadingCorrection::queueRequest(IPAContext &context,
 void LensShadingCorrection::prepare([[maybe_unused]] IPAContext &context,
 				    [[maybe_unused]] const uint32_t frame,
 				    IPAFrameContext &frameContext,
-				    RkISP1Params *params)
+				    RkISP1Params *params,
+				    bool initialize)
 {
 	uint32_t ct = frameContext.awb.colourTemperature;
 	unsigned int quantizedCt = quantize(ct, kColourTemperatureQuantization);
 
 	/* Check if we can skip the update. */
-	if (!frameContext.lsc.update) {
+	if (!frameContext.lsc.update && !initialize) {
 		if (!frameContext.lsc.enabled)
 			return;
 
diff --git a/src/ipa/rkisp1/algorithms/lsc.h b/src/ipa/rkisp1/algorithms/lsc.h
index c1f8904426c0..7ea986ae1ca8 100644
--- a/src/ipa/rkisp1/algorithms/lsc.h
+++ b/src/ipa/rkisp1/algorithms/lsc.h
@@ -35,7 +35,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/lux.cpp b/src/ipa/rkisp1/algorithms/lux.cpp
index ce6928a55d2b..eabeecdb4785 100644
--- a/src/ipa/rkisp1/algorithms/lux.cpp
+++ b/src/ipa/rkisp1/algorithms/lux.cpp
@@ -51,7 +51,8 @@  int Lux::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData)
  */
 void Lux::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
 		  IPAFrameContext &frameContext,
-		  [[maybe_unused]] RkISP1Params *params)
+		  [[maybe_unused]] RkISP1Params *params,
+		  [[maybe_unused]] bool initialize)
 {
 	frameContext.lux.lux = context.activeState.lux.lux;
 }
diff --git a/src/ipa/rkisp1/algorithms/lux.h b/src/ipa/rkisp1/algorithms/lux.h
index 8cb35cbae20d..6cb4653a1fa1 100644
--- a/src/ipa/rkisp1/algorithms/lux.h
+++ b/src/ipa/rkisp1/algorithms/lux.h
@@ -25,7 +25,8 @@  public:
 	int init(IPAContext &context, const ValueNode &tuningData) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/algorithms/wdr.cpp b/src/ipa/rkisp1/algorithms/wdr.cpp
index c3d73da2c5b2..046495a2f7b5 100644
--- a/src/ipa/rkisp1/algorithms/wdr.cpp
+++ b/src/ipa/rkisp1/algorithms/wdr.cpp
@@ -394,7 +394,8 @@  void WideDynamicRange::queueRequest([[maybe_unused]] IPAContext &context,
 void WideDynamicRange::prepare(IPAContext &context,
 			       [[maybe_unused]] const uint32_t frame,
 			       IPAFrameContext &frameContext,
-			       RkISP1Params *params)
+			       RkISP1Params *params,
+			       [[maybe_unused]] bool initialize)
 {
 	if (!params) {
 		LOG(RkISP1Wdr, Warning) << "Params is null";
diff --git a/src/ipa/rkisp1/algorithms/wdr.h b/src/ipa/rkisp1/algorithms/wdr.h
index f79de66fe73b..7cfd13c8e8aa 100644
--- a/src/ipa/rkisp1/algorithms/wdr.h
+++ b/src/ipa/rkisp1/algorithms/wdr.h
@@ -31,7 +31,8 @@  public:
 			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     RkISP1Params *params) override;
+		     RkISP1Params *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 750c0fa72733..8627b4044d30 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -329,8 +329,10 @@  uint32_t IPARkISP1::computeParamsInternal(IPAFrameContext &frameContext, const u
 	RkISP1Params params(context_.configuration.paramFormat,
 			    mappedBuffers_.at(bufferId).planes()[0]);
 
+	unsigned int frame = frameContext.frame();
 	for (const auto &algo : algorithms())
-		algo->prepare(context_, frameContext.frame(), frameContext, &params);
+		algo->prepare(context_, frame, frameContext,
+			      &params, frame == 0);
 
 	return params.bytesused();
 }
diff --git a/src/ipa/softisp/algorithms/adjust.cpp b/src/ipa/softisp/algorithms/adjust.cpp
index 56e2cf0e8362..ec4698c4b376 100644
--- a/src/ipa/softisp/algorithms/adjust.cpp
+++ b/src/ipa/softisp/algorithms/adjust.cpp
@@ -95,7 +95,8 @@  void Adjust::applySaturation(Matrix<float, 3, 3> &matrix, float saturation)
 void Adjust::prepare(IPAContext &context,
 		     [[maybe_unused]] const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     DebayerParams *params)
+		     DebayerParams *params,
+		     [[maybe_unused]] bool initialize)
 {
 	frameContext.gamma = context.activeState.knobs.gamma;
 	frameContext.contrast = context.activeState.knobs.contrast;
diff --git a/src/ipa/softisp/algorithms/adjust.h b/src/ipa/softisp/algorithms/adjust.h
index 1acf7cdf1262..1c37f09035cd 100644
--- a/src/ipa/softisp/algorithms/adjust.h
+++ b/src/ipa/softisp/algorithms/adjust.h
@@ -35,7 +35,8 @@  public:
 	void prepare(IPAContext &context,
 		     const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     DebayerParams *params) override;
+		     DebayerParams *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const SwIspStats *stats,
diff --git a/src/ipa/softisp/algorithms/agc.cpp b/src/ipa/softisp/algorithms/agc.cpp
index 7d2a53b38576..0453b0215a60 100644
--- a/src/ipa/softisp/algorithms/agc.cpp
+++ b/src/ipa/softisp/algorithms/agc.cpp
@@ -72,7 +72,9 @@  void Agc::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t fram
 }
 
 void Agc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
-		  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
+		  IPAFrameContext &frameContext,
+		  [[maybe_unused]] DebayerParams *params,
+		  [[maybe_unused]] bool initialize)
 {
 	agc_.prepare(context.configuration.agc, context.activeState.agc, frameContext.agc);
 }
diff --git a/src/ipa/softisp/algorithms/agc.h b/src/ipa/softisp/algorithms/agc.h
index 10484cb448f8..3337b3a15044 100644
--- a/src/ipa/softisp/algorithms/agc.h
+++ b/src/ipa/softisp/algorithms/agc.h
@@ -26,7 +26,8 @@  public:
 			  IPAFrameContext &frameContext, const ControlList &controls) override;
 
 	void prepare(IPAContext &context, const uint32_t frame,
-		     IPAFrameContext &frameContext, DebayerParams *params) override;
+		     IPAFrameContext &frameContext, DebayerParams *params,
+		     bool initialize) override;
 
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
diff --git a/src/ipa/softisp/algorithms/awb.cpp b/src/ipa/softisp/algorithms/awb.cpp
index 55fd326fc182..c8bfc16a97a9 100644
--- a/src/ipa/softisp/algorithms/awb.cpp
+++ b/src/ipa/softisp/algorithms/awb.cpp
@@ -105,7 +105,8 @@  void Awb::queueRequest(IPAContext &context, const uint32_t frame,
 void Awb::prepare(IPAContext &context,
 		  [[maybe_unused]] const uint32_t frame,
 		  IPAFrameContext &frameContext,
-		  DebayerParams *params)
+		  DebayerParams *params,
+		  [[maybe_unused]] bool initialize)
 {
 	awbAlgo_.prepare(context.activeState.awb, frameContext.awb);
 
diff --git a/src/ipa/softisp/algorithms/awb.h b/src/ipa/softisp/algorithms/awb.h
index c92bdbfd5780..1dcd84b7d99a 100644
--- a/src/ipa/softisp/algorithms/awb.h
+++ b/src/ipa/softisp/algorithms/awb.h
@@ -40,7 +40,8 @@  public:
 	void prepare(IPAContext &context,
 		     const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     DebayerParams *params) override;
+		     DebayerParams *params,
+		     bool initialize) override;
 	void process(IPAContext &context,
 		     const uint32_t frame,
 		     IPAFrameContext &frameContext,
diff --git a/src/ipa/softisp/algorithms/blc.cpp b/src/ipa/softisp/algorithms/blc.cpp
index c7714aa34506..734cbcfd132b 100644
--- a/src/ipa/softisp/algorithms/blc.cpp
+++ b/src/ipa/softisp/algorithms/blc.cpp
@@ -62,7 +62,8 @@  int BlackLevel::configure(IPAContext &context,
 void BlackLevel::prepare(IPAContext &context,
 			 [[maybe_unused]] const uint32_t frame,
 			 [[maybe_unused]] IPAFrameContext &frameContext,
-			 DebayerParams *params)
+			 DebayerParams *params,
+			 [[maybe_unused]] bool initialize)
 {
 	/* Latch the blacklevel gain so GPUISP can apply. */
 	params->blackLevel = RGB<double>(context.activeState.blc.level / 255.0f);
diff --git a/src/ipa/softisp/algorithms/blc.h b/src/ipa/softisp/algorithms/blc.h
index 1d602927f9f3..3fae12c350fb 100644
--- a/src/ipa/softisp/algorithms/blc.h
+++ b/src/ipa/softisp/algorithms/blc.h
@@ -27,7 +27,8 @@  public:
 	void prepare(IPAContext &context,
 		     const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     DebayerParams *params) override;
+		     DebayerParams *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const SwIspStats *stats,
diff --git a/src/ipa/softisp/algorithms/ccm.cpp b/src/ipa/softisp/algorithms/ccm.cpp
index 039074494c9d..f965fb5d57c1 100644
--- a/src/ipa/softisp/algorithms/ccm.cpp
+++ b/src/ipa/softisp/algorithms/ccm.cpp
@@ -53,7 +53,9 @@  void Ccm::queueRequest(IPAContext &context,
 }
 
 void Ccm::prepare(IPAContext &context, const uint32_t frame,
-		  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
+		  IPAFrameContext &frameContext,
+		  [[maybe_unused]] DebayerParams *params,
+		  [[maybe_unused]] bool initialize)
 {
 	if (frameContext.awb.autoEnabled)
 		ccmAlgo_.prepare(context.activeState.ccm, frameContext.ccm,
diff --git a/src/ipa/softisp/algorithms/ccm.h b/src/ipa/softisp/algorithms/ccm.h
index 2a2030a41915..6eabe5e0cecd 100644
--- a/src/ipa/softisp/algorithms/ccm.h
+++ b/src/ipa/softisp/algorithms/ccm.h
@@ -35,7 +35,8 @@  public:
 	void prepare(IPAContext &context,
 		     const uint32_t frame,
 		     IPAFrameContext &frameContext,
-		     DebayerParams *params) override;
+		     DebayerParams *params,
+		     bool initialize) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const SwIspStats *stats,
diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp
index 2a65cd7cebfe..0d26ad210ebf 100644
--- a/src/ipa/softisp/softisp.cpp
+++ b/src/ipa/softisp/softisp.cpp
@@ -241,7 +241,7 @@  void IPASoftIsp::computeParams(const uint32_t frame)
 	ASSERT(frameContext);
 
 	for (const auto &algo : algorithms())
-		algo->prepare(context_, frame, *frameContext, params_);
+		algo->prepare(context_, frame, *frameContext, params_, frame == 0);
 	params_->combinedMatrix = context_.activeState.combinedMatrix;
 
 	paramsComputed.emit(frame);