diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp
index 72833247c5..eff639fb67 100644
--- a/src/ipa/libipa/agc_mean_luminance.cpp
+++ b/src/ipa/libipa/agc_mean_luminance.cpp
@@ -314,15 +314,15 @@ int AgcMeanLuminance::parseExposureModes(const ValueNode &tuningData)
 				return -EINVAL;
 			}
 
-			std::vector<std::pair<utils::Duration, double>> stages;
-			for (unsigned int i = 0; i < exposureTimes.size(); i++) {
+			std::vector<ExposureModeHelper::Stage> stages;
+			for (size_t i = 0; i < exposureTimes.size(); i++) {
 				stages.push_back({
-					std::chrono::microseconds(exposureTimes[i]),
-					gains[i]
+					.exposureTime = std::chrono::microseconds(exposureTimes[i]),
+					.gain = gains[i],
 				});
 			}
 
-			exposureModeHelpers_.try_emplace(it->second, stages);
+			exposureModeHelpers_.try_emplace(it->second, std::move(stages));
 		}
 	}
 
@@ -334,7 +334,7 @@ int AgcMeanLuminance::parseExposureModes(const ValueNode &tuningData)
 	 */
 	if (exposureModeHelpers_.empty())
 		exposureModeHelpers_.try_emplace(controls::ExposureNormal,
-						 std::span<std::pair<utils::Duration, double>>{});
+						 std::vector<ExposureModeHelper::Stage>{});
 
 	return 0;
 }
diff --git a/src/ipa/libipa/exposure_mode_helper.cpp b/src/ipa/libipa/exposure_mode_helper.cpp
index b3e75f6358..ef14729471 100644
--- a/src/ipa/libipa/exposure_mode_helper.cpp
+++ b/src/ipa/libipa/exposure_mode_helper.cpp
@@ -59,24 +59,31 @@ namespace ipa {
  * used.
  */
 
+ /**
+  * \class ExposureModeHelper::Stage
+  * \brief Details of an exposure stage
+  *
+  * This type contains the parameters of a single exposure stage as used by the
+  * algorithm.
+  *
+  * \var ExposureModeHelper::Stage::exposureTime
+  * \brief The maximum exposure time of the stage
+  *
+  * \var ExposureModeHelper::Stage::gain
+  * \brief The maximum gain of the stage
+  */
+
 /**
  * \brief Construct an ExposureModeHelper instance
  * \param[in] stages The vector of paired exposure time and gain limits
  *
- * The input stages are exposure time and _total_ gain pairs; the gain
- * encompasses both analogue and digital gain.
- *
  * The vector of stages may be empty. In that case, the helper will simply use
  * the runtime limits set through setLimits() instead.
  */
-ExposureModeHelper::ExposureModeHelper(std::span<std::pair<utils::Duration, double>> stages)
-	: lineDuration_(1us), minExposureTime_(0us), maxExposureTime_(0us),
-	  minGain_(0), maxGain_(0), sensorHelper_(nullptr)
+ExposureModeHelper::ExposureModeHelper(std::vector<Stage> stages)
+	: stages_(std::move(stages)), lineDuration_(1us), minExposureTime_(0us),
+	  maxExposureTime_(0us), minGain_(0), maxGain_(0), sensorHelper_(nullptr)
 {
-	for (const auto &[s, g] : stages) {
-		exposureTimes_.push_back(s);
-		gains_.push_back(g);
-	}
 }
 
 /**
@@ -236,10 +243,10 @@ ExposureModeHelper::splitExposure(utils::Duration exposure) const
 	double stageGain = clampGain(1.0);
 	double lastStageGain = stageGain;
 
-	for (unsigned int stage = 0; stage < gains_.size(); stage++) {
-		utils::Duration stageExposureTime = clampExposureTime(exposureTimes_[stage],
+	for (const auto &stage : stages_) {
+		utils::Duration stageExposureTime = clampExposureTime(stage.exposureTime,
 								      &quantGain);
-		stageGain = clampGain(gains_[stage]);
+		stageGain = clampGain(stage.gain);
 
 		/*
 		 * We perform the clamping on both exposure time and gain in
diff --git a/src/ipa/libipa/exposure_mode_helper.h b/src/ipa/libipa/exposure_mode_helper.h
index d0d468a6a2..c474cc2c13 100644
--- a/src/ipa/libipa/exposure_mode_helper.h
+++ b/src/ipa/libipa/exposure_mode_helper.h
@@ -7,8 +7,6 @@
 
 #pragma once
 
-#include <span>
-#include <utility>
 #include <vector>
 
 #include <libcamera/base/utils.h>
@@ -22,7 +20,12 @@ namespace ipa {
 class ExposureModeHelper
 {
 public:
-	ExposureModeHelper(std::span<std::pair<utils::Duration, double>> stages);
+	struct Stage {
+		utils::Duration exposureTime;
+		double gain;
+	};
+
+	ExposureModeHelper(std::vector<Stage> stages);
 
 	void configure(utils::Duration lineLength, const CameraSensorHelper *sensorHelper);
 	void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
@@ -47,8 +50,7 @@ private:
 					  double *quantizationGain = nullptr) const;
 	double clampGain(double gain, double *quantizationGain = nullptr) const;
 
-	std::vector<utils::Duration> exposureTimes_;
-	std::vector<double> gains_;
+	std::vector<Stage> stages_;
 
 	utils::Duration lineDuration_;
 	utils::Duration minExposureTime_;
