Show a patch.

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

{
    "id": 26117,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/26117/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/26117/",
    "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": "<20260210-pi4-upstream-v1-1-279841c15fba@ideasonboard.com>",
    "date": "2026-02-10T08:25:46",
    "name": "[1/3] pipeline: raspberrypi: vc4: Configure format on Unicam subdev",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "b6f3c138e104f59b6d3cb0fcefebfe3173012aee",
    "submitter": {
        "id": 223,
        "url": "https://patchwork.libcamera.org/api/1.1/people/223/?format=api",
        "name": "Jai Luthra",
        "email": "jai.luthra@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/26117/mbox/",
    "series": [
        {
            "id": 5780,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5780/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5780",
            "date": "2026-02-10T08:25:45",
            "name": "Raspberry Pi: Update VC4 pipeline for upstream",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/5780/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/26117/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/26117/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 C81D2BD78E\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 10 Feb 2026 08:26:21 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7ED2F6218A;\n\tTue, 10 Feb 2026 09:26:21 +0100 (CET)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D9011620FA\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 10 Feb 2026 09:26:19 +0100 (CET)",
            "from mail.ideasonboard.com (unknown\n\t[IPv6:2401:4900:1c30:2edd:807a:f3c0:8d1b:28a])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 2D6F513BE;\n\tTue, 10 Feb 2026 09:25:32 +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=\"Q/vmT5GI\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1770711933;\n\tbh=OrK6JcYDdjORHifWcAmGdAks9aF31390jgRrY9Tobm8=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=Q/vmT5GIo1n03a3+aPr2HLiiTHCZDPx99PcM3IeL+/ctDh3MQU9M/2CFYBk6KR0ku\n\tdkwqkiEanJAHDBYDwfGBBy3Ya9Q+OZHfP1PS5yp/AF8awHhimKVXJs0DBTYGyAJd2u\n\tfvxwFKLlkpj/B45oNwbxaN1TLAAZPe+PG2qWKN4Y=",
        "From": "Jai Luthra <jai.luthra@ideasonboard.com>",
        "Date": "Tue, 10 Feb 2026 13:55:46 +0530",
        "Subject": "[PATCH 1/3] pipeline: raspberrypi: vc4: Configure format on Unicam\n\tsubdev",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260210-pi4-upstream-v1-1-279841c15fba@ideasonboard.com>",
        "References": "<20260210-pi4-upstream-v1-0-279841c15fba@ideasonboard.com>",
        "In-Reply-To": "<20260210-pi4-upstream-v1-0-279841c15fba@ideasonboard.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Naushir Patuck <naush@raspberrypi.com>, \n\tDavid Plowman <david.plowman@raspberrypi.com>, \n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>, \n\tKieran Bingham <kieran.bingham@ideasonboard.com>, \n\tJacopo Mondi <jacopo.mondi@ideasonboard.com>, \n\tDaniel Scally <dan.scally@ideasonboard.com>, \n\tJai Luthra <jai.luthra@ideasonboard.com>",
        "X-Mailer": "b4 0.14.2",
        "X-Developer-Signature": "v=1; a=openpgp-sha256; l=7487;\n\ti=jai.luthra@ideasonboard.com; h=from:subject:message-id;\n\tbh=Jbb3fTOUZ9G6JH4sr+GgvFPhuftsbpV9f0J4YxTZi0k=;\n\tb=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBpiuudhbFJIuaO9qNwJhEfb+GWhE2ki6cyy2+C+\n\t5ITQSUVBfOJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCaYrrnQAKCRBD3pH5JJpx\n\tRR95EAC8iDy4akoPLcNUjFqlN3bRwy+VHUUZCDLT3xs2qAIO4iuYft6Y6uHsRXz6Q0kWGUQ9sW+\n\tl5EUHMptha/WWiWK+sqI6p5qcNHQENlfNADHRbZTwk5EzHa5chFanh/jkGBQ5NeG1NRTziFCNnh\n\tzeCHcIbwa1A9+fyoMLgt4RZb/sPI8mneW+x5ypjuZU9QHaZa8ry8yxBPQSfCd0+YfPmPL8kXMvx\n\tOastyeoX3UavHVFnpzLpsfwx0tpaOhNDrJu/wATgj5mw+w6UeWM/sxT+HW1dzCRDbV/xqlvFTOi\n\tBMn6BDdNEqv4BACZgbtX9+vGZzxscV7dzBJ2ptwat2J3DkOm2Swn5ToQ8kxxAmkvASAe3HLEC3T\n\taixi4azV3a1oSUgxiHfQ0Mnj4NJc+qnpMuK2wFBQJR5BKfOmEFqRLKSRA/OIZ5kV0GqaYXNY2lf\n\tiQnLk4VGW5upOwXh7Z51p8YjssURFghCVUHjsZKjPO3d+aR8ZvxS2VyuFV2qa7Qxi8nST2wkdJe\n\tej9xwrfcNeaRBjSk3Hv/KvFq4qG3CzgXzyOeLCHbwPI/1+DyTzRttNwPVpvny0m4SpXWglG6HH4\n\twkfFrTvvUvZxO7RyzWgmE/cSL35sEfNc0S2cmnDQd0i7IpQe6gD90jI//TlmH9KRsSEJIL604L2\n\tZJ8tf8VhzBUONkQ==",
        "X-Developer-Key": "i=jai.luthra@ideasonboard.com; a=openpgp;\n\tfpr=4DE0D818E5D575E8D45AAFC543DE91F9249A7145",
        "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: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nThe mainline Unicam driver creates a V4L2 subdevice, which needs to be\nconfigured. Create and open a corresponding V4L2Subdevice instance and\nconfigure the format on its sink pad in the platformConfigure()\nfunction.\n\nPresence of the Unicam subdev is required, to avoid extra complexity.\nThis drops support for the driver from the Raspberry Pi downstream\nkernel. Users are expected to update their kernel to use the mainline\nUnicam driver.\n\nSigned-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\nSigned-off-by: Jai Luthra <jai.luthra@ideasonboard.com>\n---\n src/libcamera/pipeline/rpi/vc4/vc4.cpp | 100 ++++++++++++++++++++++++++++++---\n 1 file changed, 91 insertions(+), 9 deletions(-)",
    "diff": "diff --git a/src/libcamera/pipeline/rpi/vc4/vc4.cpp b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\nindex 8a80439e9082241782bdf1a9b46445caf64f2acd..cd1ec4f486990bf620f44bc6cd3ef6ae90c91327 100644\n--- a/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n+++ b/src/libcamera/pipeline/rpi/vc4/vc4.cpp\n@@ -15,6 +15,7 @@\n \n #include \"libcamera/internal/device_enumerator.h\"\n #include \"libcamera/internal/dma_buf_allocator.h\"\n+#include \"libcamera/internal/v4l2_subdevice.h\"\n \n #include \"../common/pipeline_base.h\"\n #include \"../common/rpi_stream.h\"\n@@ -33,6 +34,10 @@ namespace {\n enum class Unicam : unsigned int { Image, Embedded };\n enum class Isp : unsigned int { Input, Output0, Output1, Stats };\n \n+static constexpr unsigned int kUnicamSinkPad = 0;\n+static constexpr unsigned int kUnicamSourceImagePad = 1;\n+static constexpr unsigned int kUnicamSourceMetadataPad = 2;\n+\n } /* namespace */\n \n class Vc4CameraData final : public RPi::CameraData\n@@ -83,6 +88,8 @@ public:\n \tvoid setIspControls(const ControlList &controls);\n \tvoid setCameraTimeout(uint32_t maxFrameLengthMs);\n \n+\tstd::unique_ptr<V4L2Subdevice> unicamSubdev_;\n+\n \t/* Array of Unicam and ISP device streams and associated buffers/streams. */\n \tRPi::Device<Unicam, 2> unicam_;\n \tRPi::Device<Isp, 4> isp_;\n@@ -203,7 +210,7 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)\n \n \t\t\tstd::unique_ptr<RPi::CameraData> cameraData = std::make_unique<Vc4CameraData>(this);\n \t\t\tint ret = RPi::PipelineHandlerBase::registerCamera(cameraData,\n-\t\t\t\t\t\t\t\t\t   unicamDevice, \"unicam-image\",\n+\t\t\t\t\t\t\t\t\t   unicamDevice, \"unicam\",\n \t\t\t\t\t\t\t\t\t   ispDevice, entity);\n \t\t\tif (ret)\n \t\t\t\tLOG(RPI, Error) << \"Failed to register camera \"\n@@ -315,16 +322,19 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer\n \tif (!data->dmaHeap_.isValid())\n \t\treturn -ENOMEM;\n \n+\tMediaEntity *unicamSubdev = unicam->getEntityByName(\"unicam\");\n \tMediaEntity *unicamImage = unicam->getEntityByName(\"unicam-image\");\n \tMediaEntity *ispOutput0 = isp->getEntityByName(\"bcm2835-isp0-output0\");\n \tMediaEntity *ispCapture1 = isp->getEntityByName(\"bcm2835-isp0-capture1\");\n \tMediaEntity *ispCapture2 = isp->getEntityByName(\"bcm2835-isp0-capture2\");\n \tMediaEntity *ispCapture3 = isp->getEntityByName(\"bcm2835-isp0-capture3\");\n \n-\tif (!unicamImage || !ispOutput0 || !ispCapture1 || !ispCapture2 || !ispCapture3)\n+\tif (!unicamSubdev || !unicamImage || !ispOutput0 || !ispCapture1 ||\n+\t    !ispCapture2 || !ispCapture3)\n \t\treturn -ENOENT;\n \n-\t/* Locate and open the unicam video streams. */\n+\t/* Create the unicam subdev and video streams. */\n+\tdata->unicamSubdev_ = std::make_unique<V4L2Subdevice>(unicamSubdev);\n \tdata->unicam_[Unicam::Image] = RPi::Stream(\"Unicam Image\", unicamImage);\n \n \t/* An embedded data node will not be present if the sensor does not support it. */\n@@ -363,6 +373,10 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer\n \t * The below grouping is just for convenience so that we can easily\n \t * iterate over all streams in one go.\n \t */\n+\tint ret = data->unicamSubdev_->open();\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n \tdata->streams_.push_back(&data->unicam_[Unicam::Image]);\n \tif (data->sensorMetadata_)\n \t\tdata->streams_.push_back(&data->unicam_[Unicam::Embedded]);\n@@ -371,7 +385,7 @@ int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &camer\n \t\tdata->streams_.push_back(&stream);\n \n \tfor (auto stream : data->streams_) {\n-\t\tint ret = stream->dev()->open();\n+\t\tret = stream->dev()->open();\n \t\tif (ret)\n \t\t\treturn ret;\n \t}\n@@ -542,9 +556,54 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &\n \n int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfig)\n {\n+\t/*\n+\t * 1. Configure the Unicam subdev.\n+\t *\n+\t * Start by setting up routes, and then set the formats on the sink pad\n+\t * streams. They will be automatically propagated to the source pads by\n+\t * the kernel.\n+\t */\n+\n+\tconst V4L2Subdevice::Stream imageStream{\n+\t\tkUnicamSinkPad,\n+\t\tsensor_->imageStream().stream\n+\t};\n+\tconst V4L2Subdevice::Stream embeddedDataStream{\n+\t\tkUnicamSinkPad,\n+\t\tsensor_->embeddedDataStream().value_or(V4L2Subdevice::Stream{}).stream\n+\t};\n+\n+\tV4L2Subdevice::Routing routing;\n+\n+\trouting.emplace_back(imageStream, V4L2Subdevice::Stream{ kUnicamSourceImagePad, 0 },\n+\t\t\t     V4L2_SUBDEV_ROUTE_FL_ACTIVE);\n+\n+\tif (sensorMetadata_)\n+\t\trouting.emplace_back(embeddedDataStream,\n+\t\t\t\t     V4L2Subdevice::Stream{ kUnicamSourceMetadataPad, 0 },\n+\t\t\t\t     V4L2_SUBDEV_ROUTE_FL_ACTIVE);\n+\n+\tint ret = unicamSubdev_->setRouting(&routing);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tV4L2SubdeviceFormat subdevFormat = rpiConfig->sensorFormat_;\n+\tret = unicamSubdev_->setFormat(imageStream, &subdevFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (sensorMetadata_) {\n+\t\tsubdevFormat = sensor_->embeddedDataFormat();\n+\t\tret = unicamSubdev_->setFormat(embeddedDataStream, &subdevFormat);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\t/*\n+\t * 2. Configure the Unicam video devices.\n+\t */\n \tconst std::vector<StreamParams> &rawStreams = rpiConfig->rawStreams_;\n \tconst std::vector<StreamParams> &outStreams = rpiConfig->outStreams_;\n-\tint ret;\n \n \tV4L2VideoDevice *unicam = unicam_[Unicam::Image].dev();\n \tV4L2DeviceFormat unicamFormat;\n@@ -568,14 +627,37 @@ int Vc4CameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConfi\n \tif (ret)\n \t\treturn ret;\n \n-\tret = isp_[Isp::Input].dev()->setFormat(&unicamFormat);\n-\tif (ret)\n-\t\treturn ret;\n-\n \tLOG(RPI, Info) << \"Sensor: \" << sensor_->id()\n \t\t       << \" - Selected sensor format: \" << rpiConfig->sensorFormat_\n \t\t       << \" - Selected unicam format: \" << unicamFormat;\n \n+\t/*\n+\t * Configure the Unicam embedded data output format only if the sensor\n+\t * supports it.\n+\t */\n+\tif (sensorMetadata_) {\n+\t\tV4L2SubdeviceFormat embeddedFormat = sensor_->embeddedDataFormat();\n+\t\tV4L2DeviceFormat format{};\n+\t\tformat.fourcc = V4L2PixelFormat(V4L2_META_FMT_SENSOR_DATA);\n+\t\tformat.planes[0].size = embeddedFormat.size.width * embeddedFormat.size.height;\n+\n+\t\tLOG(RPI, Debug) << \"Setting embedded data format \" << format;\n+\t\tret = unicam_[Unicam::Embedded].dev()->setFormat(&format);\n+\t\tif (ret) {\n+\t\t\tLOG(RPI, Error) << \"Failed to set format on Unicam embedded: \"\n+\t\t\t\t\t<< format;\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * 3. Configure the ISP.\n+\t */\n+\n+\tret = isp_[Isp::Input].dev()->setFormat(&unicamFormat);\n+\tif (ret)\n+\t\treturn ret;\n+\n \t/* Use a sensible small default size if no output streams are configured. */\n \tSize maxSize = outStreams.empty() ? Size(320, 240) : outStreams[0].cfg->size;\n \tV4L2DeviceFormat format;\n",
    "prefixes": [
        "1/3"
    ]
}