{"id":25264,"url":"https://patchwork.libcamera.org/api/patches/25264/?format=json","web_url":"https://patchwork.libcamera.org/patch/25264/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20251127154519.2038844-3-antoine.bouyer@nxp.com>","date":"2025-11-27T15:45:18","name":"[v3,2/2] pipeline: imx8-isi: Integrating MediaPipeline class","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"6ae76f450c30a7c6eff0256ab948403776eab652","submitter":{"id":218,"url":"https://patchwork.libcamera.org/api/people/218/?format=json","name":"Antoine Bouyer","email":"antoine.bouyer@nxp.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/25264/mbox/","series":[{"id":5618,"url":"https://patchwork.libcamera.org/api/series/5618/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5618","date":"2025-11-27T15:45:16","name":"imx8-isi: Use MediaPipeline","version":3,"mbox":"https://patchwork.libcamera.org/series/5618/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/25264/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/25264/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 0E714C3257\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 27 Nov 2025 15:43:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id B81B460AA3;\n\tThu, 27 Nov 2025 16:43:45 +0100 (CET)","from GVXPR05CU001.outbound.protection.outlook.com\n\t(mail-swedencentralazlp170130007.outbound.protection.outlook.com\n\t[IPv6:2a01:111:f403:c202::7])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 03355609DE\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 27 Nov 2025 16:43:44 +0100 (CET)","from GVXPR04MB9831.eurprd04.prod.outlook.com (2603:10a6:150:11c::8)\n\tby PR3PR04MB7372.eurprd04.prod.outlook.com (2603:10a6:102:80::18)\n\twith Microsoft SMTP Server (version=TLS1_2,\n\tcipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9366.13;\n\tThu, 27 Nov 2025 15:43:42 +0000","from GVXPR04MB9831.eurprd04.prod.outlook.com\n\t([fe80::4634:3d9c:c4a:641a]) by\n\tGVXPR04MB9831.eurprd04.prod.outlook.com\n\t([fe80::4634:3d9c:c4a:641a%6]) with mapi id 15.20.9366.009;\n\tThu, 27 Nov 2025 15:43:42 +0000"],"Authentication-Results":["lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=nxp.com header.i=@nxp.com header.b=\"hgKNr6TD\";\n\tdkim-atps=neutral","dkim=none (message not signed)\n\theader.d=none;dmarc=none action=none header.from=nxp.com;"],"ARC-Seal":"i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n\tb=vGqJBLc64Adrsmous7IC9EWz3mZAhyh9cUsXNCCrC0dZ5OvHofNK44DB0lEaMfVoRjSzvwXQySNediuOqH5LNF8B+tY2raKUvuuMGeT3+yEXkdKkpsp6sb4sJXmywhKBvff5LNIuZVSMu8DYRDq7iRKZGUaKWk6NSh8vynL0M7zuRBW03R5xXH6TtY9pg2cut6fyMoMDenmDQzDRbDylYyjTClxXLDPrktWZFRpFHeGH7AdE2WFdG6Y/iFjv0uFSSbN+mRJhqfJtg4jhlm5A0AZtcUIMQ/q3PS/pQIl8GnJLCa+XuTzWtWBZH2/4va3l4aWRP6/D5u+pwPW+yMESGg==","ARC-Message-Signature":"i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n\ts=arcselector10001;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n\tbh=qKhC5/1JewYOODVFTvuvey1lUC6npjBW4Rjf3olYO28=;\n\tb=qKJB5wPzq0KHRKkS++TUUie2Gc2Xvjf54swLySq6Eef7eFQ+mVeyTMzVNH0aTGddp6+ATIyTDunLlNc5m5X2Yn9lyvV6S0DKu6PkWcZKHWuIiymNYYSQcqJMjHxBpSBddQcjZ2ArRAnSgZH4+C/brOV9NqR2JcFcoTggCMq5Yej3XxUMKJ6TOzMfOKFwvpTu0c/lf8IJ9TEORFvqkVBxM/te0rzaYuzhC//2X8x+t4OAp/UFNniglPF/gWjMKaTNtMDkVvX7DdsOWa3EJe+hWhZgTb32078Bce6SSljkp3zajmVsTi7d3Xmi/MHWSg5JqKEkjsU3T/dxIgV0ECPtTQ==","ARC-Authentication-Results":"i=1; mx.microsoft.com 1; spf=pass\n\tsmtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com;\n\tdkim=pass header.d=nxp.com; arc=none","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1;\n\th=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n\tbh=qKhC5/1JewYOODVFTvuvey1lUC6npjBW4Rjf3olYO28=;\n\tb=hgKNr6TDtjWNt5QbpKqqoFvkKV7XyBjfTADYuVnEUVn8Cf8FPPBlxwxfGUjgjxBQX8ay4kg2cixZDehD7mzfObTSKcuUrLePNucCCI+m5ptHyYe5b0T+RmzwMX+gegg6wPy64Aaf89VhVm8k39V/WQyMt5f9G9gGhzZM28KUgxcb4Sh5b3mQVPbW4qqSuKE01ehjayfv3vmhJxLJRBAZAmPkzpezO4ItxGIhkNaxf4Rx6UaSU2R/A3YDM8qkdaCuNCcQOtwetWKv7DxjjmVIzZfs8FX6z0kflIbRd6wiPMQxY0wpD7WAciJ5rdiVEvZqEqj9hXy/mQJbfuhy8ek+7g==","From":"Antoine Bouyer <antoine.bouyer@nxp.com>","To":"libcamera-devel@lists.libcamera.org","Cc":"julien.vuillaumier@nxp.com, jacopo.mondi@ideasonboard.com,\n\tbarnabas.pocze@ideasonboard.com, isaac.scott@ideasonboard.com,\n\tAndrei Gansari <andrei.gansari@nxp.com>,\n\tAntoine Bouyer <antoine.bouyer@nxp.com>","Subject":"[PATCH v3 2/2] pipeline: imx8-isi: Integrating MediaPipeline class","Date":"Thu, 27 Nov 2025 16:45:18 +0100","Message-ID":"<20251127154519.2038844-3-antoine.bouyer@nxp.com>","X-Mailer":"git-send-email 2.51.2","In-Reply-To":"<20251127154519.2038844-1-antoine.bouyer@nxp.com>","References":"<20251127154519.2038844-1-antoine.bouyer@nxp.com>","Content-Transfer-Encoding":"8bit","Content-Type":"text/plain","X-ClientProxiedBy":"SJ0PR05CA0173.namprd05.prod.outlook.com\n\t(2603:10b6:a03:339::28) To GVXPR04MB9831.eurprd04.prod.outlook.com\n\t(2603:10a6:150:11c::8)","MIME-Version":"1.0","X-MS-PublicTrafficType":"Email","X-MS-TrafficTypeDiagnostic":"GVXPR04MB9831:EE_|PR3PR04MB7372:EE_","X-MS-Office365-Filtering-Correlation-Id":"cb6e063b-6390-4b32-447f-08de2dcbbdec","X-MS-Exchange-SenderADCheck":"1","X-MS-Exchange-AntiSpam-Relay":"0","X-Microsoft-Antispam":"BCL:0;\n\tARA:13230040|1800799024|366016|19092799006|376014|52116014|38350700014;","X-Microsoft-Antispam-Message-Info":"kgKj4lPaXGZsaoHg/wPG2BnW8Zg/O+bNmQIfreoOFDS15BvGnL6e7uCETV0G/JXinEakYkOkm45G/5SXTvefUOq6tYtRoYsH/6sFFuCJuOWsTklNL7JDPD3PBLwZ3/J9EUQC7GyvjZbFLiSRd01dU8c4rBDr6p8x2aIkU++qRITMDBSwS9/YnjH7DYkn/uydo14oaspjMfkZ8SOUoWajNs/W4Mf6Lx6di4JGP7ODPlB76szDkeCQsR4u8lueIIHkNy7Vejt7C2bHw/zuNVhLQovEqqcBSwwPQOxgIWMdh/v7XEhM4j4Q52KeRLh6abm6qSlO/bol76hgiEoI2fUCLFIZXeNTn+CbNVAhapu8hHMZjsKEf6QELdj3cnlKKVPlWTMtzJscjlA9l1HKTdVYm13+y63DY6TArOfwhNJyJ7amk6WVQ2gRMVkxprR4n2dVETfQFYoIiZGLxqpcRZzXnM4/49iRlXjYnkrSwfCpYnyL4hrhhBqPVuanGsKHQDtO/SumEISOfPdcwOvFuRkkiZV1ms4MBVjVz8EhaFkLvmEjz0PSz4qwar0wntb1fWEgxiUjlV3iMSVnvkBMPAPHKN449BLEe71anib+5FN2aoBIraw59tjSv6p72KqFj7TmhTUaeU+1alTWDyEVkhP2R6TWVW9qkRFoM9JTMaDsE+5uqqbap1NCvqmudcficfhRiET8NLD0lz+ksu0hzKSBn8sv86THSmBvc3GrIDTZKaFso9ohoDXTa6+LXVKM3bAmyJwqEHh91Lx0AO9/iPrMNWDuMf199/nQ+whlCIm9YNC0qE6wDgCYjvVfXAH6JMDmYqNX9y9RfElMCkCubbBU2ybqCWm1AOx95B+hxiLc2SKUGLxCOiSYglSDlTkzCy7addPRjSoEquiOlc/ESOvDEbPhkZ26cvN0dY7GshajhMbRkkXgSNCrCD8I3B1w7JGdAmETbBqrxfPtKKtuH27lTHq1/NfYPT9aVpJqGSPGzJWN0LiplfexcZrjCzBN+qEiPZCY4mZSQtWutHJsvhtG+OiuYC8UMdnQE9PJjYzhwyrFy4iWUoIUDuqxfN5o9U4XpH7J6o7b1qzpkGH1Dpt2SE9qYrbbkURsqszduunrvMeiDX9ypznmpVUzTdg7/3MUYGIWiyzP+NrKEn5+DdRUm0Y50bZMFKoIdz5fyi6299mw8xl7fRuV7JOjgo+aXZt/71yzpiAAQU5yuBRHP8dmcqQ0RbLG8O5PvLixep6H4p/xpC3NWo7zh0A7pX1lV9IkkuntyWm6a8ZJXa7QLUH0I/Unib5GejSrtusPGee8W3aT/5MK/qlRb9eNTfmkqorAQiw+qEnqmvzAEql7fRPO7hj2De/yXFM20K2P5qAkyNTP9OS3IdEA3fGPszSFL2i6JxJRjJaGqVLp3ydvjztYbB2xUPcpVsjwrel89WL1rmFCGR9e/xjDJU6Xi4ny0FWplHjtdGWgvOBSbJLIIgC5dDyUJKBN6TJ1hI87nqgeBKBSYpOZtz46mqZHzIge6Boo","X-Forefront-Antispam-Report":"CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n\tIPV:NLI; SFV:NSPM; H:GVXPR04MB9831.eurprd04.prod.outlook.com; PTR:;\n\tCAT:NONE; \n\tSFS:(13230040)(1800799024)(366016)(19092799006)(376014)(52116014)(38350700014);\n\tDIR:OUT; SFP:1101; ","X-MS-Exchange-AntiSpam-MessageData-ChunkCount":"1","X-MS-Exchange-AntiSpam-MessageData-0":"dkINNNF0l1QUkpCENoTgvoz9439qmbbOgn72BqJ0MFrmNklXOsmljQgiXAwK4k11GyVyzJcxioY7gyrWHn8pF1JFzYeZVsQ/fVcSac0yTo0PRijHdOgyoB+it4iL+Cjqfp1zhIfYtOxABBaRB7zM5ypeKGTo0PfdQtnA8TeAvw3FDuXgldHLxiIJz6dKAJtsmTOFJk/jzl7w3CKkMqdAvOTKqtgJMdN8yrc/hiKuuUNWYfKbdEsSuDnFEMqHtmaRYDXzBaF8uJCHY/JyETBjGFMHZfnNXnMhyQLZ6dAx5mkrU56x7XHu21uqHDczw5dTFs8R2TsPPAZZq34222mf0M+FGhEl0AZtrp+eEkh8+37K13s2p4gb31bQ1oFMln4vf4iHR023glraBwE2gPDq/0qRqXgyJuA2GZjShhHGxerixdgJXp9R5/9e6W1XQqMNORciwH1NIVO8TaVDI7Hm10k7kzb+e5D4y+1cDg4YP2eTsR6fFN4fJ2WoFXfGc9CZYR7iPlQ4GFnyT1QcOguGSBFK/Xy8Vvs5XSZtgshzpwuALo1sxThtUMbOf0DFtul8j8Aw0DUGG0sxla+6IyAiUaovwbC9Ri7anq7zC8ty0sIZbJnIkClh11300p+WVr+p/M1bEoQOnr/3lTbA5RyBf8TKEG5Dh6WQ2W/HyjHRNVoDUhSyqLPjOYu65vOVaJ3EWqa/pbAuRuH8edFCrrWjMb1yDx9nYdDvLZDBDQSI9wYK63yzSdoffoCGADwDlRsECNPhIBljEgA22Gh8ghQkeLgI46kPWdztgkK4Dk9w78MEcZ2U8krYOGI3k5cVESNzZRCStf09ePmf2BgljyFzJV7z7ipgbdWgcccjttkuabiGTLwzjIIKlc+R3jXvGALtJhIrJdkGGsGUlgdPswVbk+B2tagC5NnfJNCWZ1pjwcHU1Cc+bdis/aG7y53LF8W0ORNTs920u6R4aMmzDpSrFEE6m2HbQ/35MyN2W5iKNTjgX8jjqfFR5LjkAj3evyQ83TLIp19wEzlhOx3PDV5CeY8baIOM1EqoIx75hOr1KVIMciORyuPp00H9n4noxTotypXYRUnlOSWqQWYvTOJXKxGBfVFRXzcdY13REF9pEhPmUVP8CeoIyfdK7LzY8GUgBTGVEvGk6JKZyMv7EKOOnZBsdyZiRxt5GUO+U/P/PKdTP8o7r+Y7zAnOsT/ORDaDS09wewUYLm1q+7ZHSRtc9xsZk+Kc0frxl75nAy1vu2zvoTv5khWh5Rkvc/klO+KdqOI7DftfHL4TcMAPra2Pxfn9QrA7NpGFkskBe7VHgwFE/FA2EsntbO1O2TDhA/HuZ0lIXOquYxq/lKM9uUl85ItsJMSwQUM6C927lLljfOZy8viTTobV40k6TcjQLrgV5fc6BHnEH2PFA+4Lzz1gnQUb1ksDNJ4Ad983LC1281iXvAbe9bnmip77GHEgqij7Xo4Gll4h7X5QVOs91/pWRpxh2ntLdAVN6fZCVYyNDioTHH6yHvVxUv1Xt+knUhalfeP0+DGnJUQLyPMfTCpVmrALWb2it6SM0yii3Z+2rWR2gapj7TxGXW+ZpMH0hON0Ik55FmmRuyam+8VkMxhz2Q==","X-OriginatorOrg":"nxp.com","X-MS-Exchange-CrossTenant-Network-Message-Id":"cb6e063b-6390-4b32-447f-08de2dcbbdec","X-MS-Exchange-CrossTenant-AuthSource":"GVXPR04MB9831.eurprd04.prod.outlook.com","X-MS-Exchange-CrossTenant-AuthAs":"Internal","X-MS-Exchange-CrossTenant-OriginalArrivalTime":"27 Nov 2025 15:43:42.4115\n\t(UTC)","X-MS-Exchange-CrossTenant-FromEntityHeader":"Hosted","X-MS-Exchange-CrossTenant-Id":"686ea1d3-bc2b-4c6f-a92c-d99c5c301635","X-MS-Exchange-CrossTenant-MailboxType":"HOSTED","X-MS-Exchange-CrossTenant-UserPrincipalName":"WnwsJOhPduehpFrONDFkAA8qx4IY1yDhAk2fQAZn0DRKYv3fA7z4Wtn+R7s0nJYFGMyuDaSzrd6M+GtVnnLkBg==","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"PR3PR04MB7372","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: Andrei Gansari <andrei.gansari@nxp.com>\n\nThis change integrates the MediaPipeline class into the imx8-isi\npipeline handler. Purpose is to allow a dynamic discovery and\nconfiguration of the actual subdevices graph between the sensor and\nthe ISI crossbar. This brings support for more complex topologies and\nsimplifies the implementation.\n\nSigned-off-by: Andrei Gansari <andrei.gansari@nxp.com>\nSigned-off-by: Antoine Bouyer <antoine.bouyer@nxp.com>\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n---\n src/libcamera/pipeline/imx8-isi/imx8-isi.cpp | 159 ++++++++++++-------\n 1 file changed, 98 insertions(+), 61 deletions(-)","diff":"diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\nindex 049d9b1c44cb..008155ff21a7 100644\n--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp\n@@ -25,6 +25,7 @@\n #include \"libcamera/internal/camera_sensor.h\"\n #include \"libcamera/internal/device_enumerator.h\"\n #include \"libcamera/internal/media_device.h\"\n+#include \"libcamera/internal/media_pipeline.h\"\n #include \"libcamera/internal/pipeline_handler.h\"\n #include \"libcamera/internal/v4l2_subdevice.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n@@ -62,14 +63,15 @@ public:\n \tunsigned int getYuvMediaBusFormat(const PixelFormat &pixelFormat) const;\n \tunsigned int getMediaBusFormat(PixelFormat *pixelFormat) const;\n \n+\t/* All entities, from the sensor to the ISI. */\n+\tMediaPipeline mediaPipeline_;\n+\n \tstd::unique_ptr<CameraSensor> sensor_;\n-\tstd::unique_ptr<V4L2Subdevice> csis_;\n \n \tstd::vector<Stream> streams_;\n \n \tstd::vector<Stream *> enabledStreams_;\n \n-\tunsigned int xbarSink_ = 0;\n \tunsigned int xbarSourceOffset_ = 0;\n };\n \n@@ -141,6 +143,8 @@ private:\n \n \tvoid bufferReady(FrameBuffer *buffer);\n \n+\tstd::vector<MediaEntity *> locateSensors(MediaDevice *media);\n+\n \tstd::shared_ptr<MediaDevice> isiDev_;\n \n \tstd::unique_ptr<V4L2Subdevice> crossbar_;\n@@ -164,10 +168,6 @@ int ISICameraData::init()\n \tif (!sensor_)\n \t\treturn -ENODEV;\n \n-\tint ret = csis_->open();\n-\tif (ret)\n-\t\treturn ret;\n-\n \tproperties_ = sensor_->properties();\n \n \treturn 0;\n@@ -811,18 +811,29 @@ int PipelineHandlerISI::configure(Camera *camera, CameraConfiguration *c)\n {\n \tISICameraConfiguration *camConfig = static_cast<ISICameraConfiguration *>(c);\n \tISICameraData *data = cameraData(camera);\n+\tCameraSensor *sensor = data->sensor_.get();\n+\tint ret;\n \n-\t/* Apply format to the sensor, CSIS receiver and crossbar sink pad. */\n-\tV4L2SubdeviceFormat format = camConfig->sensorFormat_;\n-\tint ret = data->sensor_->setFormat(&format);\n-\tif (ret)\n+\t/*\n+\t * Enable the links all the way up to the ISI, through any connected CSI\n+\t * receiver and optional formatter.\n+\t */\n+\tret = data->mediaPipeline_.initLinks();\n+\tif (ret) {\n+\t\tLOG(ISI, Error) << \"Failed to set up pipe links\";\n \t\treturn ret;\n+\t}\n \n-\tret = data->csis_->setFormat(0, &format);\n+\t/*\n+\t * Configure the format on the sensor output and propagate it through\n+\t * the pipeline.\n+\t */\n+\tV4L2SubdeviceFormat format = camConfig->sensorFormat_;\n+\tret = sensor->setFormat(&format);\n \tif (ret)\n \t\treturn ret;\n \n-\tret = crossbar_->setFormat(data->xbarSink_, &format);\n+\tret = data->mediaPipeline_.configure(sensor, &format);\n \tif (ret)\n \t\treturn ret;\n \n@@ -979,13 +990,8 @@ bool PipelineHandlerISI::match(DeviceEnumerator *enumerator)\n \t\treturn false;\n \n \t/* Count the number of sensors, to create one camera per sensor. */\n-\tunsigned cameraCount = 0;\n-\tfor (MediaEntity *entity : isiDev_->entities()) {\n-\t\tif (entity->function() != MEDIA_ENT_F_CAM_SENSOR)\n-\t\t\tcontinue;\n-\n-\t\tcameraCount++;\n-\t}\n+\tstd::vector<MediaEntity *> sensorEntities = locateSensors(isiDev_.get());\n+\tunsigned int cameraCount = sensorEntities.size();\n \n \tif (!cameraCount) {\n \t\tLOG(ISI, Error) << \"No camera sensor found\";\n@@ -1048,60 +1054,28 @@ bool PipelineHandlerISI::match(DeviceEnumerator *enumerator)\n \t * sensors to get at least one dedicated pipe.\n \t */\n \tunsigned int numCameras = 0;\n-\tunsigned int numSinks = 0;\n \tconst unsigned int xbarFirstSource = crossbar_->entity()->pads().size() - pipes_.size();\n \tconst unsigned int maxStreams = pipes_.size() / cameraCount;\n \n-\tfor (MediaPad *pad : crossbar_->entity()->pads()) {\n-\t\tunsigned int sink = numSinks;\n-\n-\t\tif (!(pad->flags() & MEDIA_PAD_FL_SINK))\n-\t\t\tcontinue;\n-\n-\t\t/*\n-\t\t * Count each crossbar sink pad to correctly configure\n-\t\t * routing and format for this camera.\n-\t\t */\n-\t\tnumSinks++;\n-\n-\t\tif (pad->links().empty())\n-\t\t\tcontinue;\n-\n-\t\tMediaEntity *csi = pad->links()[0]->source()->entity();\n-\t\tif (csi->pads().size() != 2) {\n-\t\t\tLOG(ISI, Debug) << \"Skip unsupported CSI-2 receiver \"\n-\t\t\t\t\t<< csi->name();\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\tpad = csi->pads()[0];\n-\t\tif (!(pad->flags() & MEDIA_PAD_FL_SINK) || pad->links().empty())\n-\t\t\tcontinue;\n-\n-\t\tMediaEntity *sensor = pad->links()[0]->source()->entity();\n-\t\tif (sensor->function() != MEDIA_ENT_F_CAM_SENSOR) {\n-\t\t\tLOG(ISI, Debug) << \"Skip unsupported subdevice \"\n-\t\t\t\t\t<< sensor->name();\n-\t\t\tcontinue;\n-\t\t}\n-\n-\t\t/* All links are immutable except the sensor -> csis link. */\n-\t\tconst MediaPad *sensorSrc = sensor->getPadByIndex(0);\n-\t\tsensorSrc->links()[0]->setEnabled(true);\n-\n+\tfor (MediaEntity *sensor : sensorEntities) {\n \t\t/* Create the camera data. */\n \t\tstd::unique_ptr<ISICameraData> data =\n \t\t\tstd::make_unique<ISICameraData>(this, maxStreams);\n \n+\t\tret = data->mediaPipeline_.init(sensor, \"crossbar\");\n+\t\tif (ret)\n+\t\t\tcontinue;\n+\n+\t\tconst MediaPipeline::Entity *xbarEntity = &data->mediaPipeline_.entities().back();\n+\t\tunsigned int xbarSinkIndex = xbarEntity->sink->index();\n+\n \t\tdata->sensor_ = CameraSensorFactoryBase::create(sensor);\n-\t\tdata->csis_ = std::make_unique<V4L2Subdevice>(csi);\n-\t\tdata->xbarSink_ = sink;\n \t\tdata->xbarSourceOffset_ = numCameras * data->streams_.size();\n \n \t\tLOG(ISI, Debug)\n \t\t\t<< \"cam\" << numCameras\n \t\t\t<< \" streams \" << data->streams_.size()\n-\t\t\t<< \" sink \" << data->xbarSink_\n+\t\t\t<< \" sink \" << xbarSinkIndex\n \t\t\t<< \" offset \" << data->xbarSourceOffset_;\n \n \t\tret = data->init();\n@@ -1120,7 +1094,7 @@ bool PipelineHandlerISI::match(DeviceEnumerator *enumerator)\n \t\t/*  Add routes to the crossbar switch routing table. */\n \t\tfor (unsigned i = 0; i < data->streams_.size(); i++) {\n \t\t\tunsigned int sourcePad = xbarFirstSource + data->xbarSourceOffset_ + i;\n-\t\t\trouting_.emplace_back(V4L2Subdevice::Stream{ data->xbarSink_, 0 },\n+\t\t\trouting_.emplace_back(V4L2Subdevice::Stream{ xbarSinkIndex, 0 },\n \t\t\t\t\t     V4L2Subdevice::Stream{ sourcePad, 0 },\n \t\t\t\t\t     V4L2_SUBDEV_ROUTE_FL_ACTIVE);\n \t\t}\n@@ -1163,6 +1137,69 @@ void PipelineHandlerISI::bufferReady(FrameBuffer *buffer)\n \tcompleteRequest(request);\n }\n \n+/* Original function taken from simple.cpp */\n+std::vector<MediaEntity *>\n+PipelineHandlerISI::locateSensors(MediaDevice *media)\n+{\n+\tstd::vector<MediaEntity *> entities;\n+\n+\t/*\n+\t * Gather all the camera sensor entities based on the function they\n+\t * expose.\n+\t */\n+\tfor (MediaEntity *entity : media->entities()) {\n+\t\tif (entity->function() == MEDIA_ENT_F_CAM_SENSOR)\n+\t\t\tentities.push_back(entity);\n+\t}\n+\n+\tif (entities.empty())\n+\t\treturn {};\n+\n+\t/*\n+\t * Sensors can be made of multiple entities. For instance, a raw sensor\n+\t * can be connected to an ISP, and the combination of both should be\n+\t * treated as one sensor. To support this, as a crude heuristic, check\n+\t * the downstream entity from the camera sensor, and if it is an ISP,\n+\t * use it instead of the sensor.\n+\t */\n+\tstd::vector<MediaEntity *> sensors;\n+\n+\tfor (MediaEntity *entity : entities) {\n+\t\t/*\n+\t\t * Locate the downstream entity by following the first link\n+\t\t * from a source pad.\n+\t\t */\n+\t\tconst MediaLink *link = nullptr;\n+\n+\t\tfor (const MediaPad *pad : entity->pads()) {\n+\t\t\tif ((pad->flags() & MEDIA_PAD_FL_SOURCE) &&\n+\t\t\t    !pad->links().empty()) {\n+\t\t\t\tlink = pad->links()[0];\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!link)\n+\t\t\tcontinue;\n+\n+\t\tMediaEntity *remote = link->sink()->entity();\n+\t\tif (remote->function() == MEDIA_ENT_F_PROC_VIDEO_ISP)\n+\t\t\tsensors.push_back(remote);\n+\t\telse\n+\t\t\tsensors.push_back(entity);\n+\t}\n+\n+\t/*\n+\t * Remove duplicates, in case multiple sensors are connected to the\n+\t * same ISP.\n+\t */\n+\tstd::sort(sensors.begin(), sensors.end());\n+\tauto last = std::unique(sensors.begin(), sensors.end());\n+\tsensors.erase(last, sensors.end());\n+\n+\treturn sensors;\n+}\n+\n REGISTER_PIPELINE_HANDLER(PipelineHandlerISI, \"imx8-isi\")\n \n } /* namespace libcamera */\n","prefixes":["v3","2/2"]}