summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2023-08-01 21:50:26 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2024-04-24 20:44:26 +0300
commit3b2e84a779f51d5eca47d663395c7dc3cb7cb1f3 (patch)
tree26e747bc63a6aecc81c1158c1f001977937d97c5
parent7efdad196d012c72f9a2440abbacbe05fffc5d8b (diff)
pipeline: raspberrypi: vc4: Configure format on Unicam subdev
The mainline Unicam driver creates a V4L2 subdevice, which needs to be configured. Create and open a corresponding V4L2Subdevice instance and configure the format on its sink pad in the platformConfigure() function. Presence of the Unicam subdev is required, to avoid extra complexity. This drops support for the driver from the Raspberry Pi downstream kernel. Users are expected to update their kernel to use the mainline Unicam driver. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-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);