Patch Detail
Show a patch.
GET /api/patches/23924/?format=api
{ "id": 23924, "url": "https://patchwork.libcamera.org/api/patches/23924/?format=api", "web_url": "https://patchwork.libcamera.org/patch/23924/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/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": "<20250724065256.75175-8-dan.scally@ideasonboard.com>", "date": "2025-07-24T06:52:53", "name": "[07/10] libcamera: mali-c55: Add RZG2LCRU class", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "eb1016c98e5920c4d2e656776b6f9f3c70c89a7d", "submitter": { "id": 156, "url": "https://patchwork.libcamera.org/api/people/156/?format=api", "name": "Dan Scally", "email": "dan.scally@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/23924/mbox/", "series": [ { "id": 5319, "url": "https://patchwork.libcamera.org/api/series/5319/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5319", "date": "2025-07-24T06:52:46", "name": "Support memory input mode in mali-c55", "version": 1, "mbox": "https://patchwork.libcamera.org/series/5319/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/23924/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/23924/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 69A79C332A\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 24 Jul 2025 06:53:31 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 29AB36909D;\n\tThu, 24 Jul 2025 08:53:26 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 1BE1F69089\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 24 Jul 2025 08:53:16 +0200 (CEST)", "from mail.ideasonboard.com\n\t(cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 38EF87F0;\n\tThu, 24 Jul 2025 08:52:37 +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=\"NHFC3GuR\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1753339957;\n\tbh=TUmc1/BaIxN30HqfOBSAZM2aYtDWn3rqfaw+hbKqZl8=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=NHFC3GuRz81lyLHjeX+VmsMVmfwBkFrHxJKNAYorho1ziU1017Ra0QYsCXPMyFoIx\n\tr9vumg5ECZY7AAT+m+WvD6OL6lXHUxru/ENUmJZ08hAFUIBrp4EO2pZ6HWDHoFBNfE\n\tCwE9PERZTcVVZy4lPrfwys7QvGoOaWf5L5d9Aj9s=", "From": "Daniel Scally <dan.scally@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Daniel Scally <dan.scally@ideasonboard.com>", "Subject": "[PATCH 07/10] libcamera: mali-c55: Add RZG2LCRU class", "Date": "Thu, 24 Jul 2025 07:52:53 +0100", "Message-Id": "<20250724065256.75175-8-dan.scally@ideasonboard.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20250724065256.75175-1-dan.scally@ideasonboard.com>", "References": "<20250724065256.75175-1-dan.scally@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "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": "Add a class allowing us to control the RZ/G2L Camera Receiver Unit\nwhich is found on the KakiP board. This will allow us to capture\nbuffers from the sensor, which in this configuration is not directly\nconnected to the ISP.\n\nAs this is not a guaranteed component of a video pipeline involving\nthe Mali-C55 ISP we would ideally use modular pipelines to fill this\nrole, but for now this will let us enable capture on the KakiP.\n\nSigned-off-by: Daniel Scally <dan.scally@ideasonboard.com>\n---\n .clang-format | 1 -\n src/libcamera/pipeline/mali-c55/meson.build | 3 +-\n src/libcamera/pipeline/mali-c55/rzg2l-cru.cpp | 236 ++++++++++++++++++\n src/libcamera/pipeline/mali-c55/rzg2l-cru.h | 66 +++++\n 4 files changed, 304 insertions(+), 2 deletions(-)\n create mode 100644 src/libcamera/pipeline/mali-c55/rzg2l-cru.cpp\n create mode 100644 src/libcamera/pipeline/mali-c55/rzg2l-cru.h", "diff": "diff --git a/.clang-format b/.clang-format\nindex 7fc30f61..c6b3dd24 100644\n--- a/.clang-format\n+++ b/.clang-format\n@@ -75,7 +75,6 @@ IncludeCategories:\n Priority: 9\n # Qt includes (match before C++ standard library)\n - Regex: '<Q([A-Za-z0-9\\-_])+>'\n- CaseSensitive: true\n Priority: 9\n # Headers in <> with an extension. (+system libraries)\n - Regex: '<([A-Za-z0-9\\-_])+\\.h>'\ndiff --git a/src/libcamera/pipeline/mali-c55/meson.build b/src/libcamera/pipeline/mali-c55/meson.build\nindex eba8e5a3..4e768242 100644\n--- a/src/libcamera/pipeline/mali-c55/meson.build\n+++ b/src/libcamera/pipeline/mali-c55/meson.build\n@@ -1,5 +1,6 @@\n # SPDX-License-Identifier: CC0-1.0\n \n libcamera_internal_sources += files([\n- 'mali-c55.cpp'\n+ 'mali-c55.cpp',\n+ 'rzg2l-cru.cpp',\n ])\ndiff --git a/src/libcamera/pipeline/mali-c55/rzg2l-cru.cpp b/src/libcamera/pipeline/mali-c55/rzg2l-cru.cpp\nnew file mode 100644\nindex 00000000..6b4e7b91\n--- /dev/null\n+++ b/src/libcamera/pipeline/mali-c55/rzg2l-cru.cpp\n@@ -0,0 +1,236 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2025, Ideas on Board Oy\n+ *\n+ * Pipine handler element for the Renesas RZ/G2L Camera Receiver Unit\n+ */\n+\n+#include \"rzg2l-cru.h\"\n+\n+#include <map>\n+\n+#include <libcamera/base/log.h>\n+#include <libcamera/base/regex.h>\n+\n+#include <libcamera/formats.h>\n+#include <libcamera/pixel_format.h>\n+\n+#include \"libcamera/internal/bayer_format.h\"\n+#include \"libcamera/internal/camera_sensor.h\"\n+#include \"libcamera/internal/framebuffer.h\"\n+#include \"libcamera/internal/media_device.h\"\n+#include \"libcamera/internal/request.h\"\n+\n+namespace libcamera {\n+\n+static const std::map<uint8_t, PixelFormat> bitDepthToFmt {\n+\t{ 10, formats::RAW10_CRU },\n+\t{ 12, formats::RAW12_CRU },\n+\t{ 14, formats::RAW14_CRU },\n+};\n+\n+LOG_DEFINE_CATEGORY(RZG2LCRU)\n+\n+std::vector<Size> RZG2LCRU::sizes(unsigned int mbusCode) const\n+{\n+\tstd::vector<Size> sensorSizes = sensor_->sizes(mbusCode);\n+\tstd::vector<Size> cruSizes = {};\n+\n+\tfor (auto size : sensorSizes) {\n+\t\tif (size > csi2Resolution_)\n+\t\t\tcontinue;\n+\n+\t\tcruSizes.push_back(size);\n+\t}\n+\n+\treturn cruSizes;\n+}\n+\n+const Size RZG2LCRU::resolution() const\n+{\n+\treturn sensor_->resolution().boundedTo(csi2Resolution_);\n+}\n+\n+void RZG2LCRU::setSensorAndCSI2Pointers(std::shared_ptr<CameraSensor> sensor,\n+\t\t\t\t\tstd::shared_ptr<V4L2Subdevice> csi2)\n+{\n+\tstd::vector<Size> csi2Sizes;\n+\n+\tsensor_ = sensor;\n+\tcsi2_ = csi2;\n+\n+\tV4L2Subdevice::Formats formats = csi2_->formats(0);\n+\tif (formats.empty())\n+\t\treturn;\n+\n+\tfor (const auto &format : formats) {\n+\t\tconst std::vector<SizeRange> &ranges = format.second;\n+\t\tstd::transform(ranges.begin(), ranges.end(), std::back_inserter(csi2Sizes),\n+\t\t\t [](const SizeRange &range) { return range.max; });\n+\t}\n+\n+\tcsi2Resolution_ = csi2Sizes.back();\n+}\n+\n+FrameBuffer *RZG2LCRU::queueBuffer(Request *request)\n+{\n+\tFrameBuffer *buffer;\n+\n+\tif (availableBuffers_.empty()) {\n+\t\tLOG(RZG2LCRU, Debug) << \"CRU buffer underrun\";\n+\t\treturn nullptr;\n+\t}\n+\n+\tbuffer = availableBuffers_.front();\n+\n+\tint ret = output_->queueBuffer(buffer);\n+\tif (ret) {\n+\t\tLOG(RZG2LCRU, Error) << \"Failed to queue buffer to CRU\";\n+\t\treturn nullptr;\n+\t}\n+\n+\tavailableBuffers_.pop();\n+\tbuffer->_d()->setRequest(request);\n+\n+\treturn buffer;\n+}\n+\n+void RZG2LCRU::cruReturnBuffer(FrameBuffer *buffer)\n+{\n+\tfor (const std::unique_ptr<FrameBuffer> &buf : buffers_) {\n+\t\tif (buf.get() == buffer) {\n+\t\t\tavailableBuffers_.push(buffer);\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+}\n+\n+int RZG2LCRU::start()\n+{\n+\tint ret = output_->exportBuffers(kBufferCount, &buffers_);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+\tret = output_->importBuffers(kBufferCount);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tfor (std::unique_ptr<FrameBuffer> &buffer : buffers_)\n+\t\tavailableBuffers_.push(buffer.get());\n+\n+\tret = output_->streamOn();\n+\tif (ret) {\n+\t\tfreeBuffers();\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+int RZG2LCRU::stop()\n+{\n+\tint ret;\n+\n+\tcsi2_->setFrameStartEnabled(false);\n+\n+\tret = output_->streamOff();\n+\n+\tfreeBuffers();\n+\n+\treturn ret;\n+}\n+\n+void RZG2LCRU::freeBuffers()\n+{\n+\tavailableBuffers_ = {};\n+\tbuffers_.clear();\n+\n+\tif (output_->releaseBuffers())\n+\t\tLOG(RZG2LCRU, Error) << \"Failed to release CRU buffers\";\n+}\n+\n+int RZG2LCRU::configure(V4L2SubdeviceFormat *subdevFormat, V4L2DeviceFormat *inputFormat)\n+{\n+\tint ret;\n+\n+\t/*\n+\t * The sensor and CSI-2 rx have already had their format set by the\n+\t * CameraData class...all we need to do is propagate it to the remaining\n+\t * elements of the CRU graph - the CRU subdevice and output video device\n+\t */\n+\n+\tret = cru_->setFormat(0, subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = cru_->getFormat(1, subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/*\n+\t * The capture device needs to be set with a format that can be produced\n+\t * from the mbus code of the subdevFormat. The CRU and IVC use bayer\n+\t * order agnostic pixel formats, so all we need to do is find the right\n+\t * bitdepth and select the appropriate format.\n+\t */\n+\tBayerFormat bayerFormat = BayerFormat::fromMbusCode(subdevFormat->code);\n+\tif (!bayerFormat.isValid())\n+\t\treturn -EINVAL;\n+\n+\tPixelFormat pixelFormat = bitDepthToFmt.at(bayerFormat.bitDepth);\n+\n+\tV4L2DeviceFormat captureFormat;\n+\tcaptureFormat.fourcc = output_->toV4L2PixelFormat(pixelFormat);\n+\tcaptureFormat.size = subdevFormat->size;\n+\n+\tret = output_->setFormat(&captureFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/*\n+\t * We return the format that we set against the output device, as the\n+\t * same format will also need to be set against the Input Video Control\n+\t * Block device.\n+\t */\n+\t*inputFormat = captureFormat;\n+\n+\treturn 0;\n+}\n+\n+int RZG2LCRU::init(const MediaDevice *media, MediaEntity **sensorEntity)\n+{\n+\tint ret;\n+\n+\tMediaEntity *csi2Entity = media->getEntityByName(std::regex(\"csi-[0-9a-f]{8}.csi2\"));\n+\tif (!csi2Entity)\n+\t\treturn -ENODEV;\n+\n+\tconst std::vector<MediaPad *> &pads = csi2Entity->pads();\n+\tif (pads.empty())\n+\t\treturn -ENODEV;\n+\n+\t/* The receiver has a single sink pad at index 0 */\n+\tMediaPad *sink = pads[0];\n+\tconst std::vector<MediaLink *> &links = sink->links();\n+\tif (links.empty())\n+\t\treturn -ENODEV;\n+\n+\tMediaLink *link = links[0];\n+\t*sensorEntity = link->source()->entity();\n+\n+\t/*\n+\t * We don't handle the sensor and csi-2 rx subdevice here, as the\n+\t * CameraData class does that already.\n+\t *\n+\t * \\todo lose this horrible hack by making modular pipelines.\n+\t */\n+\tcru_ = V4L2Subdevice::fromEntityName(media, std::regex(\"cru-ip-[0-9a-f]{8}.cru[0-9]\"));\n+\tret = cru_->open();\n+\tif (ret)\n+\t\treturn ret;\n+\n+\toutput_ = V4L2VideoDevice::fromEntityName(media, \"CRU output\");\n+\treturn output_->open();\n+}\n+\n+} /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/mali-c55/rzg2l-cru.h b/src/libcamera/pipeline/mali-c55/rzg2l-cru.h\nnew file mode 100644\nindex 00000000..5beb3a6e\n--- /dev/null\n+++ b/src/libcamera/pipeline/mali-c55/rzg2l-cru.h\n@@ -0,0 +1,66 @@\n+/* SPDX-License-Identifier: LGPL-2.1-or-later */\n+/*\n+ * Copyright (C) 2025, Ideas on Board Oy\n+ *\n+ * Pipine handler element for the Renesas RZ/G2L Camera Receiver Unit\n+ */\n+\n+#pragma once\n+\n+#include <memory>\n+#include <vector>\n+\n+#include <libcamera/base/signal.h>\n+\n+#include \"libcamera/internal/v4l2_subdevice.h\"\n+#include \"libcamera/internal/v4l2_videodevice.h\"\n+\n+#include <queue>\n+\n+namespace libcamera {\n+\n+class CameraSensor;\n+class FrameBuffer;\n+class MediaDevice;\n+class PixelFormat;\n+class Request;\n+class Size;\n+class SizeRange;\n+struct StreamConfiguration;\n+enum class Transform;\n+\n+class RZG2LCRU\n+{\n+public:\n+\tstatic constexpr unsigned int kBufferCount = 4;\n+\n+\tRZG2LCRU() = default;\n+\n+\tstd::vector<Size> sizes(unsigned int mbusCode) const;\n+\tint init(const MediaDevice *media, MediaEntity **sensorEntity);\n+\tconst Size resolution() const;\n+\tvoid setSensorAndCSI2Pointers(std::shared_ptr<CameraSensor> sensor,\n+\t\t\t\t std::shared_ptr<V4L2Subdevice> csi2);\n+\tint configure(V4L2SubdeviceFormat *subdevFormat, V4L2DeviceFormat *inputFormat);\n+\tFrameBuffer *queueBuffer(Request *request);\n+\tvoid cruReturnBuffer(FrameBuffer *buffer);\n+\tV4L2VideoDevice *output() { return output_.get(); }\n+\tint start();\n+\tint stop();\n+private:\n+\tvoid freeBuffers();\n+\n+\tvoid cruBufferReady(FrameBuffer *buffer);\n+\n+\tstd::shared_ptr<CameraSensor> sensor_;\n+\tstd::shared_ptr<V4L2Subdevice> csi2_;\n+\tstd::unique_ptr<V4L2Subdevice> cru_;\n+\tstd::unique_ptr<V4L2VideoDevice> output_;\n+\n+\tstd::vector<std::unique_ptr<FrameBuffer>> buffers_;\n+\tstd::queue<FrameBuffer *> availableBuffers_;\n+\n+\tSize csi2Resolution_;\n+};\n+\n+} /* namespace libcamera */\n", "prefixes": [ "07/10" ] }