diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp
index 030f69dd95..99e33410cd 100644
--- a/src/ipa/libipa/camera_sensor_helper.cpp
+++ b/src/ipa/libipa/camera_sensor_helper.cpp
@@ -76,6 +76,16 @@ namespace ipa {
  * \return The black level of the sensor, or std::nullopt if not known
  */
 
+/**
+ * \fn CameraSensorHelper::exposureMargin()
+ * \brief Fetch the exposure margin of the sensor
+ *
+ * This function returns the exposure margin of the sensor, in lines, which
+ * is the minimum difference between the integration time and frame length.
+ *
+ * \return The exposure margin of the sensor, or std::nullopt if not known
+ */
+
 /**
  * \brief Compute gain code from the analogue gain absolute value
  * \param[in] gain The real gain to pass
@@ -229,6 +239,12 @@ double CameraSensorHelper::quantizeGain(double _gain, double *quantizationGain)
  * sensor specific. Use this variable to store the values at init time.
  */
 
+/**
+ * \var CameraSensorHelper::exposureMargin_
+ * \brief The smallest margin between the integration time and the frame length
+ * in lines
+ */
+
 /**
  * \class CameraSensorHelperFactoryBase
  * \brief Base class for camera sensor helper factories
@@ -387,6 +403,7 @@ public:
 	{
 		/* Power-on default value: 168 at 12bits. */
 		blackLevel_ = 2688;
+		exposureMargin_ = 4;
 	}
 
 	uint32_t gainCode(double gain) const override
@@ -473,6 +490,11 @@ REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144)
 class CameraSensorHelperAr0521 : public CameraSensorHelper
 {
 public:
+	CameraSensorHelperAr0521()
+	{
+		exposureMargin_ = 4;
+	}
+
 	uint32_t gainCode(double gain) const override
 	{
 		gain = std::clamp(gain, 1.0, 15.5);
@@ -503,6 +525,7 @@ public:
 		/* From datasheet: 64 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("gc05a2", CameraSensorHelperGc05a2)
@@ -515,6 +538,7 @@ public:
 		/* From datasheet: 64 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 };
+		exposureMargin_ = 16;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("gc08a3", CameraSensorHelperGc08a3)
@@ -525,6 +549,7 @@ public:
 	CameraSensorHelperHm1246()
 	{
 		gain_ = AnalogueGainLinear{ 1, 16, 0, 16 };
+		exposureMargin_ = 2;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("hm1246", CameraSensorHelperHm1246)
@@ -537,6 +562,7 @@ public:
 		/* From datasheet: 64 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 0, 512, -1, 512 };
+		exposureMargin_ = 10;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx214", CameraSensorHelperImx214)
@@ -549,6 +575,7 @@ public:
 		/* From datasheet: 64 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 0, 256, -1, 256 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219)
@@ -561,6 +588,7 @@ public:
 		/* From datasheet: 0x40 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 0, 512, -1, 512 };
+		exposureMargin_ = 10;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx258", CameraSensorHelperImx258)
@@ -573,6 +601,7 @@ public:
 		/* From datasheet: 0x32 at 10bits. */
 		blackLevel_ = 3200;
 		gain_ = AnalogueGainLinear{ 0, 2048, -1, 2048 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx283", CameraSensorHelperImx283)
@@ -585,6 +614,7 @@ public:
 		/* From datasheet: 0xf0 at 12bits. */
 		blackLevel_ = 3840;
 		gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) };
+		exposureMargin_ = 2;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx290", CameraSensorHelperImx290)
@@ -595,6 +625,11 @@ public:
 	CameraSensorHelperImx296()
 	{
 		gain_ = AnalogueGainExp{ 1.0, expGainDb(0.1) };
+		/*
+		 * The driver doesn't apply any margin. Use the value
+		 * in RPi's CamHelper.
+		 */
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx296", CameraSensorHelperImx296)
@@ -612,6 +647,7 @@ public:
 		/* From datasheet: 0x32 at 10bits. */
 		blackLevel_ = 3200;
 		gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) };
+		exposureMargin_ = 10;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx335", CameraSensorHelperImx335)
@@ -624,6 +660,7 @@ public:
 		/* From datasheet: 64 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx355", CameraSensorHelperImx355)
@@ -634,6 +671,7 @@ public:
 	CameraSensorHelperImx415()
 	{
 		gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx415", CameraSensorHelperImx415)
@@ -652,6 +690,7 @@ public:
 		blackLevel_ = 4096;
 		/* gain = 1024/(1024 - code); code = [0, 800]; max gain = x4.57 */
 		gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 };
+		exposureMargin_ = 18;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx471", CameraSensorHelperImx471)
@@ -662,6 +701,7 @@ public:
 	CameraSensorHelperImx477()
 	{
 		gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 };
+		exposureMargin_ = 22;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx477", CameraSensorHelperImx477)
@@ -674,6 +714,7 @@ public:
 		/* From datasheet: 0xc8 at 12bits. */
 		blackLevel_ = 3200;
 		gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) };
+		exposureMargin_ = 2;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx662", CameraSensorHelperImx662)
@@ -686,6 +727,7 @@ public:
 		/* From datasheet: 0x32 at 10bits. */
 		blackLevel_ = 3200;
 		gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) };
+		exposureMargin_ = 8; /* FIXME: kernel driver: 8, rpi: 4 */
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx678", CameraSensorHelperImx678)
@@ -697,6 +739,7 @@ public:
 	{
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 };
+		exposureMargin_ = 48;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx708", CameraSensorHelperImx708)
@@ -724,6 +767,7 @@ public:
 		/* From dark frame measurement: 0x40 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 256 };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov01a10", CameraSensorHelperOv01a10)
@@ -736,6 +780,7 @@ public:
 		/* From Linux kernel driver: 0x40 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 6;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov08d10", CameraSensorHelperOv08d10)
@@ -747,6 +792,7 @@ public:
 	{
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov08x40", CameraSensorHelperOv08x40)
@@ -759,6 +805,7 @@ public:
 		blackLevel_ = 3600;
 		/* gain is fixed to 1x, this is just a place holder. */
 		gain_ = AnalogueGainLinear{ 0, 2048, -1, 2048 };
+		exposureMargin_ = 6;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("mira220", CameraSensorHelperMira220)
@@ -773,6 +820,7 @@ public:
 		 * This has been validated with some empirical testing only.
 		 */
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov2685", CameraSensorHelperOv2685)
@@ -785,6 +833,7 @@ public:
 		/* From Linux kernel driver: 0x40 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov2740", CameraSensorHelperOv2740)
@@ -797,6 +846,7 @@ public:
 		/* From datasheet: 0x40 at 12bits. */
 		blackLevel_ = 1024;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov4689", CameraSensorHelperOv4689)
@@ -809,6 +859,14 @@ public:
 		/* From datasheet: 0x10 at 10bits. */
 		blackLevel_ = 1024;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 16 };
+		/*
+		 * Very convoluted in the driver that however applies a margin
+		 * of 4 lines when setting vts.
+		 *
+		 * 	cap_vts = cap_shutter + 4;
+		 * 	ret = ov5640_set_vts(sensor, cap_vts);
+		 */
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov5640", CameraSensorHelperOv5640)
@@ -819,6 +877,7 @@ public:
 	CameraSensorHelperOv5647()
 	{
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 16 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov5647", CameraSensorHelperOv5647)
@@ -829,6 +888,7 @@ public:
 	CameraSensorHelperOv5670()
 	{
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670)
@@ -841,6 +901,7 @@ public:
 		/* From Linux kernel driver: 0x40 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov5675", CameraSensorHelperOv5675)
@@ -852,6 +913,7 @@ public:
 	{
 		blackLevel_ = 1024;
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 16 };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693)
@@ -862,6 +924,7 @@ public:
 	CameraSensorHelperOv64a40()
 	{
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 32;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov64a40", CameraSensorHelperOv64a40)
@@ -878,6 +941,7 @@ public:
 		 * See: https://patchwork.linuxtv.org/project/linux-media/patch/20221106171129.166892-2-nicholas@rothemail.net/#142267
 		 */
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 4;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov8858", CameraSensorHelperOv8858)
@@ -888,6 +952,7 @@ public:
 	CameraSensorHelperOv8865()
 	{
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov8865", CameraSensorHelperOv8865)
@@ -898,6 +963,7 @@ public:
 	CameraSensorHelperOv13858()
 	{
 		gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+		exposureMargin_ = 8;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858)
@@ -910,6 +976,7 @@ public:
 		/* From datasheet: 0x40 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 0, 32, -1, 32 };
+		exposureMargin_ = 64;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("vd55g1", CameraSensorHelperVd55g1)
@@ -922,6 +989,7 @@ public:
 		/* From datasheet: 0x40 at 10bits. */
 		blackLevel_ = 4096;
 		gain_ = AnalogueGainLinear{ 0, 32, -1, 32 };
+		exposureMargin_ = 75;
 	}
 };
 REGISTER_CAMERA_SENSOR_HELPER("vd56g3", CameraSensorHelperVd56g3)
diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h
index bd3d0beec7..a9e55c832d 100644
--- a/src/ipa/libipa/camera_sensor_helper.h
+++ b/src/ipa/libipa/camera_sensor_helper.h
@@ -27,6 +27,7 @@ public:
 	virtual ~CameraSensorHelper() = default;
 
 	std::optional<int16_t> blackLevel() const { return blackLevel_; }
+	std::optional<uint32_t> exposureMargin() const { return exposureMargin_; }
 	virtual uint32_t gainCode(double gain) const;
 	virtual double gain(uint32_t gainCode) const;
 	double quantizeGain(double gain, double *quantizationGain) const;
@@ -46,6 +47,7 @@ protected:
 
 	std::optional<int16_t> blackLevel_;
 	std::variant<std::monostate, AnalogueGainLinear, AnalogueGainExp> gain_;
+	std::optional<uint32_t> exposureMargin_;
 
 private:
 	LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelper)
