diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp
index 8bd58c3d..52df8c23 100644
--- a/src/libcamera/software_isp/debayer.cpp
+++ b/src/libcamera/software_isp/debayer.cpp
@@ -94,13 +94,12 @@ Debayer::~Debayer()
  */
 
 /**
- * \fn void Debayer::process(uint32_t frame, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output, DebayerParams params)
+ * \fn void Debayer::process(uint32_t frame, const uint32_t paramsBufferId, FrameBuffer *input, FrameBuffer *output)
  * \brief Process the bayer data into the requested format
  * \param[in] frame The frame number
  * \param[in] paramsBufferId The id of the params buffer in use
  * \param[in] input The input buffer
  * \param[in] output The output buffer
- * \param[in] params The parameters to be used in debayering
  *
  * \note DebayerParams is passed by value deliberately so that a copy is passed
  * when this is run in another thread by invokeMethod().
diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h
index 93020735..251b14fd 100644
--- a/src/libcamera/software_isp/debayer.h
+++ b/src/libcamera/software_isp/debayer.h
@@ -42,8 +42,7 @@ public:
 
 	virtual void process(uint32_t frame,
 			     const uint32_t paramsBufferId,
-			     FrameBuffer *input, FrameBuffer *output,
-			     DebayerParams params) = 0;
+			     FrameBuffer *input, FrameBuffer *output) = 0;
 
 	virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0;
 
diff --git a/src/libcamera/software_isp/debayer_cpu.cpp b/src/libcamera/software_isp/debayer_cpu.cpp
index 20a15ae0..af08ab10 100644
--- a/src/libcamera/software_isp/debayer_cpu.cpp
+++ b/src/libcamera/software_isp/debayer_cpu.cpp
@@ -11,9 +11,10 @@
 
 #include "debayer_cpu.h"
 
-#include <stdlib.h>
 #include <time.h>
 
+#include <libcamera/base/shared_fd.h>
+
 #include <libcamera/formats.h>
 
 #include "libcamera/internal/bayer_format.h"
@@ -32,8 +33,10 @@ namespace libcamera {
 /**
  * \brief Constructs a DebayerCpu object
  * \param[in] stats Pointer to the stats object to use
+ * \param[in] paramBuffers SharedFDs of parameter buffers
  */
-DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
+DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats,
+		       const std::vector<SharedFD> &paramBuffers)
 	: stats_(std::move(stats))
 {
 	/*
@@ -49,6 +52,20 @@ DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
 	/* Initialize color lookup tables */
 	for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++)
 		red_[i] = green_[i] = blue_[i] = i;
+
+	paramsBuffers_ = std::map<unsigned int, DebayerParams *>();
+
+	for (auto &sharedFd : paramBuffers) {
+		void *mem = mmap(nullptr, sizeof(DebayerParams), PROT_WRITE,
+				 MAP_SHARED, sharedFd.get(), 0);
+		if (mem == MAP_FAILED) {
+			LOG(Debayer, Error) << "Unable to map Parameters";
+			return;
+		}
+
+		ASSERT(sharedFd.get() >= 0);
+		paramsBuffers_[sharedFd.get()] = static_cast<DebayerParams *>(mem);
+	}
 }
 
 DebayerCpu::~DebayerCpu() = default;
@@ -608,8 +625,7 @@ void DebayerCpu::memcpyNextLine(const uint8_t *linePointers[])
 	memcpy(lineBuffers_[lineBufferIndex_].data(),
 	       linePointers[patternHeight] - lineBufferPadding_,
 	       lineBufferLength_);
-	linePointers[patternHeight] = lineBuffers_[lineBufferIndex_].data()
-				    + lineBufferPadding_;
+	linePointers[patternHeight] = lineBuffers_[lineBufferIndex_].data() + lineBufferPadding_;
 
 	lineBufferIndex_ = (lineBufferIndex_ + 1) % (patternHeight + 1);
 }
@@ -726,7 +742,7 @@ static inline int64_t timeDiff(timespec &after, timespec &before)
 
 void DebayerCpu::process(uint32_t frame,
 			 const uint32_t paramsBufferId,
-			 FrameBuffer *input, FrameBuffer *output, DebayerParams params)
+			 FrameBuffer *input, FrameBuffer *output)
 {
 	timespec frameStartTime;
 
@@ -735,12 +751,14 @@ void DebayerCpu::process(uint32_t frame,
 		clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
 	}
 
-	green_ = params.green;
-	red_ = swapRedBlueGains_ ? params.blue : params.red;
-	blue_ = swapRedBlueGains_ ? params.red : params.blue;
-
+	DebayerParams *params = paramsBuffers_.at(paramsBufferId);
 	releaseIspParams.emit(paramsBufferId);
 
+	/* \todo Avoid copying here. */
+	green_ = params->green;
+	red_ = swapRedBlueGains_ ? params->blue : params->red;
+	blue_ = swapRedBlueGains_ ? params->red : params->blue;
+
 	/* Copy metadata from the input buffer */
 	FrameMetadata &metadata = output->_d()->metadata();
 	metadata.status = input->metadata().status;
diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h
index 0b5a5258..324fc6c0 100644
--- a/src/libcamera/software_isp/debayer_cpu.h
+++ b/src/libcamera/software_isp/debayer_cpu.h
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include <libcamera/base/object.h>
+#include <libcamera/base/shared_fd.h>
 
 #include "libcamera/internal/bayer_format.h"
 
@@ -27,7 +28,8 @@ namespace libcamera {
 class DebayerCpu : public Debayer, public Object
 {
 public:
-	DebayerCpu(std::unique_ptr<SwStatsCpu> stats);
+	DebayerCpu(std::unique_ptr<SwStatsCpu> stats,
+		   const std::vector<SharedFD> &paramBuffers);
 	~DebayerCpu();
 
 	int configure(const StreamConfiguration &inputCfg,
@@ -38,7 +40,7 @@ public:
 	strideAndFrameSize(const PixelFormat &outputFormat, const Size &size);
 	void process(uint32_t frame,
 		     const uint32_t paramsBufferId,
-		     FrameBuffer *input, FrameBuffer *output, DebayerParams params);
+		     FrameBuffer *input, FrameBuffer *output);
 	SizeRange sizes(PixelFormat inputFormat, const Size &inputSize);
 
 	/**
@@ -160,6 +162,7 @@ private:
 	/* Skip 30 frames for things to stabilize then measure 30 frames */
 	static constexpr unsigned int kFramesToSkip = 30;
 	static constexpr unsigned int kLastFrameToMeasure = 60;
+	std::map<unsigned int, DebayerParams *> paramsBuffers_;
 };
 
 } /* namespace libcamera */
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index 480ecf6e..db77f6f9 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -86,10 +86,11 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 	}
 	stats->statsReady.connect(this, &SoftwareIsp::statsReady);
 
-	debayer_ = std::make_unique<DebayerCpu>(std::move(stats));
 	std::vector<SharedFD> fdParams;
 	for (auto &item : sharedParams_)
 		fdParams.emplace_back(item.second.fd());
+
+	debayer_ = std::make_unique<DebayerCpu>(std::move(stats), fdParams);
 	debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady);
 	debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady);
 	debayer_->releaseIspParams.connect(this, &SoftwareIsp::releaseIspParams);
@@ -385,9 +386,8 @@ void SoftwareIsp::process(uint32_t frame, FrameBuffer *input, FrameBuffer *outpu
 	const uint32_t paramsBufferId = availableParams_.front();
 	availableParams_.pop();
 	ipa_->prepare(frame, paramsBufferId);
-	debayerParams_ = *sharedParams_.at(paramsBufferId);
 	debayer_->invokeMethod(&DebayerCpu::process,
-			       ConnectionTypeQueued, frame, paramsBufferId, input, output, debayerParams_);
+			       ConnectionTypeQueued, frame, paramsBufferId, input, output);
 }
 
 void SoftwareIsp::saveIspParams(uint32_t paramsBufferId)
