diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h
index b64910637dcc..12e70ec12481 100644
--- a/include/libcamera/internal/software_isp/software_isp.h
+++ b/include/libcamera/internal/software_isp/software_isp.h
@@ -102,6 +102,7 @@ private:
 	DmaBufAllocator dmaHeap_;
 	bool ccmEnabled_;
 	bool lscEnabled_;
+	SizeRange outputSizeLimits_;
 
 	std::unique_ptr<ipa::softisp::IPAProxySoftIsp> ipa_;
 	std::deque<FrameBuffer *> queuedInputBuffers_;
diff --git a/include/libcamera/ipa/softisp.mojom b/include/libcamera/ipa/softisp.mojom
index e42742ed7f6d..52f60d902b25 100644
--- a/include/libcamera/ipa/softisp.mojom
+++ b/include/libcamera/ipa/softisp.mojom
@@ -20,7 +20,8 @@ interface IPASoftIspInterface {
 	     libcamera.ControlInfoMap sensorControls)
 		=> (int32 ret,
 		    libcamera.ControlInfoMap ipaControls,
-		    bool ccmEnabled, bool lscEnabled);
+		    bool ccmEnabled, bool lscEnabled,
+		    libcamera.SizeRange sizeLimits);
 	start() => (int32 ret);
 	stop();
 	configure(IPAConfigInfo configInfo)
diff --git a/src/ipa/softisp/softisp.cpp b/src/ipa/softisp/softisp.cpp
index 00249a300430..a166176b90c0 100644
--- a/src/ipa/softisp/softisp.cpp
+++ b/src/ipa/softisp/softisp.cpp
@@ -59,7 +59,8 @@ public:
 		 const ControlInfoMap &sensorControls,
 		 ControlInfoMap *ipaControls,
 		 bool *ccmEnabled,
-		 bool *lscEnabled) override;
+		 bool *lscEnabled,
+		 SizeRange *sizeLimits) override;
 	int configure(const IPAConfigInfo &configInfo,
 		      ControlInfoMap *ipaControls) override;
 
@@ -99,7 +100,8 @@ int IPASoftIsp::init(const IPASettings &settings,
 		     const ControlInfoMap &sensorControls,
 		     ControlInfoMap *ipaControls,
 		     bool *ccmEnabled,
-		     bool *lscEnabled)
+		     bool *lscEnabled,
+		     SizeRange *sizeLimits)
 {
 	context_.camHelper = CameraSensorHelperFactoryBase::create(settings.sensorModel);
 	if (!context_.camHelper) {
@@ -186,6 +188,22 @@ int IPASoftIsp::init(const IPASettings &settings,
 	ControlInfoMap::Map ctrlMap = context_.ctrlMap;
 	*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
 
+	sizeLimits->min = Size(0, 0);
+	sizeLimits->max = Size(std::numeric_limits<uint32_t>::max(),
+			       std::numeric_limits<uint32_t>::max());
+	if (data->contains("options")) {
+		const ValueNode *options = &(*data)["options"];
+
+		if (options->contains("min_output_width"))
+			sizeLimits->min.width = (*options)["min_output_width"].get<uint32_t>(0);
+		if (options->contains("min_output_heigth"))
+			sizeLimits->min.height = (*options)["min_output_heigth"].get<uint32_t>(0);
+		if (options->contains("max_output_width"))
+			sizeLimits->max.width = (*options)["max_output_width"].get<uint32_t>(0);
+		if (options->contains("max_output_heigth"))
+			sizeLimits->max.height = (*options)["max_output_heigth"].get<uint32_t>(0);
+	}
+
 	return 0;
 }
 
diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp
index 627625b4f54f..218660ed8510 100644
--- a/src/libcamera/software_isp/software_isp.cpp
+++ b/src/libcamera/software_isp/software_isp.cpp
@@ -164,7 +164,8 @@ SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 			 sensor->controls(),
 			 ipaControls,
 			 &ccmEnabled_,
-			 &lscEnabled_);
+			 &lscEnabled_,
+			 &outputSizeLimits_);
 	if (ret) {
 		LOG(SoftwareIsp, Error) << "IPA init failed";
 		debayer_.reset();
@@ -244,7 +245,10 @@ SizeRange SoftwareIsp::sizes(PixelFormat inputFormat, const Size &inputSize)
 {
 	ASSERT(debayer_);
 
-	return debayer_->sizes(inputFormat, inputSize);
+	SizeRange sizes = debayer_->sizes(inputFormat, inputSize);
+	sizes.min = sizes.min.expandTo(outputSizeLimits_.min).alignUpTo(sizes.hStep, sizes.vStep);
+	sizes.max = sizes.max.boundTo(outputSizeLimits_.max).alignDownTo(sizes.hStep, sizes.vStep);
+	return sizes;
 }
 
 /**
