diff --git a/include/libcamera/ipa/soft.mojom b/include/libcamera/ipa/soft.mojom
index f37c1e747..4738a1b46 100644
--- a/include/libcamera/ipa/soft.mojom
+++ b/include/libcamera/ipa/soft.mojom
@@ -15,7 +15,7 @@ struct IPAConfigInfo {
 interface IPASoftInterface {
 	init(libcamera.IPASettings settings,
 	     libcamera.SharedFD fdStats,
-	     libcamera.SharedFD fdParams,
+	     array<libcamera.SharedFD> fdParams,
 	     libcamera.IPACameraSensorInfo sensorInfo,
 	     libcamera.ControlInfoMap sensorControls)
 		=> (int32 ret, libcamera.ControlInfoMap ipaControls, bool ccmEnabled);
diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
index 1e8b5334c..f212fabe3 100644
--- a/src/ipa/simple/soft_simple.cpp
+++ b/src/ipa/simple/soft_simple.cpp
@@ -53,7 +53,7 @@ public:
 
 	int init(const IPASettings &settings,
 		 const SharedFD &fdStats,
-		 const SharedFD &fdParams,
+		 const std::vector<SharedFD> &fdParams,
 		 const IPACameraSensorInfo &sensorInfo,
 		 const ControlInfoMap &sensorControls,
 		 ControlInfoMap *ipaControls,
@@ -76,7 +76,7 @@ protected:
 private:
 	void updateExposure(double exposureMSV);
 
-	DebayerParams *params_;
+	std::map<unsigned int, DebayerParams *> paramsBuffers_;
 	SwIspStats *stats_;
 	std::unique_ptr<CameraSensorHelper> camHelper_;
 	ControlInfoMap sensorInfoMap_;
@@ -89,13 +89,13 @@ IPASoftSimple::~IPASoftSimple()
 {
 	if (stats_)
 		munmap(stats_, sizeof(SwIspStats));
-	if (params_)
-		munmap(params_, sizeof(DebayerParams));
+	for (auto &item : paramsBuffers_)
+		munmap(item.second, sizeof(DebayerParams));
 }
 
 int IPASoftSimple::init(const IPASettings &settings,
 			const SharedFD &fdStats,
-			const SharedFD &fdParams,
+			const std::vector<SharedFD> &fdParams,
 			const IPACameraSensorInfo &sensorInfo,
 			const ControlInfoMap &sensorControls,
 			ControlInfoMap *ipaControls,
@@ -138,8 +138,6 @@ int IPASoftSimple::init(const IPASettings &settings,
 		return ret;
 
 	*ccmEnabled = context_.ccmEnabled;
-
-	params_ = nullptr;
 	stats_ = nullptr;
 
 	if (!fdStats.isValid()) {
@@ -147,25 +145,27 @@ int IPASoftSimple::init(const IPASettings &settings,
 		return -ENODEV;
 	}
 
-	if (!fdParams.isValid()) {
-		LOG(IPASoft, Error) << "Invalid Parameters handle";
-		return -ENODEV;
-	}
+	for (auto &sharedFd : fdParams) {
+		if (!sharedFd.isValid()) {
+			LOG(IPASoft, Error) << "Invalid Parameters handle";
+			return -ENODEV;
+		}
 
-	{
 		void *mem = mmap(nullptr, sizeof(DebayerParams), PROT_WRITE,
-				 MAP_SHARED, fdParams.get(), 0);
+				 MAP_SHARED, sharedFd.get(), 0);
 		if (mem == MAP_FAILED) {
 			LOG(IPASoft, Error) << "Unable to map Parameters";
 			return -errno;
 		}
 
-		params_ = static_cast<DebayerParams *>(mem);
-		params_->blackLevel = { { 0.0, 0.0, 0.0 } };
-		params_->gamma = 1.0 / algorithms::kDefaultGamma;
-		params_->contrastExp = 1.0;
-		params_->gains = { { 1.0, 1.0, 1.0 } };
+		ASSERT(sharedFd.get() >= 0);
+		DebayerParams *params = static_cast<DebayerParams *>(mem);
+		params->blackLevel = { { 0.0, 0.0, 0.0 } };
+		params->gamma = 1.0 / algorithms::kDefaultGamma;
+		params->contrastExp = 1.0;
+		params->gains = { { 1.0, 1.0, 1.0 } };
 		/* combinedMatrix is reset for each frame. */
+		paramsBuffers_[sharedFd.get()] = params;
 	}
 
 	{
@@ -291,9 +291,10 @@ void IPASoftSimple::computeParams(const uint32_t frame,
 	context_.activeState.combinedMatrix = Matrix<float, 3, 3>::identity();
 
 	IPAFrameContext &frameContext = context_.frameContexts.get(frame);
+	DebayerParams *params = paramsBuffers_.at(paramsBufferId);
 	for (auto const &algo : algorithms())
-		algo->prepare(context_, frame, frameContext, params_);
-	params_->combinedMatrix = context_.activeState.combinedMatrix;
+		algo->prepare(context_, frame, frameContext, params);
+	params->combinedMatrix = context_.activeState.combinedMatrix;
 
 	setIspParams.emit(paramsBufferId);
 }
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index 02d1c4c12..2bc0d30b1 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -14,6 +14,7 @@
 #include <unistd.h>
 
 #include <libcamera/base/log.h>
+#include <libcamera/base/shared_fd.h>
 #include <libcamera/base/thread.h>
 #include <libcamera/base/utils.h>
 
@@ -118,6 +119,9 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 	if (!debayer_)
 		debayer_ = std::make_unique<DebayerCpu>(std::move(stats), configuration);
 
+	std::vector<SharedFD> fdParams;
+	for (auto &item : sharedParams_)
+		fdParams.emplace_back(item.second.fd());
 	debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady);
 	debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady);
 	debayer_->releaseIspParams.connect(this, &SoftwareIsp::releaseIspParams);
@@ -146,7 +150,7 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 
 	ret = ipa_->init(IPASettings{ ipaTuningFile, sensor->model() },
 			 debayer_->getStatsFD(),
-			 sharedParams_.begin()->second.fd(),
+			 fdParams,
 			 sensorInfo,
 			 sensor->controls(),
 			 ipaControls,
@@ -422,13 +426,14 @@ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *outpu
 	const uint32_t paramsBufferId = availableParams_.front();
 	availableParams_.pop();
 	ipa_->computeParams(frame, paramsBufferId);
+	debayerParams_ = *sharedParams_.at(paramsBufferId);
 	debayer_->invokeMethod(&Debayer::process,
 			       ConnectionTypeQueued, frame, paramsBufferId, input, output, debayerParams_);
 }
 
-void SoftwareIsp::saveIspParams([[maybe_unused]] uint32_t paramsBufferId)
+void SoftwareIsp::saveIspParams(uint32_t paramsBufferId)
 {
-	debayerParams_ = *sharedParams_.begin()->second;
+	debayerParams_ = *sharedParams_.at(paramsBufferId);
 }
 
 void SoftwareIsp::releaseIspParams(uint32_t paramsBufferId)
