Raspberry Pi 5 Support
diff mbox series

Message ID ae369612-0d35-47b9-8796-d3670bfd9086@gmx.de
State New
Headers show
Series
  • Raspberry Pi 5 Support
Related show

Commit Message

Christian Rauch May 17, 2026, 10:38 a.m. UTC
Dear all,

A while ago (actually nearly a year to this date) I was asking about the 
Raspberry Pi 5 support in upstream libcamera and Naush mentioned that 
Raspberry Pi is using a workaround in the CFE kernel driver to make this 
work. I assume that Naush was talking about the kernel module "rp1_cfe", 
which is shipped with the workaround as "rp1_cfe_downstream" in 
Raspberry Pi OS.

Ubuntu 26.04 with its kernel "7.0.0-1010-raspi" ships the "rp1_cfe" 
module with workaround as "rp1_cfe_downstream" too, and also patched 
(patch attached) the upstream libcamera sources with a fix to detect the 
camera when either of those kernel modules is loaded.

Since the Raspberry Pi 5 support is still not available with upstream 
libcamera and the "rp1_cfe" kernel module, and it seems it is going to 
stay that way for a while, would you accept the attached patch to 
replicate the behaviour in the Raspberry Pi libcamera fork?

Given that the "rp1_cfe" module does not work with the upstream 
"rpi/pisp" pipeline, how do you know that this pipeline handler is 
actually working? Are you carrying custom patches on top of "rp1_cfe" to 
make the upstream "rpi/pisp" work? Once the required features are merged 
into upstream module "rp1_cfe", how do you know that the "rpi/pisp" 
pipeline will still be compatible?

Alternatively, couldn't the patches to the pipeline handler and kernel 
modules be upstreamed in order to resolve this issue?

Best,
Christian

Patch
diff mbox series

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;
 	}