[v2,6/8] pipeline: rpi: vc4: Switch to mainline media topology for bcm2835-isp
diff mbox series

Message ID 20260722-pi4-upstream-v2-6-eb44d3c6fd92@ideasonboard.com
State New
Headers show
Series
  • Raspberry Pi: Update VC4 pipeline for mainline
Related show

Commit Message

Jai Luthra July 22, 2026, 11:23 a.m. UTC
Switch from the downstream driver's video node naming scheme of
bcm2835-isp0-output0,capture1..3 to the mainline scheme of
bcm2835-isp-output0,capture0..1,stats2.

Users are expected to update their kernel to use the mainline VC4
driver.

For now we only initialize the new bcm2835-isp-params video node.
Filling and queueing buffers to the node will be handled in a subsequent
commit.

Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
---
 src/libcamera/pipeline/rpi/common/rpi_stream.h |  1 +
 src/libcamera/pipeline/rpi/vc4/vc4.cpp         | 49 +++++++++++++++++++-------
 2 files changed, 37 insertions(+), 13 deletions(-)

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.h b/src/libcamera/pipeline/rpi/common/rpi_stream.h
index 300a352a7..cc18dcc8f 100644
--- a/src/libcamera/pipeline/rpi/common/rpi_stream.h
+++ b/src/libcamera/pipeline/rpi/common/rpi_stream.h
@@ -30,6 +30,7 @@  enum BufferMask {
 	MaskStats		= 0x010000,
 	MaskEmbeddedData	= 0x020000,
 	MaskBayerData		= 0x040000,
+	MaskParams		= 0x080000,
 };
 
 struct BufferObject {
diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
index f06c439d5..e9fae8890 100644
--- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
@@ -32,7 +32,7 @@  using StreamParams = RPi::RPiCameraConfiguration::StreamParams;
 namespace {
 
 enum class Unicam : unsigned int { Image, Embedded };
-enum class Isp : unsigned int { Input, Output0, Output1, Stats };
+enum class Isp : unsigned int { Input, Output0, Output1, Stats, Params };
 
 static constexpr unsigned int kUnicamSinkPad = 0;
 static constexpr unsigned int kUnicamSourceImagePad = 1;
@@ -93,7 +93,7 @@  public:
 
 	/* Array of Unicam and ISP device streams and associated buffers/streams. */
 	RPi::Device<Unicam, 2> unicam_;
-	RPi::Device<Isp, 4> isp_;
+	RPi::Device<Isp, 5> isp_;
 
 	/* DMAHEAP allocation helper. */
 	DmaBufAllocator dmaHeap_;
@@ -267,6 +267,13 @@  int PipelineHandlerVc4::allocateBuffers(Camera *camera)
 				     std::max<int>(data->config_.minUnicamBuffers,
 						   minBuffers - numRawBuffers);
 
+		} else if (stream == &data->isp_[Isp::Params]) {
+			/*
+			 * Parameter buffers are dequeued immediately after
+			 * sending the commands to VC4 firmware. Ideally, 1
+			 * buffer would be sufficient, but allot 2 to be safe.
+			 */
+			numBuffers = 2;
 		} else if (stream == &data->unicam_[Unicam::Embedded]) {
 			/*
 			 * Embedded data buffers are (currently) for internal use, and
@@ -303,10 +310,11 @@  int PipelineHandlerVc4::allocateBuffers(Camera *camera)
 	}
 
 	/*
-	 * Pass the stats and embedded data buffers to the IPA. No other
-	 * buffers need to be passed.
+	 * Pass the stats, embedded data and parameter buffers to the IPA. No
+	 * other buffers need to be passed.
 	 */
 	mapBuffers(camera, data->isp_[Isp::Stats].getBuffers(), RPi::MaskStats);
+	mapBuffers(camera, data->isp_[Isp::Params].getBuffers(), RPi::MaskParams);
 	if (data->sensorMetadata_)
 		mapBuffers(camera, data->unicam_[Unicam::Embedded].getBuffers(),
 			   RPi::MaskEmbeddedData);
@@ -325,13 +333,14 @@  int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
 
 	MediaEntity *unicamSubdev = unicam->getEntityByName("unicam");
 	MediaEntity *unicamImage = unicam->getEntityByName("unicam-image");
-	MediaEntity *ispOutput0 = isp->getEntityByName("bcm2835-isp0-output0");
-	MediaEntity *ispCapture1 = isp->getEntityByName("bcm2835-isp0-capture1");
-	MediaEntity *ispCapture2 = isp->getEntityByName("bcm2835-isp0-capture2");
-	MediaEntity *ispCapture3 = isp->getEntityByName("bcm2835-isp0-capture3");
+	MediaEntity *ispOutput0 = isp->getEntityByName("bcm2835-isp-output0");
+	MediaEntity *ispCapture0 = isp->getEntityByName("bcm2835-isp-capture0");
+	MediaEntity *ispCapture1 = isp->getEntityByName("bcm2835-isp-capture1");
+	MediaEntity *ispCapture2 = isp->getEntityByName("bcm2835-isp-stats2");
+	MediaEntity *ispParams = isp->getEntityByName("bcm2835-isp-params");
 
-	if (!unicamSubdev || !unicamImage || !ispOutput0 || !ispCapture1 ||
-	    !ispCapture2 || !ispCapture3)
+	if (!unicamSubdev || !unicamImage || !ispOutput0 || !ispCapture0 ||
+	    !ispCapture1 || !ispCapture2 || !ispParams)
 		return -ENOENT;
 
 	/* Create the unicam subdev and video streams. */
@@ -348,9 +357,12 @@  int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
 
 	/* Tag the ISP input stream as an import stream. */
 	data->isp_[Isp::Input] = RPi::Stream("ISP Input", ispOutput0, StreamFlag::ImportOnly);
-	data->isp_[Isp::Output0] = RPi::Stream("ISP Output0", ispCapture1);
-	data->isp_[Isp::Output1] = RPi::Stream("ISP Output1", ispCapture2);
-	data->isp_[Isp::Stats] = RPi::Stream("ISP Stats", ispCapture3);
+	data->isp_[Isp::Output0] = RPi::Stream("ISP Output0", ispCapture0);
+	data->isp_[Isp::Output1] = RPi::Stream("ISP Output1", ispCapture1);
+	data->isp_[Isp::Stats] = RPi::Stream("ISP Stats", ispCapture2);
+	/* Tag the ISP params stream as MMAP (for writing into it in the IPA) and recurrent. */
+	data->isp_[Isp::Params] = RPi::Stream("ISP Params", ispParams,
+					      StreamFlag::RequiresMmap | StreamFlag::Recurrent);
 
 	/* Wire up all the buffer connections. */
 	data->unicam_[Unicam::Image].dev()->bufferReady.connect(data, &Vc4CameraData::unicamBufferDequeue);
@@ -358,6 +370,7 @@  int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
 	data->isp_[Isp::Output0].dev()->bufferReady.connect(data, &Vc4CameraData::ispOutputDequeue);
 	data->isp_[Isp::Output1].dev()->bufferReady.connect(data, &Vc4CameraData::ispOutputDequeue);
 	data->isp_[Isp::Stats].dev()->bufferReady.connect(data, &Vc4CameraData::ispOutputDequeue);
+	data->isp_[Isp::Params].dev()->bufferReady.connect(data, &Vc4CameraData::ispOutputDequeue);
 
 	if (data->sensorMetadata_ ^ !!data->unicam_[Unicam::Embedded].dev()) {
 		LOG(RPI, Warning) << "Mismatch between Unicam and CamHelper for embedded data usage!";
@@ -758,6 +771,16 @@  int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfi
 		return ret;
 	}
 
+	/* ISP parameters input format. */
+	format = {};
+	format.fourcc = V4L2PixelFormat(V4L2_META_FMT_BCM2835_ISP_PARAMS);
+	ret = isp_[Isp::Params].dev()->setFormat(&format);
+	if (ret) {
+		LOG(RPI, Error) << "Failed to set format on ISP params stream: "
+				<< format;
+		return ret;
+	}
+
 	/*
 	 * Configure the Unicam embedded data output format only if the sensor
 	 * supports it.