diff --git a/include/libcamera/internal/camera_sensor.h b/include/libcamera/internal/camera_sensor.h
index db12b07e..d25a1165 100644
--- a/include/libcamera/internal/camera_sensor.h
+++ b/include/libcamera/internal/camera_sensor.h
@@ -38,7 +38,7 @@ public:
 	const std::string &id() const { return id_; }
 	const MediaEntity *entity() const { return entity_; }
 	const std::vector<unsigned int> &mbusCodes() const { return mbusCodes_; }
-	const std::vector<Size> &sizes() const { return sizes_; }
+	const std::vector<Size> sizes(unsigned int mbusCode) const;
 	Size resolution() const;
 	const std::vector<int32_t> &testPatternModes() const
 	{
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index cde431cc..3c3ceff3 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -471,16 +471,6 @@ int CameraSensor::initProperties()
  * \return The supported media bus codes sorted in increasing order
  */
 
-/**
- * \fn CameraSensor::sizes()
- * \brief Retrieve the frame sizes supported by the camera sensor
- *
- * The reported sizes span all media bus codes supported by the camera sensor.
- * Not all sizes may be supported by all media bus codes.
- *
- * \return The supported frame sizes sorted in increasing order
- */
-
 /**
  * \brief Retrieve the camera sensor resolution
  *
@@ -594,6 +584,32 @@ V4L2SubdeviceFormat CameraSensor::getFormat(const std::vector<unsigned int> &mbu
 	return format;
 }
 
+/**
+ * \brief Retrieve the supported frame sizes for a media bus code
+ * \param[in] mbusCode The media bus code for which sizes are requested
+ *
+ * The reported sizes for a particular \a mbusCode are supported by the camera
+ * sensor.
+ *
+ * \return The supported frame sizes for \a mbusCode sorted in increasing order
+ */
+const std::vector<Size> CameraSensor::sizes(unsigned int mbusCode) const
+{
+	std::vector<Size> sizes;
+
+	const auto format = formats_.find(mbusCode);
+	if (format == formats_.end())
+		return sizes;
+
+	const std::vector<SizeRange> &ranges = format->second;
+	std::transform(ranges.begin(), ranges.end(), std::back_inserter(sizes),
+		       [](const SizeRange &range) { return range.max; });
+
+	std::sort(sizes.begin(), sizes.end());
+
+	return sizes;
+}
+
 /**
  * \brief Set the sensor output format
  * \param[in] format The desired sensor output format
diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
index 1bcd580e..6f2ef321 100644
--- a/src/libcamera/pipeline/ipu3/cio2.cpp
+++ b/src/libcamera/pipeline/ipu3/cio2.cpp
@@ -69,11 +69,13 @@ std::vector<SizeRange> CIO2Device::sizes() const
 	if (!sensor_)
 		return {};
 
-	std::vector<SizeRange> sizes;
-	for (const Size &size : sensor_->sizes())
-		sizes.emplace_back(size, size);
+	std::set<Size> allSizes;
+	for (unsigned int code : sensor_->mbusCodes()) {
+		for (Size sz : sensor_->sizes(code))
+			allSizes.insert(sz);
+	}
 
-	return sizes;
+	return std::vector<SizeRange>(allSizes.begin(), allSizes.end());
 }
 
 /**
diff --git a/test/camera-sensor.cpp b/test/camera-sensor.cpp
index a8dcad82..372ee4af 100644
--- a/test/camera-sensor.cpp
+++ b/test/camera-sensor.cpp
@@ -76,7 +76,7 @@ protected:
 			return TestFail;
 		}
 
-		const std::vector<Size> &sizes = sensor_->sizes();
+		const std::vector<Size> &sizes = sensor_->sizes(*iter);
 		auto iter2 = std::find(sizes.begin(), sizes.end(),
 				       Size(4096, 2160));
 		if (iter2 == sizes.end()) {
