Show a patch.

GET /api/1.1/patches/26295/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 26295,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/26295/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/26295/",
    "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": "<20260313-mali-cru-v5-4-48f93e431294@ideasonboard.com>",
    "date": "2026-03-13T16:14:38",
    "name": "[v5,4/7] libcamera: mali-c55: Register memory input camera",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "e5c9f0a8cc2142b4274bf69b450d9ec1b3518c84",
    "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/26295/mbox/",
    "series": [
        {
            "id": 5830,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5830/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5830",
            "date": "2026-03-13T16:14:34",
            "name": "libcamera: mali-c55: Add support for memory-to-memory",
            "version": 5,
            "mbox": "https://patchwork.libcamera.org/series/5830/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/26295/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/26295/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 8E17DC32F0\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 13 Mar 2026 16:14:52 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 29AF762727;\n\tFri, 13 Mar 2026 17:14:52 +0100 (CET)",
            "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 59E3B6270C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 13 Mar 2026 17:14:50 +0100 (CET)",
            "from [192.168.224.131] (unknown [37.159.122.93])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id B462A1934;\n\tFri, 13 Mar 2026 17:13:40 +0100 (CET)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"DY0md4I7\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1773418421;\n\tbh=APUyktNx0MVd4SoGkw/VTrDTc+XxoVQwTfbNIXCEEy4=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=DY0md4I73mYOqBKzEo77h/dqB6TW7C6j8kgtjl3RFnwdetJljIe7u+yYN81OW6D6A\n\t7Vjg9mhUHMkCn4Zt+xE/Zdc0Cg1bUBXpmJl63ZeEDB+wlwK7qqQ+bqYCU2VO76P3Vn\n\t9vbTMwevK5lDhz3puIlEvxToNPkAPqLzgkL+U1QI=",
        "From": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>",
        "Date": "Fri, 13 Mar 2026 17:14:38 +0100",
        "Subject": "[PATCH v5 4/7] libcamera: mali-c55: Register memory input camera",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260313-mali-cru-v5-4-48f93e431294@ideasonboard.com>",
        "References": "<20260313-mali-cru-v5-0-48f93e431294@ideasonboard.com>",
        "In-Reply-To": "<20260313-mali-cru-v5-0-48f93e431294@ideasonboard.com>",
        "To": "Daniel Scally <dan.scally@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org",
        "Cc": "Jacopo Mondi <jacopo.mondi@ideasonboard.com>",
        "X-Mailer": "b4 0.14.3",
        "X-Developer-Signature": "v=1; a=openpgp-sha256; l=9819;\n\ti=jacopo.mondi@ideasonboard.com; h=from:subject:message-id;\n\tbh=KOQwFbPgOiDmtCmZ7//v9C+mAaBkiNylRVHBHbip3zQ=;\n\tb=owEBbQKS/ZANAwAKAXI0Bo8WoVY8AcsmYgBptDfzCFn5VtPPGHQWM4Qc1RAbIvaiuhf6Ef7bx\n\tEmEgvuQAdOJAjMEAAEKAB0WIQS1xD1IgJogio9YOMByNAaPFqFWPAUCabQ38wAKCRByNAaPFqFW\n\tPNFID/9ewLFuZPpkbErgjcIYRW2xX9zb0xylp1hmWomI6q9i2RR5oR0jobBQiIe7W8OsDBQy+hM\n\tDrP3s7vzRmiC2JtoSiGx0tPvlrLdB+CvouQpFcS0pe6VwIh4BWU389lVHygf4usc5Z3m9BCteVc\n\t0WwliyLDAMkkcOMbJN1lJMqJOocnEIeCxp5em/IEnP/hFjxnQsNvQ4rwkCAZUUPK6+llFrjLvMZ\n\trUjOv53FmtQWmTyVdoj5UZ5OgP1J20FKSst3duwFrkmWbe+Kbq5UUjyMxKF23k2Xrrqxtxp1Mob\n\t1tkrV1hq7WRcWps3Jem2L/cs40nGIZkPYQLrDQTpgFT7oppPDbH0lMf1es62yqdZENGyW3WnwNS\n\t3aXNw9HbMNOXCa8wprPM7nr45spkryiVuxTJw20B0Fknyzz9ddSizGXzQx20NuS11TpR/XIy6Rm\n\tIPWeiTAANMp9nkW4EdQJRBfeniReRXl5+iChHfVALdDO867vPk3BVRjw+wPpVib+k1EMW7P7o3e\n\tQp0Z7xP9E5KyrmzpKanY8L1DIHGIgQVs7Aq70AERrVXL7xGlXphz58sM66JkmFEi7pIjD4kAz1e\n\tgytFfhyQfO1U7CQElkX8VqjyHYzKg5trvGdV42gDLZujHB2QbT6yzb/6Pje4A2p5nFv46lwKU5E\n\ttTmC2uHvfAFFbSw==",
        "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": "From: Daniel Scally <dan.scally@ideasonboard.com>\n\nAdd support to Mali C55 pipeline handler for memory-to-memory camera\nmode.\n\nThe Mali-C55, as integrated in the Renesas RZ/V2H(P) SoC, is fed with\nimages saved to memory by the CRU unit and read on behalf of the ISP\nby the IVC.\n\nUpdate the pipeline handler's match() function to search for the CRU\nmedia entity necessary to register a memory input camera. Create and\ninitialize a CameraData instance for the memory camera use case if a\nvalid CRU is found and initialize the IVC components used to feed the\nISP with images read from memory.\n\nDo not implement camera configuration for the time being to reuce\nthe patch size. It will be provided in the following patches.\n\nSigned-off-by: Daniel Scally <dan.scally@ideasonboard.com>\nSigned-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\n src/libcamera/pipeline/mali-c55/mali-c55.cpp | 151 ++++++++++++++++++++++++---\n 1 file changed, 134 insertions(+), 17 deletions(-)",
    "diff": "diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\nindex 45e23ffd3841..5e93d66b01cd 100644\n--- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n+++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp\n@@ -44,6 +44,8 @@\n #include \"libcamera/internal/v4l2_subdevice.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n+#include \"rzg2l-cru.h\"\n+\n namespace {\n \n bool isFormatRaw(const libcamera::PixelFormat &pixFmt)\n@@ -105,7 +107,12 @@ public:\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+\tstruct Memory {\n+\t\tstd::unique_ptr<RZG2LCRU> cru_;\n+\t};\n+\n+\tusing CameraType = std::variant<Tpg, Inline, Memory>;\n \n \tMaliC55CameraData(PipelineHandler *pipe)\n \t\t: Camera::Private(pipe)\n@@ -116,6 +123,7 @@ public:\n \n \tint initTpg(MediaEntity *entity);\n \tint initInline(MediaEntity *entity);\n+\tint initMemory(MediaDevice *cruMedia);\n \n \tstd::vector<Size> sizes(unsigned int mbusCode) const\n \t{\n@@ -125,6 +133,9 @@ public:\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\t[&](const Memory &mem) -> std::vector<Size> {\n+\t\t\t\treturn mem.cru_->sizes();\n \t\t\t}\n \t\t}, input_);\n \t}\n@@ -137,6 +148,9 @@ public:\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\t[&](const Memory &mem) -> V4L2Subdevice * {\n+\t\t\t\treturn mem.cru_->sensor()->device();\n \t\t\t}\n \t\t}, input_);\n \t}\n@@ -150,6 +164,9 @@ public:\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\t[&](const Memory &mem) -> CameraSensor * {\n+\t\t\t\treturn mem.cru_->sensor();\n \t\t\t}\n \t\t}, input_);\n \t}\n@@ -163,6 +180,9 @@ public:\n \t\t\t},\n \t\t\t[&](const Inline &in) -> V4L2Subdevice * {\n \t\t\t\treturn in.csi2_.get();\n+\t\t\t},\n+\t\t\t[&](const Memory &mem) -> V4L2Subdevice * {\n+\t\t\t\treturn mem.cru_->csi2();\n \t\t\t}\n \t\t}, input_);\n \t}\n@@ -175,10 +195,26 @@ public:\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\t[&](const Memory &mem) -> Size {\n+\t\t\t\treturn mem.cru_->resolution();\n \t\t\t}\n \t\t}, input_);\n \t}\n \n+\tRZG2LCRU *cru() const\n+\t{\n+\t\treturn std::visit(utils::overloaded{\n+\t\t\t[&](auto &) -> RZG2LCRU * {\n+\t\t\t\tASSERT(false);\n+\t\t\t\treturn nullptr;\n+\t\t\t},\n+\t\t\t[&](const Memory &mem) -> RZG2LCRU * {\n+\t\t\t\treturn mem.cru_.get();\n+\t\t\t},\n+\t\t}, input_);\n+\t}\n+\n \tint pixfmtToMbusCode(const PixelFormat &pixFmt) const;\n \tconst PixelFormat &bestRawFormat() const;\n \n@@ -258,6 +294,21 @@ int MaliC55CameraData::initInline(MediaEntity *sensor)\n \treturn 0;\n }\n \n+int MaliC55CameraData::initMemory(MediaDevice *cruMedia)\n+{\n+\tMemory mem;\n+\n+\tmem.cru_ = std::make_unique<RZG2LCRU>();\n+\n+\tint ret = mem.cru_->init(cruMedia);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tinput_.emplace<Memory>(std::move(mem));\n+\n+\treturn 0;\n+}\n+\n std::vector<Size> MaliC55CameraData::Tpg::sizes(unsigned int mbusCode) const\n {\n \tV4L2Subdevice::Formats formats = sd_->formats(0);\n@@ -738,11 +789,15 @@ private:\n \t\t\t\tconst std::string &name);\n \tbool registerTPGCamera(MediaLink *link);\n \tbool registerSensorCamera(MediaLink *link);\n+\tbool registerMemoryInputCamera();\n \n \tstd::shared_ptr<MediaDevice> media_;\n+\tstd::shared_ptr<MediaDevice> cruMedia_;\n \tstd::unique_ptr<V4L2Subdevice> isp_;\n \tstd::unique_ptr<V4L2VideoDevice> stats_;\n \tstd::unique_ptr<V4L2VideoDevice> params_;\n+\tstd::unique_ptr<V4L2Subdevice> ivcSd_;\n+\tstd::unique_ptr<V4L2VideoDevice> ivc_;\n \n \tstd::vector<std::unique_ptr<FrameBuffer>> statsBuffers_;\n \tstd::queue<FrameBuffer *> availableStatsBuffers_;\n@@ -993,6 +1048,9 @@ int PipelineHandlerMaliC55::configure(Camera *camera,\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\t[](MaliC55CameraData::Memory &) {\n+\t\t\treturn 0;\n+\t\t}\n \t}, data->input_);\n \tif (ret)\n \t\treturn ret;\n@@ -1018,6 +1076,9 @@ int PipelineHandlerMaliC55::configure(Camera *camera,\n \n \t\t\treturn data->csi2()->getFormat(1, &subdevFormat);\n \t\t},\n+\t\t[](MaliC55CameraData::Memory &) {\n+\t\t\treturn 0;\n+\t\t}\n \t}, data->input_);\n \tif (ret)\n \t\treturn ret;\n@@ -1691,6 +1752,34 @@ bool PipelineHandlerMaliC55::registerSensorCamera(MediaLink *ispLink)\n \treturn true;\n }\n \n+bool PipelineHandlerMaliC55::registerMemoryInputCamera()\n+{\n+\tstd::unique_ptr<MaliC55CameraData> data =\n+\t\tstd::make_unique<MaliC55CameraData>(this);\n+\n+\tint ret = data->initMemory(cruMedia_.get());\n+\tif (ret)\n+\t\treturn false;\n+\n+\tCameraSensor *sensor = data->sensor();\n+\tdata->properties_ = sensor->properties();\n+\n+\tconst CameraSensorProperties::SensorDelays &delays = sensor->sensorDelays();\n+\tstd::unordered_map<uint32_t, DelayedControls::ControlParams> params = {\n+\t\t{ V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } },\n+\t\t{ V4L2_CID_EXPOSURE, { delays.exposureDelay, false } },\n+\t};\n+\n+\tdata->delayedCtrls_ =\n+\t\tstd::make_unique<DelayedControls>(sensor->device(), params);\n+\tisp_->frameStart.connect(data->delayedCtrls_.get(),\n+\t\t\t\t &DelayedControls::applyControls);\n+\n+\tivc_->bufferReady.connect(data->cru(), &RZG2LCRU::cruReturnBuffer);\n+\n+\treturn registerMaliCamera(std::move(data), sensor->device()->entity()->name());\n+}\n+\n bool PipelineHandlerMaliC55::match(DeviceEnumerator *enumerator)\n {\n \tconst MediaPad *ispSink;\n@@ -1700,14 +1789,14 @@ bool PipelineHandlerMaliC55::match(DeviceEnumerator *enumerator)\n \t * The TPG and the downscale pipe are both optional blocks and may not\n \t * be fitted.\n \t */\n-\tDeviceMatch dm(\"mali-c55\");\n-\tdm.add(\"mali-c55 isp\");\n-\tdm.add(\"mali-c55 resizer fr\");\n-\tdm.add(\"mali-c55 fr\");\n-\tdm.add(\"mali-c55 3a stats\");\n-\tdm.add(\"mali-c55 3a params\");\n-\n-\tmedia_ = acquireMediaDevice(enumerator, dm);\n+\tDeviceMatch c55_dm(\"mali-c55\");\n+\tc55_dm.add(\"mali-c55 isp\");\n+\tc55_dm.add(\"mali-c55 resizer fr\");\n+\tc55_dm.add(\"mali-c55 fr\");\n+\tc55_dm.add(\"mali-c55 3a stats\");\n+\tc55_dm.add(\"mali-c55 3a params\");\n+\n+\tmedia_ = acquireMediaDevice(enumerator, c55_dm);\n \tif (!media_)\n \t\treturn false;\n \n@@ -1767,6 +1856,25 @@ bool PipelineHandlerMaliC55::match(DeviceEnumerator *enumerator)\n \tstats_->bufferReady.connect(this, &PipelineHandlerMaliC55::statsBufferReady);\n \tparams_->bufferReady.connect(this, &PipelineHandlerMaliC55::paramsBufferReady);\n \n+\t/*\n+\t * We also need to search for the rzg2l-cru CSI-2 receiver. If we find\n+\t * that then we need to work in memory input mode instead of the inline\n+\t * mode. The absence of this match is not necessarily a failure at this\n+\t * point...it depends on the media links that we investigate momentarily.\n+\t *\n+\t * This is a bit hacky, because there could be multiple of these media\n+\t * devices and we're just taking the first. We need modular pipelines to\n+\t * properly solve the issue.\n+\t */\n+\tstatic const std::regex cruCsi2Regex(\"csi-[0-9a-f]{8}.csi2\");\n+\tstatic const std::regex cruIpRegex(\"cru-ip-[0-9a-f]{8}.cru[0-9]\");\n+\n+\tDeviceMatch cruDm(\"rzg2l_cru\");\n+\tcruDm.add(cruCsi2Regex);\n+\tcruDm.add(cruIpRegex);\n+\tcruDm.add(\"CRU output\");\n+\tcruMedia_ = acquireMediaDevice(enumerator, cruDm);\n+\n \tispSink = isp_->entity()->getPadByIndex(0);\n \tif (!ispSink || ispSink->links().empty()) {\n \t\tLOG(MaliC55, Error) << \"ISP sink pad error\";\n@@ -1780,13 +1888,6 @@ bool PipelineHandlerMaliC55::match(DeviceEnumerator *enumerator)\n \t * MEDIA_ENT_F_CAM_SENSOR - The test pattern generator\n \t * MEDIA_ENT_F_VID_IF_BRIDGE - A CSI-2 receiver\n \t * MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER - An input device\n-\t *\n-\t * The last one will be unsupported for now. The TPG is relatively easy,\n-\t * we just register a Camera for it. If we have a CSI-2 receiver we need\n-\t * to check its sink pad and register Cameras for anything connected to\n-\t * it (probably...there are some complex situations in which that might\n-\t * not be true but let's pretend they don't exist until we come across\n-\t * them)\n \t */\n \tbool registered;\n \tfor (MediaLink *link : ispSink->links()) {\n@@ -1806,7 +1907,23 @@ bool PipelineHandlerMaliC55::match(DeviceEnumerator *enumerator)\n \n \t\t\tbreak;\n \t\tcase MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER:\n-\t\t\tLOG(MaliC55, Warning) << \"Memory input not yet supported\";\n+\t\t\tif (!cruMedia_)\n+\t\t\t\treturn false;\n+\n+\t\t\tivcSd_ = V4L2Subdevice::fromEntityName(media_.get(),\n+\t\t\t\t\t\t\t       \"rzv2h ivc block\");\n+\t\t\tif (ivcSd_->open() < 0)\n+\t\t\t\treturn false;\n+\n+\t\t\tivc_ = V4L2VideoDevice::fromEntityName(media_.get(),\n+\t\t\t\t\t\t\t       \"rzv2h-ivc\");\n+\t\t\tif (ivc_->open() < 0)\n+\t\t\t\treturn false;\n+\n+\t\t\tregistered = registerMemoryInputCamera();\n+\t\t\tif (!registered)\n+\t\t\t\treturn registered;\n+\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tLOG(MaliC55, Error) << \"Unsupported entity function\";\n",
    "prefixes": [
        "v5",
        "4/7"
    ]
}