Show a patch.

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

{
    "id": 27440,
    "url": "https://patchwork.libcamera.org/api/patches/27440/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/27440/",
    "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": "<20260722-pi4-upstream-v2-5-eb44d3c6fd92@ideasonboard.com>",
    "date": "2026-07-22T11:23:21",
    "name": "[v2,5/8] pipeline: rpi: 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/people/223/?format=api",
        "name": "Jai Luthra",
        "email": "jai.luthra@ideasonboard.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/27440/mbox/",
    "series": [
        {
            "id": 6072,
            "url": "https://patchwork.libcamera.org/api/series/6072/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=6072",
            "date": "2026-07-22T11:23:16",
            "name": "Raspberry Pi: Update VC4 pipeline for mainline",
            "version": 2,
            "mbox": "https://patchwork.libcamera.org/series/6072/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/27440/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/27440/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 25876BDE17\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 22 Jul 2026 11:25:11 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BE51067E9E;\n\tWed, 22 Jul 2026 13:25:10 +0200 (CEST)",
            "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 3C37967E8A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 Jul 2026 13:25:09 +0200 (CEST)",
            "from mail.ideasonboard.com (unknown\n\t[IPv6:2401:4900:1c68:25d4:fa24:78d1:31:7a56])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id D2BD9227;\n\tWed, 22 Jul 2026 13:24:08 +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=\"p1FrjwJS\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1784719449;\n\tbh=d+YQTS6n9HgC8Zb49pUpjQKeBNKxnzl/vTVWTVtNZE0=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:From;\n\tb=p1FrjwJSYN9r/SBf9Cmp1V/DXbIfsljqNWSulq7jZ4vANuMRmaAA7+64kUlrm3dqS\n\tKoeKFKc0WjifH8jQAiv5apx554/VtxN1a5Skat+qwCSJIvY2fn4ef3TLBkUbNDjrWp\n\t8OI2zMk625DpIB3LHFY2Ad57EvwJWGOjK1ZS8d9I=",
        "From": "Jai Luthra <jai.luthra@ideasonboard.com>",
        "Date": "Wed, 22 Jul 2026 16:53:21 +0530",
        "Subject": "[PATCH v2 5/8] pipeline: rpi: vc4: Configure format on Unicam subdev",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260722-pi4-upstream-v2-5-eb44d3c6fd92@ideasonboard.com>",
        "References": "<20260722-pi4-upstream-v2-0-eb44d3c6fd92@ideasonboard.com>",
        "In-Reply-To": "<20260722-pi4-upstream-v2-0-eb44d3c6fd92@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.3",
        "X-Developer-Signature": "v=1; a=openpgp-sha256; l=7425;\n\ti=jai.luthra@ideasonboard.com; h=from:subject:message-id;\n\tbh=ietdfXWCu9WIQELry+xNGfG3JoQt36DW+JiF3miCcQo=;\n\tb=owEBbQKS/ZANAwAKAUPekfkkmnFFAcsmYgBqYKhr8M//hkxuVAMKsYnRRAgVtpPQtwTAxpfHd\n\trcFYOb/jlmJAjMEAAEKAB0WIQRN4NgY5dV16NRar8VD3pH5JJpxRQUCamCoawAKCRBD3pH5JJpx\n\tRdIHEAClVMy/2cOVSlYS5vRfQklzzxZLYMkngKidZdXLgfhUG6CRg7asoMzovgWD1zHdZRtURQJ\n\tJfUKxDH8IvRyZlY8aau6peVhdjiJ764k3dqRN8WnX94PAQAPAhezRNN8xOv4jz5o4QAThAGj0SJ\n\t09tJKKigGMDPw1H6+458n52+Z0COU3sE4oDSDu7mj+E8qtyyR5orYLqfP70wJMMNuiFgK7sA+6K\n\tHYKq1Tx7IXmG4sA8rj01g0aCkCIL+ZSuRnVeHbQN4jn+vChzX5QUyMMDkV2dWx88pjl7Nne24FS\n\tmK/YW4H6ySAGxqQTwIfL9PiLqOX2HX92qkL3RgqbDjHNJDSm/3khkzsjBr9YC/PC7NNtk+89Hx4\n\t2KSlWiBUUujOr7LBOHxGP40wqFGeDe6Ac/y4qMmDGJm63pb6yNZsv7UF92wpuG6/ORBug8Vd/Q+\n\tNoB0yqStQozdIRsGoIvsDoETg/CSmqe5kGFRj0jYhotEMwKnoi2ZizuZ2PPvFdcBivLqGPm6sFH\n\tyKBkOtjGMmc8qinzjhhzQkv297T+ItfVSJlv/aXVKrA6CAh0RwK4gTkulpMyol7jS7cOqgjAWQi\n\tpXZ2nfy54r/UR4Gm1Yzh2H/hOhUwT5EAnxGZ+XbiXCfUFZ8uSbqhsOdYqmTDGWXldMRIInNw1AG\n\tIpEUats8AIU3Vpw==",
        "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 c18358876..f06c439d5 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@@ -84,6 +89,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@@ -204,7 +211,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@@ -316,16 +323,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@@ -364,6 +374,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@@ -372,7 +386,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@@ -543,9 +557,54 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<ValueNode> &r\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@@ -569,14 +628,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": [
        "v2",
        "5/8"
    ]
}