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-09-30 11:15:29 +0300
commit77ee017ed30f64ea33c7e2ccbf8676a30075a717 (patch)
tree24f99139048dec7f9a1bfe103ae7d37ac987f83d
parent7082f6bbec4b39295180730573a7e0152cd8b756 (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 392d3486..f55cd4a4 100644
--- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp
+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp
@@ -5,6 +5,8 @@
* 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_buf_allocator.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);