summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/pipeline/rpi/vc4/vc4.cpp78
1 files changed, 68 insertions, 10 deletions
diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
index 2114106c..3108af99 100644
--- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
@@ -5,6 +5,8 @@
* vc4.cpp - Pipeline handler for VC4-based Raspberry Pi devices
*/
+#include <memory>
+
#include <linux/bcm2835-isp.h>
#include <linux/v4l2-controls.h>
#include <linux/videodev2.h>
@@ -13,6 +15,7 @@
#include "libcamera/internal/device_enumerator.h"
#include "libcamera/internal/dma_heaps.h"
+#include "libcamera/internal/v4l2_subdevice.h"
#include "../common/pipeline_base.h"
#include "../common/rpi_stream.h"
@@ -31,6 +34,10 @@ namespace {
enum class Unicam : unsigned int { Image, Embedded };
enum class Isp : unsigned int { Input, Output0, Output1, Stats };
+static constexpr unsigned int kUnicamSinkPad = 0;
+static constexpr unsigned int kUnicamSourceImagePad = 1;
+static constexpr unsigned int kUnicamSourceMetadataPad = 2;
+
} /* namespace */
class Vc4CameraData final : public RPi::CameraData
@@ -81,6 +88,8 @@ public:
void setIspControls(const ControlList &controls);
void setCameraTimeout(uint32_t maxFrameLengthMs);
+ std::unique_ptr<V4L2Subdevice> unicamSubdev_;
+
/* Array of Unicam and ISP device streams and associated buffers/streams. */
RPi::Device<Unicam, 2> unicam_;
RPi::Device<Isp, 4> isp_;
@@ -309,6 +318,7 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
if (!data->dmaHeap_.isValid())
return -ENOMEM;
+ MediaEntity *unicamSubdev = unicam->getEntityByName("unicam");
MediaEntity *unicamImage = unicam->getEntityByName("unicam-image");
MediaEntity *unicamEmbedded = unicam->getEntityByName("unicam-embedded");
MediaEntity *ispOutput0 = isp->getEntityByName("bcm2835-isp0-output0");
@@ -320,7 +330,13 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
!ispOutput0 || !ispCapture1 || !ispCapture2 || !ispCapture3)
return -ENOENT;
- /* Create the unicam video streams. */
+ if (!unicamSubdev) {
+ LOG(RPI, Error) << "Downstream Unicam driver not supported, please update your kernel!";
+ return -EINVAL;
+ }
+
+ /* Create the unicam subdev and video streams. */
+ data->unicamSubdev_ = std::make_unique<V4L2Subdevice>(unicamSubdev);
data->unicam_[Unicam::Image] = RPi::Stream("Unicam Image", unicamImage);
data->unicam_[Unicam::Embedded] = RPi::Stream("Unicam Embedded", unicamEmbedded);
@@ -349,6 +365,10 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
* The below grouping is just for convenience so that we can easily
* iterate over all streams in one go.
*/
+ int ret = data->unicamSubdev_->open();
+ if (ret < 0)
+ return ret;
+
data->streams_.push_back(&data->unicam_[Unicam::Image]);
if (data->sensorMetadata_)
data->streams_.push_back(&data->unicam_[Unicam::Embedded]);
@@ -357,16 +377,11 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer
data->streams_.push_back(&stream);
for (auto stream : data->streams_) {
- int ret = stream->dev()->open();
+ ret = stream->dev()->open();
if (ret)
return ret;
}
- if (!data->unicam_[Unicam::Image].dev()->caps().hasMediaController()) {
- LOG(RPI, Error) << "Unicam driver does not use the MediaController, please update your kernel!";
- return -EINVAL;
- }
-
/* Write up all the IPA connections. */
data->ipa_->processStatsComplete.connect(data, &Vc4CameraData::processStatsComplete);
data->ipa_->prepareIspComplete.connect(data, &Vc4CameraData::prepareIspComplete);
@@ -529,7 +544,50 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &
int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfig)
{
/*
- * 1. Configure the Unicam video devices.
+ * 1. Configure the Unicam subdev.
+ *
+ * Start by setting up routes, and then set the formats on the sink pad
+ * streams. They will be automatically propagated to the source pads by
+ * the kernel.
+ */
+
+ const V4L2Subdevice::Stream imageStream{
+ kUnicamSinkPad,
+ sensor_->imageStream().stream
+ };
+ const V4L2Subdevice::Stream embeddedDataStream{
+ kUnicamSinkPad,
+ sensor_->embeddedDataStream().value_or(V4L2Subdevice::Stream{}).stream
+ };
+
+ V4L2Subdevice::Routing routing;
+
+ routing.emplace_back(imageStream, V4L2Subdevice::Stream{ kUnicamSourceImagePad, 0 },
+ V4L2_SUBDEV_ROUTE_FL_ACTIVE);
+
+ if (sensorMetadata_)
+ routing.emplace_back(embeddedDataStream,
+ V4L2Subdevice::Stream{ kUnicamSourceMetadataPad, 0 },
+ V4L2_SUBDEV_ROUTE_FL_ACTIVE);
+
+ int ret = unicamSubdev_->setRouting(&routing);
+ if (ret)
+ return ret;
+
+ V4L2SubdeviceFormat subdevFormat = rpiConfig->sensorFormat_;
+ ret = unicamSubdev_->setFormat(imageStream, &subdevFormat);
+ if (ret)
+ return ret;
+
+ if (sensorMetadata_) {
+ subdevFormat = sensor_->embeddedDataFormat();
+ ret = unicamSubdev_->setFormat(embeddedDataStream, &subdevFormat);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * 2. Configure the Unicam video devices.
*/
V4L2VideoDevice *unicam = unicam_[Unicam::Image].dev();
@@ -552,7 +610,7 @@ int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfi
BayerFormat::Packing::CSI2);
}
- int ret = unicam->setFormat(&unicamFormat);
+ ret = unicam->setFormat(&unicamFormat);
if (ret)
return ret;
@@ -580,7 +638,7 @@ int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfi
}
/*
- * 2. Configure the ISP.
+ * 3. Configure the ISP.
*/
ret = isp_[Isp::Input].dev()->setFormat(&unicamFormat);