From patchwork Fri Mar 1 21:21:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 19620 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 5BB99C3260 for ; Fri, 1 Mar 2024 21:22:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 18D6362C84; Fri, 1 Mar 2024 22:22:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ByigtAHf"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 3400662C94 for ; Fri, 1 Mar 2024 22:22:02 +0100 (CET) Received: from pendragon.ideasonboard.com (89-27-53-110.bb.dnainternet.fi [89.27.53.110]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id B16EE3DF7; Fri, 1 Mar 2024 22:21:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1709328107; bh=LGJCkU8WiFH6nxUqWNKrukB57KBiBbJ9SDEhPjBxC3I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ByigtAHfZn7Sf6mKKFxJfplcF38unKFtJu2CEmTtwlc5DvvykLjohcj4ewZDkdFXS xTtsjj4z+/ghTSz37RzADKnD1xaQlQ3CO6ugaToOTPGBmiPuGHmbnv5RNykOHWjKku wn4jfV+UB3M/SG4scyMA/7u0LbyfiMasNF/laXhg= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH/RFC 29/32] pipeline: raspberrypi: vc4: Configure format on Unicam subdev Date: Fri, 1 Mar 2024 23:21:18 +0200 Message-ID: <20240301212121.9072-30-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240301212121.9072-1-laurent.pinchart@ideasonboard.com> References: <20240301212121.9072-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Sakari Ailus Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" 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 --- src/libcamera/pipeline/rpi/vc4/vc4.cpp | 78 ++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp index da925ba5f793..81e0bc1b8f7a 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 + #include #include #include @@ -12,6 +14,7 @@ #include #include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/v4l2_subdevice.h" #include "../common/pipeline_base.h" #include "../common/rpi_stream.h" @@ -32,6 +35,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 @@ -82,6 +89,8 @@ public: void setIspControls(const ControlList &controls); void setCameraTimeout(uint32_t maxFrameLengthMs); + std::unique_ptr unicamSubdev_; + /* Array of Unicam and ISP device streams and associated buffers/streams. */ RPi::Device unicam_; RPi::Device isp_; @@ -310,6 +319,7 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr &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"); @@ -321,7 +331,13 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr &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(unicamSubdev); data->unicam_[Unicam::Image] = RPi::Stream("Unicam Image", unicamImage); data->unicam_[Unicam::Embedded] = RPi::Stream("Unicam Embedded", unicamEmbedded); @@ -350,6 +366,10 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr &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]); @@ -358,16 +378,11 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr &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); @@ -530,7 +545,50 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr & 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(); @@ -553,7 +611,7 @@ int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfi BayerFormat::Packing::CSI2); } - int ret = unicam->setFormat(&unicamFormat); + ret = unicam->setFormat(&unicamFormat); if (ret) return ret; @@ -581,7 +639,7 @@ int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfi } /* - * 2. Configure the ISP. + * 3. Configure the ISP. */ ret = isp_[Isp::Input].dev()->setFormat(&unicamFormat);