Author: Pragyansh Chaturvedi <r41k0u@ubuntu.com>
Forwarded: not-needed
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libcamera/+bug/2110144
Last-Update: 2026-02-18
Description: Fix PiSP CFE entity match patterns
 libcamera0.5 includes the PiSP drivers for Raspberry Pi. But
 while registering the cameras, it is using different match
 strings for CFE entities than what are present in Raspberry Pi's
 fork of libcamera and the current device-tree overlays. This leads
 to camera sensors not being detected on Raspberry Pi 5, which
 used to work in libcamera0.4.
 .
 This indicates an upcoming change in these device-tree overlays,
 as Raspberry Pi themselves upstreamed these changes to libcamera.
 So this patch allows both the old and current match strings for
 searching for CFE devices. This delta can be removed once our kernel
 catches up and introduces the new strings.

---
--- a/include/libcamera/internal/device_enumerator.h
+++ b/include/libcamera/internal/device_enumerator.h
@@ -28,6 +28,8 @@
 
 	bool match(const MediaDevice *device) const;
 
+	void clear();
+
 private:
 	std::string driver_;
 	std::vector<std::string> entities_;
--- a/src/libcamera/device_enumerator.cpp
+++ b/src/libcamera/device_enumerator.cpp
@@ -157,6 +157,14 @@
 }
 
 /**
+ * \brief Clear the entities search pattern vector
+ */
+void DeviceMatch::clear()
+{
+	entities_.clear();
+}
+
+/**
  * \class DeviceEnumerator
  * \brief Enumerate, store and search media devices
  *
--- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp
+++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
@@ -888,7 +888,17 @@
 		std::shared_ptr<MediaDevice> cfeDevice = acquireMediaDevice(enumerator, cfe);
 
 		if (!cfeDevice) {
-			LOG(RPI, Debug) << "Unable to acquire a CFE instance";
+			LOG(RPI, Debug) << "Trying old entity search patterns for CFE instance";
+		}
+
+		cfe.clear();
+		cfe.add("rp1-cfe-fe_image0");
+		cfe.add("rp1-cfe-fe_stats");
+		cfe.add("rp1-cfe-fe_config");
+		cfeDevice = acquireMediaDevice(enumerator, cfe);
+
+		if (!cfeDevice) {
+			LOG(RPI, Debug) << "Unable to acquire CFE instance";
 			break;
 		}
 
@@ -1073,9 +1083,26 @@
 	int ret;
 
 	MediaEntity *cfeImage = cfe->getEntityByName("rp1-cfe-fe-image0");
+	if (!cfeImage)
+	{
+		cfeImage = cfe->getEntityByName("rp1-cfe-fe_image0");
+	}
 	MediaEntity *cfeEmbedded = cfe->getEntityByName("rp1-cfe-csi2-ch1");
+	if (!cfeEmbedded)
+	{
+		cfeEmbedded = cfe->getEntityByName("rp1-cfe-embedded");
+	}
 	MediaEntity *cfeStats = cfe->getEntityByName("rp1-cfe-fe-stats");
+	if (!cfeStats)
+	{
+		cfeStats = cfe->getEntityByName("rp1-cfe-fe_stats");
+	}
 	MediaEntity *cfeConfig = cfe->getEntityByName("rp1-cfe-fe-config");
+	if (!cfeConfig)
+	{
+		cfeConfig = cfe->getEntityByName("rp1-cfe-fe_config");
+	}
+
 	MediaEntity *ispInput = isp->getEntityByName("pispbe-input");
 	MediaEntity *IpaPrepare = isp->getEntityByName("pispbe-config");
 	MediaEntity *ispOutput0 = isp->getEntityByName("pispbe-output0");
@@ -2144,8 +2171,9 @@
 	int ret = 0;
 
 	constexpr unsigned int csiVideoSinkPad = 0;
-	constexpr unsigned int csiVideoSourcePad = 1;
-	constexpr unsigned int csiMetaSourcePad = 2;
+	constexpr unsigned int csiMetaSinkPad = 1;
+	constexpr unsigned int csiVideoSourcePad = 4;
+	constexpr unsigned int csiMetaSourcePad = 5;
 
 	constexpr unsigned int feVideoSinkPad = 0;
 	constexpr unsigned int feConfigSinkPad = 1;
@@ -2156,48 +2184,29 @@
 	const MediaEntity *csi2 = csi2Subdev_->entity();
 	const MediaEntity *fe = feSubdev_->entity();
 
-	for (MediaLink *link : csi2->pads()[csiVideoSourcePad]->links()) {
-		if (link->sink()->entity()->name() == "rp1-cfe-csi2-ch0")
+	for (MediaLink *link : csi2->getPadByIndex(csiVideoSourcePad)->links()) {
+		if (link->sink()->entity()->name() == "rp1-cfe-csi2-ch0" || link->sink()->entity()->name() == "rp1-cfe-csi2_ch0")
 			link->setEnabled(false);
 		else if (link->sink()->entity()->name() == "pisp-fe")
 			link->setEnabled(true);
 	}
 
-	csi2->pads()[csiMetaSourcePad]->links()[0]->setEnabled(sensorMetadata_);
+	csi2->getPadByIndex(csiMetaSourcePad)->links()[0]->setEnabled(sensorMetadata_);
 
-	fe->pads()[feConfigSinkPad]->links()[0]->setEnabled(true);
-	fe->pads()[feVideo0SourcePad]->links()[0]->setEnabled(true);
-	fe->pads()[feVideo1SourcePad]->links()[0]->setEnabled(false);
-	fe->pads()[feStatsSourcePad]->links()[0]->setEnabled(true);
-
-	const V4L2Subdevice::Stream imageStream{
-		csiVideoSinkPad,
-		sensor_->imageStream().stream
-	};
-	const V4L2Subdevice::Stream embeddedDataStream{
-		csiVideoSinkPad,
-		sensor_->embeddedDataStream().value_or(V4L2Subdevice::Stream{}).stream
-	};
-
-	V4L2Subdevice::Routing routing;
-	routing.emplace_back(imageStream, V4L2Subdevice::Stream{ csiVideoSourcePad, 0 },
-			     V4L2_SUBDEV_ROUTE_FL_ACTIVE);
-
-	if (sensorMetadata_)
-		routing.emplace_back(embeddedDataStream,
-				     V4L2Subdevice::Stream{ csiMetaSourcePad, 0 },
-				     V4L2_SUBDEV_ROUTE_FL_ACTIVE);
-
-	ret = csi2Subdev_->setRouting(&routing);
-	if (ret)
-		return ret;
+	fe->getPadByIndex(feConfigSinkPad)->links()[0]->setEnabled(true);
+	fe->getPadByIndex(feVideo0SourcePad)->links()[0]->setEnabled(true);
+	fe->getPadByIndex(feVideo1SourcePad)->links()[0]->setEnabled(false);
+	fe->getPadByIndex(feStatsSourcePad)->links()[0]->setEnabled(true);
 
-	ret = csi2Subdev_->setFormat(imageStream, &sensorFormat);
+	ret = csi2Subdev_->setFormat(csiVideoSinkPad, &sensorFormat);
 	if (ret)
 		return ret;
 
 	if (sensorMetadata_) {
-		ret = csi2Subdev_->setFormat(embeddedDataStream, &embeddedFormat);
+		ret = csi2Subdev_->setFormat(csiMetaSinkPad, &embeddedFormat);
+		if (ret)
+			return ret;
+		ret = csi2Subdev_->setFormat(csiMetaSourcePad, &embeddedFormat);
 		if (ret)
 			return ret;
 	}
