Patch Detail
Show a patch.
GET /api/1.1/patches/26393/?format=api
{ "id": 26393, "url": "https://patchwork.libcamera.org/api/1.1/patches/26393/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26393/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260331-mali-cru-v7-3-4caedc898a0e@ideasonboard.com>", "date": "2026-03-31T16:36:31", "name": "[v7,3/8] libcamera: mali-c55: Split TPG and Inline camera handling", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "631f1ff79990fb38d966cc00be2d6e9e56b7299d", "submitter": { "id": 143, "url": "https://patchwork.libcamera.org/api/1.1/people/143/?format=api", "name": "Jacopo Mondi", "email": "jacopo.mondi@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26393/mbox/", "series": [ { "id": 5860, "url": "https://patchwork.libcamera.org/api/1.1/series/5860/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5860", "date": "2026-03-31T16:36:28", "name": "libcamera: mali-c55: Add support for memory-to-memory", "version": 7, "mbox": "https://patchwork.libcamera.org/series/5860/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26393/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26393/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 3829FC32BB\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 31 Mar 2026 16:36:58 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6321762D48;\n\tTue, 31 Mar 2026 18:36:55 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id C02E96274D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 31 Mar 2026 18:36:50 +0200 (CEST)", "from [100.93.44.16] (net-93-65-100-155.cust.vodafonedsl.it\n\t[93.65.100.155])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 48A8F31A5;\n\tTue, 31 Mar 2026 18:35:28 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"GMmKJ9oq\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1774974928;\n\tbh=jFpT13cBTk2VgxmG46TrkerQDDgq6237mXTx4G/Gn0A=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=GMmKJ9oqxeNuq6oYdsLDjrTHlxOTm4Z9snQmCtxT/tvrk4GisDBy0Dn6mV4CP5qUI\n\tQsCmSxk5Y7RL6deKuV8FAy8mNSf8fkb/CMGE7z4aGvzAn5lpBJfzJyAIbNWt361h3e\n\tjYXSz6xRjmHz39hlBH5fudz3CAscCpjc2fLtVBDk=", "From": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>", "Date": "Tue, 31 Mar 2026 18:36:31 +0200", "Subject": "[PATCH v7 3/8] libcamera: mali-c55: Split TPG and Inline camera\n\thandling", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "8bit", "Message-Id": "<20260331-mali-cru-v7-3-4caedc898a0e@ideasonboard.com>", "References": "<20260331-mali-cru-v7-0-4caedc898a0e@ideasonboard.com>", "In-Reply-To": "<20260331-mali-cru-v7-0-4caedc898a0e@ideasonboard.com>", "To": "Daniel Scally <dan.scally@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org", "Cc": "=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>,\n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>", "X-Mailer": "b4 0.14.3", "X-Developer-Signature": "v=1; a=openpgp-sha256; l=16182;\n\ti=jacopo.mondi@ideasonboard.com; h=from:subject:message-id;\n\tbh=jFpT13cBTk2VgxmG46TrkerQDDgq6237mXTx4G/Gn0A=;\n\tb=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBpy/ggtOwTDBDtAkBzyqIVUMJ6vYUXWFgXZ8OsU\n\tyqcYzxDcIOJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCacv4IAAKCRByNAaPFqFW\n\tPIR0D/44qvFk5jABHbHra0jtN+kxfVWlGUasd+X70cMRODANSeQkSJXeVV0xrEKE6olswDkqGw1\n\tOY8OHxYJTM8pWyfwyy1Jow6VeRAjlXQBnbCVVkHlhA9THCTmvRMtU83l6DOoE9zSbFR4QNaUVdB\n\tJawfvFz8fAYCAie3/uUJBALYCUHWwCwBHYKReR0vl8DUE2DBPJwTaSyCf4fomG3wnuGT9EI1Ahl\n\tmOHyZ6xCtAC4idUaCdnQf19x9TyU93HM1cj6ncW3YAeqo5D3rxrubB+6/NA0hWkWI8FsEHSOKg/\n\t+cMcT8vnhnBu8E+HqQcIdrHUF2r9Jm3zCMv3b/Sd+HEK46IeZrJ+qe/kbOzqWkElW3Vts5vo0h7\n\tBv6Mk7w4oge+WzYT7QEA0Wz/qukGnzYyqkDa5onWUFopLsHbwmHDZnfZ9VkSR6Xs6mvOTMT+OXY\n\tovreGNNY58LUDzqosGNoMfxuWZqjYjfAJReqH9S3NohkaNvistyI1HQ5dLSLNgLC31k0ao+6FIJ\n\tQ86MyH+x+uiqMDQmAvox4AfPWtmzXJdqNLyhDFTSHNW/q1yNWJkmkbBu/29fPjYSCVfR8nh3vWB\n\tmazQKTprmTyz6aaDoK/VS3yJoqPYETVgQKlGLg46rNYdqUs862Hp/Jo4iyrKecbqtL8PeJyNCT+\n\tLRmJyNzw9zQ9eSg==", "X-Developer-Key": "i=jacopo.mondi@ideasonboard.com; a=openpgp;\n\tfpr=72392EDC88144A65C701EA9BA5826A2587AD026B", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "In order to prepare to support memory input cameras, split the handling of\nthe TPG and Inline camera cases.\n\nThe Mali C55 pipeline handler uses the entity and subdevice stored in the\nCameraData to support both the handling of the TPG and of the Inline (CSI-2\n+ sensor) use cases. Adding support for memory cameras by using the CRU unit\nwould add yet-another special case making the code harder to follow and\nmore prone to errors.\n\nSplit the handling of the TPG and Inline cameras by introducing an\nstd::variant<> variable and to deflect the functions called on the\ncamera data to the correct type by using overloaded std::visit<>().\n\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\nReviewed-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n---\n src/libcamera/pipeline/mali-c55/mali-c55.cpp | 278 ++++++++++++++++-----------\n 1 file changed, 162 insertions(+), 116 deletions(-)", "diff": "diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\nindex c209b0b070b1..26dfd0aef73c 100644\n--- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n+++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n@@ -11,12 +11,14 @@\n #include <memory>\n #include <set>\n #include <string>\n+#include <variant>\n \n #include <linux/mali-c55-config.h>\n #include <linux/media-bus-format.h>\n #include <linux/media.h>\n \n #include <libcamera/base/log.h>\n+#include <libcamera/base/utils.h>\n \n #include <libcamera/camera.h>\n #include <libcamera/formats.h>\n@@ -92,17 +94,77 @@ struct MaliC55FrameInfo {\n class MaliC55CameraData : public Camera::Private\n {\n public:\n-\tMaliC55CameraData(PipelineHandler *pipe, MediaEntity *entity)\n-\t\t: Camera::Private(pipe), entity_(entity)\n+\tstruct Tpg {\n+\t\tstd::vector<Size> sizes(unsigned int mbusCode) const;\n+\n+\t\tSize resolution_;\n+\t\tstd::unique_ptr<V4L2Subdevice> sd_;\n+\t};\n+\n+\tstruct Inline {\n+\t\tstd::unique_ptr<V4L2Subdevice> csi2_;\n+\t\tstd::unique_ptr<CameraSensor> sensor_;\n+\t};\n+\tusing CameraType = std::variant<Tpg, Inline>;\n+\n+\tMaliC55CameraData(PipelineHandler *pipe)\n+\t\t: Camera::Private(pipe)\n \t{\n \t}\n \n-\tint init();\n \tint loadIPA();\n \n-\t/* Deflect these functionalities to either TPG or CameraSensor. */\n-\tstd::vector<Size> sizes(unsigned int mbusCode) const;\n-\tSize resolution() const;\n+\tTpg *initTpg(MediaEntity *entity);\n+\tInline *initInline(MediaEntity *entity);\n+\n+\tstd::vector<Size> sizes(unsigned int mbusCode) const\n+\t{\n+\t\treturn std::visit(utils::overloaded{\n+\t\t\t[&](const Tpg &tpg) -> std::vector<Size> {\n+\t\t\t\treturn tpg.sizes(mbusCode);\n+\t\t\t},\n+\t\t\t[&](const Inline &in) -> std::vector<Size> {\n+\t\t\t\treturn in.sensor_->sizes(mbusCode);\n+\t\t\t}\n+\t\t}, input_);\n+\t}\n+\n+\tV4L2Subdevice *subdev() const\n+\t{\n+\t\treturn std::visit(utils::overloaded{\n+\t\t\t[&](const Tpg &tpg) -> V4L2Subdevice * {\n+\t\t\t\treturn tpg.sd_.get();\n+\t\t\t},\n+\t\t\t[&](const Inline &in) -> V4L2Subdevice * {\n+\t\t\t\treturn in.sensor_->device();\n+\t\t\t},\n+\t\t}, input_);\n+\t}\n+\n+\tCameraSensor *sensor() const\n+\t{\n+\t\treturn std::visit(utils::overloaded{\n+\t\t\t[&](auto &) -> CameraSensor * {\n+\t\t\t\tASSERT(false);\n+\t\t\t\treturn nullptr;\n+\t\t\t},\n+\t\t\t[&](const Inline &in) -> CameraSensor * {\n+\t\t\t\treturn in.sensor_.get();\n+\t\t\t},\n+\t\t}, input_);\n+\t}\n+\n+\tSize resolution() const\n+\t{\n+\t\treturn std::visit(utils::overloaded{\n+\t\t\t[&](const Tpg &tpg) -> Size {\n+\t\t\t\treturn tpg.resolution_;\n+\t\t\t},\n+\t\t\t[&](const Inline &in) -> Size {\n+\t\t\t\treturn in.sensor_->resolution();\n+\t\t\t},\n+\t\t}, input_);\n+\t}\n \n \tint pixfmtToMbusCode(const PixelFormat &pixFmt) const;\n \tconst PixelFormat &bestRawFormat() const;\n@@ -112,11 +174,6 @@ public:\n \tPixelFormat adjustRawFormat(const PixelFormat &pixFmt) const;\n \tSize adjustRawSizes(const PixelFormat &pixFmt, const Size &rawSize) const;\n \n-\tstd::unique_ptr<CameraSensor> sensor_;\n-\n-\tMediaEntity *entity_;\n-\tstd::unique_ptr<V4L2Subdevice> csi_;\n-\tstd::unique_ptr<V4L2Subdevice> sd_;\n \tStream frStream_;\n \tStream dsStream_;\n \n@@ -126,58 +183,28 @@ public:\n \n \tstd::unique_ptr<DelayedControls> delayedCtrls_;\n \n+\tCameraType input_;\n+\n private:\n-\tvoid initTPGData();\n \tvoid setSensorControls(const ControlList &sensorControls);\n-\n \tstd::string id_;\n-\tSize tpgResolution_;\n };\n \n-int MaliC55CameraData::init()\n+MaliC55CameraData::Tpg *MaliC55CameraData::initTpg(MediaEntity *entity)\n {\n-\tint ret;\n+\tTpg tpg;\n \n-\tsd_ = std::make_unique<V4L2Subdevice>(entity_);\n-\tret = sd_->open();\n+\ttpg.sd_ = std::make_unique<V4L2Subdevice>(entity);\n+\tint ret = tpg.sd_->open();\n \tif (ret) {\n-\t\tLOG(MaliC55, Error) << \"Failed to open sensor subdevice\";\n-\t\treturn ret;\n-\t}\n-\n-\t/* If this camera is created from TPG, we return here. */\n-\tif (entity_->name() == \"mali-c55 tpg\") {\n-\t\tinitTPGData();\n-\t\treturn 0;\n-\t}\n-\n-\t/*\n-\t * Register a CameraSensor if we connect to a sensor and create\n-\t * an entity for the connected CSI-2 receiver.\n-\t */\n-\tsensor_ = CameraSensorFactoryBase::create(entity_);\n-\tif (!sensor_)\n-\t\treturn -ENODEV;\n-\n-\tconst MediaPad *sourcePad = entity_->getPadByIndex(0);\n-\tMediaEntity *csiEntity = sourcePad->links()[0]->sink()->entity();\n-\n-\tcsi_ = std::make_unique<V4L2Subdevice>(csiEntity);\n-\tret = csi_->open();\n-\tif (ret) {\n-\t\tLOG(MaliC55, Error) << \"Failed to open CSI-2 subdevice\";\n-\t\treturn ret;\n+\t\tLOG(MaliC55, Error) << \"Failed to open TPG subdevice\";\n+\t\treturn nullptr;\n \t}\n \n-\treturn 0;\n-}\n-\n-void MaliC55CameraData::initTPGData()\n-{\n \t/* Replicate the CameraSensor implementation for TPG. */\n-\tV4L2Subdevice::Formats formats = sd_->formats(0);\n+\tV4L2Subdevice::Formats formats = tpg.sd_->formats(0);\n \tif (formats.empty())\n-\t\treturn;\n+\t\treturn nullptr;\n \n \tstd::vector<Size> tpgSizes;\n \n@@ -187,19 +214,35 @@ void MaliC55CameraData::initTPGData()\n \t\t\t [](const SizeRange &range) { return range.max; });\n \t}\n \n-\ttpgResolution_ = tpgSizes.back();\n+\ttpg.resolution_ = tpgSizes.back();\n+\n+\treturn &input_.emplace<Tpg>(std::move(tpg));\n }\n \n-void MaliC55CameraData::setSensorControls(const ControlList &sensorControls)\n+MaliC55CameraData::Inline *MaliC55CameraData::initInline(MediaEntity *sensor)\n {\n-\tdelayedCtrls_->push(sensorControls);\n+\tInline in;\n+\n+\t/* Register a CameraSensor and create an entity for the CSI-2 receiver. */\n+\tin.sensor_ = CameraSensorFactoryBase::create(sensor);\n+\tif (!in.sensor_)\n+\t\treturn nullptr;\n+\n+\tconst MediaPad *sourcePad = sensor->getPadByIndex(0);\n+\tMediaEntity *csiEntity = sourcePad->links()[0]->sink()->entity();\n+\n+\tin.csi2_ = std::make_unique<V4L2Subdevice>(csiEntity);\n+\tint ret = in.csi2_->open();\n+\tif (ret) {\n+\t\tLOG(MaliC55, Error) << \"Failed to open CSI-2 subdevice\";\n+\t\treturn nullptr;\n+\t}\n+\n+\treturn &input_.emplace<Inline>(std::move(in));\n }\n \n-std::vector<Size> MaliC55CameraData::sizes(unsigned int mbusCode) const\n+std::vector<Size> MaliC55CameraData::Tpg::sizes(unsigned int mbusCode) const\n {\n-\tif (sensor_)\n-\t\treturn sensor_->sizes(mbusCode);\n-\n \tV4L2Subdevice::Formats formats = sd_->formats(0);\n \tif (formats.empty())\n \t\treturn {};\n@@ -218,12 +261,9 @@ std::vector<Size> MaliC55CameraData::sizes(unsigned int mbusCode) const\n \treturn sizes;\n }\n \n-Size MaliC55CameraData::resolution() const\n+void MaliC55CameraData::setSensorControls(const ControlList &sensorControls)\n {\n-\tif (sensor_)\n-\t\treturn sensor_->resolution();\n-\n-\treturn tpgResolution_;\n+\tdelayedCtrls_->push(sensorControls);\n }\n \n /*\n@@ -242,7 +282,7 @@ int MaliC55CameraData::pixfmtToMbusCode(const PixelFormat &pixFmt) const\n \tif (!bayerFormat.isValid())\n \t\treturn -EINVAL;\n \n-\tV4L2Subdevice::Formats formats = sd_->formats(0);\n+\tV4L2Subdevice::Formats formats = subdev()->formats(0);\n \tunsigned int sensorMbusCode = 0;\n \tunsigned int bitDepth = 0;\n \n@@ -280,7 +320,7 @@ const PixelFormat &MaliC55CameraData::bestRawFormat() const\n {\n \tstatic const PixelFormat invalidPixFmt = {};\n \n-\tfor (const auto &fmt : sd_->formats(0)) {\n+\tfor (const auto &fmt : subdev()->formats(0)) {\n \t\tBayerFormat sensorBayer = BayerFormat::fromMbusCode(fmt.first);\n \n \t\tif (!sensorBayer.isValid())\n@@ -302,11 +342,11 @@ const PixelFormat &MaliC55CameraData::bestRawFormat() const\n \n void MaliC55CameraData::updateControls(const ControlInfoMap &ipaControls)\n {\n-\tif (!sensor_)\n+\tif (std::holds_alternative<Tpg>(input_))\n \t\treturn;\n \n \tIPACameraSensorInfo sensorInfo;\n-\tint ret = sensor_->sensorInfo(&sensorInfo);\n+\tint ret = sensor()->sensorInfo(&sensorInfo);\n \tif (ret) {\n \t\tLOG(MaliC55, Error) << \"Failed to retrieve sensor info\";\n \t\treturn;\n@@ -379,7 +419,7 @@ int MaliC55CameraData::loadIPA()\n \tint ret;\n \n \t/* Do not initialize IPA for TPG. */\n-\tif (!sensor_)\n+\tif (std::holds_alternative<Tpg>(input_))\n \t\treturn 0;\n \n \tipa_ = IPAManager::createIPA<ipa::mali_c55::IPAProxyMaliC55>(pipe(), 1, 1);\n@@ -388,20 +428,20 @@ int MaliC55CameraData::loadIPA()\n \n \tipa_->setSensorControls.connect(this, &MaliC55CameraData::setSensorControls);\n \n-\tstd::string ipaTuningFile = ipa_->configurationFile(sensor_->model() + \".yaml\",\n+\tstd::string ipaTuningFile = ipa_->configurationFile(sensor()->model() + \".yaml\",\n \t\t\t\t\t\t\t \"uncalibrated.yaml\");\n \n \t/* We need to inform the IPA of the sensor configuration */\n \tipa::mali_c55::IPAConfigInfo ipaConfig{};\n \n-\tret = sensor_->sensorInfo(&ipaConfig.sensorInfo);\n+\tret = sensor()->sensorInfo(&ipaConfig.sensorInfo);\n \tif (ret)\n \t\treturn ret;\n \n-\tipaConfig.sensorControls = sensor_->controls();\n+\tipaConfig.sensorControls = sensor()->controls();\n \n \tControlInfoMap ipaControls;\n-\tret = ipa_->init({ ipaTuningFile, sensor_->model() }, ipaConfig,\n+\tret = ipa_->init({ ipaTuningFile, sensor()->model() }, ipaConfig,\n \t\t\t &ipaControls);\n \tif (ret) {\n \t\tLOG(MaliC55, Error) << \"Failed to initialise the Mali-C55 IPA\";\n@@ -444,13 +484,13 @@ CameraConfiguration::Status MaliC55CameraConfiguration::validate()\n \t * The TPG doesn't support flips, so we only need to calculate a\n \t * transform if we have a sensor.\n \t */\n-\tif (data_->sensor_) {\n+\tif (std::holds_alternative<MaliC55CameraData::Tpg>(data_->input_)) {\n+\t\tcombinedTransform_ = Transform::Rot0;\n+\t} else {\n \t\tOrientation requestedOrientation = orientation;\n-\t\tcombinedTransform_ = data_->sensor_->computeTransform(&orientation);\n+\t\tcombinedTransform_ = data_->sensor()->computeTransform(&orientation);\n \t\tif (orientation != requestedOrientation)\n \t\t\tstatus = Adjusted;\n-\t} else {\n-\t\tcombinedTransform_ = Transform::Rot0;\n \t}\n \n \t/* Only 2 streams available. */\n@@ -927,39 +967,44 @@ int PipelineHandlerMaliC55::configure(Camera *camera,\n \n \t/* Link the graph depending if we are operating the TPG or a sensor. */\n \tMaliC55CameraData *data = cameraData(camera);\n-\tif (data->csi_) {\n-\t\tconst MediaEntity *csiEntity = data->csi_->entity();\n-\t\tret = csiEntity->getPadByIndex(1)->links()[0]->setEnabled(true);\n-\t} else {\n-\t\tret = data->entity_->getPadByIndex(0)->links()[0]->setEnabled(true);\n-\t}\n+\tret = std::visit(utils::overloaded{\n+\t\t[](MaliC55CameraData::Tpg &tpg) {\n+\t\t\tconst MediaEntity *tpgEntity = tpg.sd_->entity();\n+\t\t\treturn tpgEntity->getPadByIndex(0)->links()[0]->setEnabled(true);\n+\t\t},\n+\t\t[](MaliC55CameraData::Inline &in) {\n+\t\t\tconst MediaEntity *csi2Entity = in.csi2_->entity();\n+\t\t\treturn csi2Entity->getPadByIndex(1)->links()[0]->setEnabled(true);\n+\t\t},\n+\t}, data->input_);\n \tif (ret)\n \t\treturn ret;\n \n \tMaliC55CameraConfiguration *maliConfig =\n \t\tstatic_cast<MaliC55CameraConfiguration *>(config);\n \tV4L2SubdeviceFormat subdevFormat = maliConfig->sensorFormat_;\n-\tret = data->sd_->getFormat(0, &subdevFormat);\n+\n+\t/* Apply format to the origin of the pipeline and propagate it. */\n+\tret = std::visit(utils::overloaded{\n+\t\t[&](MaliC55CameraData::Tpg &tpg) {\n+\t\t\treturn tpg.sd_->setFormat(0, &subdevFormat);\n+\t\t},\n+\t\t[&](MaliC55CameraData::Inline &in) {\n+\t\t\tint r = in.sensor_->setFormat(&subdevFormat,\n+\t\t\t\t\t\t maliConfig->combinedTransform());\n+\t\t\tif (r)\n+\t\t\t\treturn r;\n+\n+\t\t\tr = in.csi2_->setFormat(0, &subdevFormat);\n+\t\t\tif (r)\n+\t\t\t\treturn r;\n+\n+\t\t\treturn in.csi2_->getFormat(1, &subdevFormat);\n+\t\t},\n+\t}, data->input_);\n \tif (ret)\n \t\treturn ret;\n \n-\tif (data->sensor_) {\n-\t\tret = data->sensor_->setFormat(&subdevFormat,\n-\t\t\t\t\t maliConfig->combinedTransform());\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\t}\n-\n-\tif (data->csi_) {\n-\t\tret = data->csi_->setFormat(0, &subdevFormat);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\n-\t\tret = data->csi_->getFormat(1, &subdevFormat);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\t}\n-\n \tV4L2DeviceFormat statsFormat;\n \tret = stats_->getFormat(&statsFormat);\n \tif (ret)\n@@ -973,8 +1018,6 @@ int PipelineHandlerMaliC55::configure(Camera *camera,\n \t/*\n \t * Propagate the format to the ISP sink pad and configure the input\n \t * crop rectangle (no crop at the moment).\n-\t *\n-\t * \\todo Configure the CSI-2 receiver.\n \t */\n \tret = isp_->setFormat(0, &subdevFormat);\n \tif (ret)\n@@ -1058,18 +1101,18 @@ int PipelineHandlerMaliC55::configure(Camera *camera,\n \t/* We need to inform the IPA of the sensor configuration */\n \tipa::mali_c55::IPAConfigInfo ipaConfig{};\n \n-\tret = data->sensor_->sensorInfo(&ipaConfig.sensorInfo);\n+\tret = data->sensor()->sensorInfo(&ipaConfig.sensorInfo);\n \tif (ret)\n \t\treturn ret;\n \n-\tipaConfig.sensorControls = data->sensor_->controls();\n+\tipaConfig.sensorControls = data->sensor()->controls();\n \n \t/*\n \t * And we also need to tell the IPA the bayerOrder of the data (as\n \t * affected by any flips that we've configured)\n \t */\n \tconst Transform &combinedTransform = maliConfig->combinedTransform();\n-\tBayerFormat::Order bayerOrder = data->sensor_->bayerOrder(combinedTransform);\n+\tBayerFormat::Order bayerOrder = data->sensor()->bayerOrder(combinedTransform);\n \n \tControlInfoMap ipaControls;\n \tret = data->ipa_->configure(ipaConfig, utils::to_underlying(bayerOrder),\n@@ -1283,7 +1326,7 @@ void PipelineHandlerMaliC55::applyScalerCrop(Camera *camera,\n \tif (!scalerCrop)\n \t\treturn;\n \n-\tif (!data->sensor_) {\n+\tif (std::holds_alternative<MaliC55CameraData::Tpg>(data->input_)) {\n \t\tLOG(MaliC55, Error) << \"ScalerCrop not supported for TPG\";\n \t\treturn;\n \t}\n@@ -1291,7 +1334,7 @@ void PipelineHandlerMaliC55::applyScalerCrop(Camera *camera,\n \tRectangle nativeCrop = *scalerCrop;\n \n \tIPACameraSensorInfo sensorInfo;\n-\tint ret = data->sensor_->sensorInfo(&sensorInfo);\n+\tint ret = data->sensor()->sensorInfo(&sensorInfo);\n \tif (ret) {\n \t\tLOG(MaliC55, Error) << \"Failed to retrieve sensor info\";\n \t\treturn;\n@@ -1573,9 +1616,9 @@ bool PipelineHandlerMaliC55::registerTPGCamera(MediaLink *link)\n \t}\n \n \tstd::unique_ptr<MaliC55CameraData> data =\n-\t\tstd::make_unique<MaliC55CameraData>(this, link->source()->entity());\n+\t\tstd::make_unique<MaliC55CameraData>(this);\n \n-\tif (data->init())\n+\tif (!data->initTpg(link->source()->entity()))\n \t\treturn false;\n \n \treturn registerMaliCamera(std::move(data), name);\n@@ -1600,21 +1643,24 @@ bool PipelineHandlerMaliC55::registerSensorCamera(MediaLink *ispLink)\n \t\t\tcontinue;\n \n \t\tstd::unique_ptr<MaliC55CameraData> data =\n-\t\t\tstd::make_unique<MaliC55CameraData>(this, sensor);\n-\t\tif (data->init())\n+\t\t\tstd::make_unique<MaliC55CameraData>(this);\n+\n+\t\tauto *in = data->initInline(sensor);\n+\t\tif (!in)\n \t\t\treturn false;\n \n-\t\tdata->properties_ = data->sensor_->properties();\n+\t\tdata->properties_ = in->sensor_->properties();\n \n-\t\tconst CameraSensorProperties::SensorDelays &delays = data->sensor_->sensorDelays();\n+\t\tconst CameraSensorProperties::SensorDelays &delays =\n+\t\t\tin->sensor_->sensorDelays();\n \t\tstd::unordered_map<uint32_t, DelayedControls::ControlParams> params = {\n \t\t\t{ V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } },\n \t\t\t{ V4L2_CID_EXPOSURE, { delays.exposureDelay, false } },\n \t\t};\n \n-\t\tdata->delayedCtrls_ =\n-\t\t\tstd::make_unique<DelayedControls>(data->sensor_->device(),\n-\t\t\t\t\t\t\t params);\n+\t\tV4L2Subdevice *sensorSubdev = in->sensor_->device();\n+\t\tdata->delayedCtrls_ = std::make_unique<DelayedControls>(sensorSubdev,\n+\t\t\t\t\t\t\t\t\tparams);\n \t\tisp_->frameStart.connect(data->delayedCtrls_.get(),\n \t\t\t\t\t &DelayedControls::applyControls);\n \n", "prefixes": [ "v7", "3/8" ] }