From patchwork Thu Mar 6 16:56:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Riesch X-Patchwork-Id: 14005014 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 39EA0C282D1 for ; Thu, 6 Mar 2025 17:10:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:MIME-Version:Cc:To: In-Reply-To:References:Message-Id:Content-Transfer-Encoding:Content-Type: Subject:Date:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=xAtgJa+/EwNCVWEDtt1GoWNhickiQDHH53RIj5CHu/s=; b=znua8LUqdeWPdWMugCK6XCrxZf La89lrh6rXuumJp6HQ3XU26UbBNpgWsu/bpCYWM1wbSuCJbVHjDMLxYtYsztNLDgJY1gc6GOgzqS3 cOnWrBzSLhzErURWJNIvxTNnCoYD0vexbB8c+akfYrzqDuH1+9cAqSw+69nMZUUHSgdUFFptIkM97 KeKEcfuIMDzxRNlkJlQyQfAcBtob2q6ztmyghYiOINlVQzUa8JhMV55V4Cg1vylogmXP71YrqF0oZ +m3lcnIqjclY0DlKifT/xGPDVthKpf+JxxwBYG/NEsIapmgziW4TI6SdgIBZPX8LQEBpIoPIbk9hG 9zd/R2xA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tqEjq-0000000Bdav-21hg; Thu, 06 Mar 2025 17:10:26 +0000 Received: from mail-northeuropeazlp170120003.outbound.protection.outlook.com ([2a01:111:f403:c200::3] helo=DU2PR03CU002.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tqEWK-0000000BafT-16cZ; Thu, 06 Mar 2025 16:56:29 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=lE32QKNpEhisW+yvuKK5AeBeFjUr9/wS02MhP7KssFRcuEPe4mUE6rx8x06AXPQj9XOh5XONA3JsBgyBLsud3OP4tsvrd9fKRBWLzRx9pHUENr+AcAJEM+sp9ZY3vUsb4xeFti5mbEa7TUePi1Z2KnE++xMscYgqGb0pWHYWiyrgrHjesandNdZY5hb3dkG2dAB9tELRHhdCVQq7BB6MSGcPincjx6V/oLUgJTr1dRBSv30ECbZ6xwXSZIRaMs9EpsHHxpHV0eFzMxVol0Iwvkmr1Vt2FOQ9Tlgw7ifQRJPgIJVNUXwtiShucWQxDL7Z+K9Hy6qiRFqvmBPrN5YVug== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=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; bh=xAtgJa+/EwNCVWEDtt1GoWNhickiQDHH53RIj5CHu/s=; b=YM1/1c/F+AIAXA63lShYgXZwE/c49lQILrdgltE2stOt9Gb305FtIhDdLrGpudeHVia0Adgs2vuBCuN/Ll++d6hyBIRYZdUva04vrrHq3kuIdwCTUpk5BcdQKJo7uhKX8Er4AyGnj6wSTqkv9n9fW8IPUqHF3MJ5E+ZCL6A9nQH7pLlGsCXWnpdmLUwRK5qsXyshcx/pwCPyYJJ8aa4hppTI+diPNqCrlqG8n/ll+d58iWmNAgEWpQJEFWtI5zk+BYu33XFS6tetMUQjLcoxaQQZslaWBaJnh+2ohmbf0AXUpHU4mSeDveMqD6JTUPxJbJkG7MwhC22i6bfuDfnP4Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=wolfvision.net; dmarc=pass action=none header.from=wolfvision.net; dkim=pass header.d=wolfvision.net; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=wolfvision.net; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=xAtgJa+/EwNCVWEDtt1GoWNhickiQDHH53RIj5CHu/s=; b=buxsMBlC4ErcZtadjqtVIAxzhAQ6hB/zmaUy5rQ9SjYrXeyjq80W0ewB4fg2I0GaY5t0C7Ya/IgAs84QiLOn+JpzkU1+MwXDqauuT1QnrNZtb7eqGcIjoa3/AQinFy2eKROTxeizY8zlERYpVcOawWZZRxnldOOWPT6PcLGE3Mk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=wolfvision.net; Received: from DU0PR08MB9155.eurprd08.prod.outlook.com (2603:10a6:10:416::5) by GV1PR08MB11001.eurprd08.prod.outlook.com (2603:10a6:150:1f2::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8511.16; Thu, 6 Mar 2025 16:56:20 +0000 Received: from DU0PR08MB9155.eurprd08.prod.outlook.com ([fe80::4e72:c5d4:488e:f16d]) by DU0PR08MB9155.eurprd08.prod.outlook.com ([fe80::4e72:c5d4:488e:f16d%5]) with mapi id 15.20.8511.017; Thu, 6 Mar 2025 16:56:20 +0000 From: Michael Riesch Date: Thu, 06 Mar 2025 17:56:08 +0100 Subject: [PATCH v5 07/11] media: rockchip: rkcif: add support for mipi csi-2 receiver Message-Id: <20250306-v6-8-topic-rk3568-vicap-v5-7-f02152534f3c@wolfvision.net> References: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net> In-Reply-To: <20250306-v6-8-topic-rk3568-vicap-v5-0-f02152534f3c@wolfvision.net> To: Mehdi Djait , Maxime Chevallier , =?utf-8?q?Th=C3=A9o_Leb?= =?utf-8?q?run?= , Gerald Loacker , Thomas Petazzoni , Laurent Pinchart , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Heiko Stuebner , Kever Yang , Nicolas Dufresne , Sebastian Fricke , Sebastian Reichel , Paul Kocialkowski , Alexander Shiyan , Val Packett , Rob Herring , Philipp Zabel , Sakari Ailus Cc: linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, Michael Riesch X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1741280167; l=24737; i=michael.riesch@wolfvision.net; s=20240405; h=from:subject:message-id; bh=O6C5i9vmAK+MSXSwiwsvwi0MA2QtOMo2691qtgVSKjM=; b=mG0oci6uci0tpBYy7J5HJ0dkxCYhYwbFDMhDl6bNp6G6k2KPovL2B+f8t8ivqE6gSZp7beUac J2VetqogTC5B/DJnQTUdFpc1SWXNHLNuzf02rjHEtsIhG4Qim3LoqaB X-Developer-Key: i=michael.riesch@wolfvision.net; a=ed25519; pk=cSJmgKSH3B6kdCIDCl+IYDW1Pw/Ybc6g9rmnUd/G7Ck= X-ClientProxiedBy: VI1PR04CA0133.eurprd04.prod.outlook.com (2603:10a6:803:f0::31) To DU0PR08MB9155.eurprd08.prod.outlook.com (2603:10a6:10:416::5) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DU0PR08MB9155:EE_|GV1PR08MB11001:EE_ X-MS-Office365-Filtering-Correlation-Id: 77a2966c-75fa-4ba1-eb80-08dd5ccfd183 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|7416014|52116014|1800799024|366016|921020|38350700014; X-Microsoft-Antispam-Message-Info: =?utf-8?q?lxubFgqtlXk1XB974ANGDD9tTKf8x1Z?= =?utf-8?q?h9YxawjMT28K3fVJ7Syd2ouAnjMgeqLmroKzY+OxY+HoVuNAU0/WzaZhEFBhPF5JE?= =?utf-8?q?n7WWqDMAp6pZ+KVrklQ/x+sGqGSj6Idx3aNOA597QOdXkP2/ZK2EanIOI8hSYkLLh?= =?utf-8?q?vqM9VXzkNMsJruvJRTHXAgvHTDhWJ8pc9jG9WUngZV/MNF39K20PB/gZFOHe9Beg4?= =?utf-8?q?DFYMIFHNTGOXLc2ziSrbWACLfoOk9UX7eS5CEkjGI04d2VLvCU6DMULXJyJNbojsk?= =?utf-8?q?NGiZEPS8rgaPhGAa9+Yc/lVLvaLDOaQEHJYS3HH+Ue5cI/jX8vASF6SNIf964+uW9?= =?utf-8?q?5ri/NlQRoUnSQ/OiMCDRNHjQB57dSLO2SiGtaqIHo5eHsk0QpAy9sGwpr+gJD4mdk?= =?utf-8?q?ihlCDvjTXqprptaJGq8jmvA2qPqScskkppQMU5+zE+d56uHE3hB2XvTWlmYoUkFzh?= =?utf-8?q?rEqpSARM/knzsCL1MYdxGGex7XDDBhKh5L/a/o2PAYlkxvW6d/bk2yhZHGr1Rp0Fy?= =?utf-8?q?FWy7DOk5zXBvfzDcq4KCGrYzoODiCiizEW4Vk9yV/RWjKTYex7gKIZKz8mFRBDKJw?= =?utf-8?q?bf3ziiSoLM7R3c/itqx8JQ0vT5SZzYoeznkjSD8G3cHSVU3MVyedUkOgWUUGqfl4j?= =?utf-8?q?raRNM12b4HMDbo2vQusn0KUiODdoCQG9rfzUL6zmrChs5GiZe6gygktRfaHiSPZSa?= =?utf-8?q?b4YOdBHySKe4jEr38NiakRrFYIgrdwgsahJPT3QvJ6yxGZaevisoSNzrM3JZgw+rR?= =?utf-8?q?m+uB7SoKrmcmPUnSTU+ffTWawwLicIDvUsZiE+eahOGkQv4Z457qWu+e5PBHAsZd/?= =?utf-8?q?EnHVrd3PI2T5fMCv5ivhCxQN62OyCXdyKSXHysg+gbfDa/3NhBxi2YlBVNrijxBIR?= =?utf-8?q?S4Nx87CJXQR4eGmexGQQOrdBfssDC76UPKTe+bJigS7n1KV5l4KNxvhcwFNm14+p2?= =?utf-8?q?19F3yeeqlqPZc7mft1wvd2k5ylL7fjViIlF8cSVJIlHBSW8u4KpyaLkheKa40QExm?= =?utf-8?q?d2VZ7bM6/P07xGVPrFJnoRq2cMKod7sVnaFdkgsmX6KhDevSQBtv9qAUk8LxH03JP?= =?utf-8?q?2Ra+9wY2T6qQPzjPsEqLO+TWuyKGMTlZg4GGbK0aHZKM2z/XMlKOOgBBGlpcVtx1Z?= =?utf-8?q?1PX/tVOSywzKuSOvNBIiltRNaHo5l5vIVDVSwY6uYxaMTA5B/tdrWEbY0Cc437A5y?= =?utf-8?q?s3dCxofSvtW4S4fl3d3r3q9jY2opIJk3H/tWLjW3ItIrM3bFrmQlQG1WgrFKU2jdT?= =?utf-8?q?Aqna7f7hV5TB276QSEZ0lb7eg14NGNmCZ/Atr8vT7RKI+sXqbx9rVaO+mnE4pK5IK?= =?utf-8?q?8d0TawnFdMunlwr0cU285HgXiSWNpS+4lN8thBr2A8k5eU60DwZTu61OMLC8SgIt8?= =?utf-8?q?DWI4VIK5SE9uSLPMxpO6Y1TmZFW/yLMjg=3D=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DU0PR08MB9155.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(376014)(7416014)(52116014)(1800799024)(366016)(921020)(38350700014);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?q?d5U8uxlt95LkYz+JWHgBM5EzNzMq?= =?utf-8?q?VVwSGoP721sYFlIwjKTx5z4sDKkgexUpOlxlGyQTIblKt5lIPWCSZFHNZZJkydw/y?= =?utf-8?q?6m1Xy5lmZF+5mJsoCjzdO+SN6VJ6PpwPdVx5NPhGt39ZjC795CZ5cr3blAJtStJ5t?= =?utf-8?q?Y58mZ57WOEE6K1jWQSPvfenAa+oFjz1jFeQLwPDlNe6O/i9WfrjuEhaXGz0vMWcmy?= =?utf-8?q?96yDY7s/z4mbfoxWxdVMALaM0N+RDAZ1SMH/+su6BDnbi14Ah98LTs01bmtlGsJb2?= =?utf-8?q?IXUgOVJ9XuAzxcw7dIHFNaG6ZpvjphqvpYDHetLxDx6Mr94TvTpYUywHGYXLVZdzW?= =?utf-8?q?khuhcQNryo56fqPU8qk7g8l5uaE0oHT+yyH59GtfgjG2BguAeeMVVXXB5M9qTnQUG?= =?utf-8?q?/7aXSlItk7yYSqxJNCroYIpf51iPtYrPX50Hb0bUgQcbGwmUvgUOcgA//aHKsHd41?= =?utf-8?q?gc9ofhIBLSoRsJdDG/HKvJyclY936J5kd7KhxFxuWlGDP3PxI0WkL5xBZPPloYVP9?= =?utf-8?q?lDA8R6mH18LpNEv+BjqwPyc2tlw5eJ0lNCQAx/IhHyjOgJi0IB3+LN2Qe8RFBLMsU?= =?utf-8?q?tD1HB6geEhIqH7ZP4PeqCgQWZ8BX8lA8rLBBt33h2Rw4nxzGKcpP76Kb2/dn8rmhj?= =?utf-8?q?yf7IIZNdaV6uq/Z2kb3gMwjQvVRmFfUDVtB1JbeEV6Vm8GP8KYRJ5UiQeu7p3MR9M?= =?utf-8?q?o4jZEykoEpj4QE5NaqRq9z+cA0u34KYu3g+774VnvuQUX7ps1f9cGIlV3kh+w/Tlm?= =?utf-8?q?1tXf4AOXPOHzoD7ixRxdvHjy4MKBWlz7fTGf0SJ5TEath36JIMQGHqEQznRRYCqQD?= =?utf-8?q?HAY4jw0HS85vMaZ5eUuJPk+65eM7Am5ewVrxJE4cGTSgC8O7E2zZsfcVRUY7y72py?= =?utf-8?q?eEgkd/TG47Vg4Lgq6r6gA6afaIAOWEdMKsllvhEAusvuAp+UG8PI5rcP25DlKbVQc?= =?utf-8?q?yojAfdbgixy04lGuXSkLd+uo1bBihUsgAfrL1XMtE+BzGTSAStFb6y+TaFmxTQ7aH?= =?utf-8?q?mupMqkEJ9esde4irI3qNMB4UQDbGE6tMa9S4yR/idlHY0Or89mdAUmGPDwgDYqsHG?= =?utf-8?q?4oQh+23zFKC0NijxL6yALd+NjkUtJbxSgBFMS6zpZNY9gGDJyQb6n6bI1lUrJKCXb?= =?utf-8?q?TPaxFqx8Xi6eUPLHnl64cjKRAxTpe/xJomvWYh3JpY8RLE5i76qjUfvbcAdEzXgK8?= =?utf-8?q?vcnCga0XiNLF/ozVH/c5qw3gOMaue3xOjB/I3ExzYEWZBTc7yWEaHTE0/oGYTs879?= =?utf-8?q?pF3oY9DseC6LjGF6HebWULuprCZL5LdJdsGVGm7GygFDayjFj2Cs7jJqygKlEctL4?= =?utf-8?q?bdTB53YKjYuivCK7bCQRVKPxoP4tqE/trAq3+z/XuPANPh7+TdWz3Q9v77kPdhtwb?= =?utf-8?q?szpMuZDMcamDiLTYV1l4+bpUVH/NKPGRe5l8oBYbYeBc9BQMZysaFKtyX9fFs0JmK?= =?utf-8?q?o+Ut97ODGev4N17XCcVjLC2uqf199xwo27pp7+u4L5KUIDyibpTTLoTGPP7zI1qRT?= =?utf-8?q?vm1PDu3g1yFC4JcHFIchHpD6wNYZJqUkoQ=3D=3D?= X-OriginatorOrg: wolfvision.net X-MS-Exchange-CrossTenant-Network-Message-Id: 77a2966c-75fa-4ba1-eb80-08dd5ccfd183 X-MS-Exchange-CrossTenant-AuthSource: DU0PR08MB9155.eurprd08.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Mar 2025 16:56:20.1219 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: e94ec9da-9183-471e-83b3-51baa8eb804f X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: PKzkffoABHQEZkSANstQ958GfJgDyiLQjPGBjYtve1NNZRZrWo33frk6XlBajw6YWfLR0xVmxyX6coW4pc6rRgkbEtZ5ZQXZzaph+c4mB8w= X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV1PR08MB11001 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250306_085628_319269_05096C5D X-CRM114-Status: GOOD ( 13.16 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The RK3568 Video Capture (VICAP) unit features a MIPI CSI-2 receiver that can receive video data and write it into system memory using the ping-pong scheme. Add support for it. Signed-off-by: Michael Riesch --- .../platform/rockchip/rkcif/rkcif-capture-mipi.c | 695 +++++++++++++++++++++ .../platform/rockchip/rkcif/rkcif-capture-mipi.h | 2 + .../media/platform/rockchip/rkcif/rkcif-common.h | 16 + drivers/media/platform/rockchip/rkcif/rkcif-dev.c | 1 + .../platform/rockchip/rkcif/rkcif-interface.c | 5 +- drivers/media/platform/rockchip/rkcif/rkcif-regs.h | 24 +- 6 files changed, 741 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c index 0c3f7b8cfa18..dcc0c4aeeec4 100644 --- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c +++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c @@ -6,22 +6,717 @@ * Copyright (C) 2025 Michael Riesch */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + #include "rkcif-capture-mipi.h" #include "rkcif-common.h" +#include "rkcif-interface.h" +#include "rkcif-regs.h" #include "rkcif-stream.h" +#define RKCIF_MIPI_CTRL0_COMPACT_EN BIT(6) +#define RKCIF_MIPI_CTRL0_CROP_EN BIT(5) +#define RKCIF_MIPI_CTRL0_TYPE(type) ((type) << 1) +#define RKCIF_MIPI_CTRL0_TYPE_RAW8 RKCIF_MIPI_CTRL0_TYPE(0x0) +#define RKCIF_MIPI_CTRL0_TYPE_RAW10 RKCIF_MIPI_CTRL0_TYPE(0x1) +#define RKCIF_MIPI_CTRL0_TYPE_RAW12 RKCIF_MIPI_CTRL0_TYPE(0x2) +#define RKCIF_MIPI_CTRL0_TYPE_RGB888 RKCIF_MIPI_CTRL0_TYPE(0x3) +#define RKCIF_MIPI_CTRL0_TYPE_YUV422SP RKCIF_MIPI_CTRL0_TYPE(0x4) +#define RKCIF_MIPI_CTRL0_TYPE_YUV420SP RKCIF_MIPI_CTRL0_TYPE(0x5) +#define RKCIF_MIPI_CTRL0_TYPE_YUV400 RKCIF_MIPI_CTRL0_TYPE(0x6) +#define RKCIF_MIPI_CTRL0_CAP_EN BIT(0) + +#define RKCIF_MIPI_INT_FRAME0_END(id) BIT(8 + (id) * 2 + 0) +#define RKCIF_MIPI_INT_FRAME1_END(id) BIT(8 + (id) * 2 + 1) + +static const struct rkcif_output_fmt mipi_out_fmts[] = { + /* YUV formats */ + { + .fourcc = V4L2_PIX_FMT_YUYV, + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, + .depth = 16, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_YUV422_8B, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + { + .fourcc = V4L2_PIX_FMT_UYVY, + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, + .depth = 16, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_YUV422_8B, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + { + .fourcc = V4L2_PIX_FMT_YVYU, + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, + .depth = 16, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_YUV422_8B, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + { + .fourcc = V4L2_PIX_FMT_VYUY, + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, + .depth = 16, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_YUV422_8B, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + /* RGB formats */ + { + .fourcc = V4L2_PIX_FMT_RGB24, + .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, + .depth = 24, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RGB888, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RGB888, + }, + }, + { + .fourcc = V4L2_PIX_FMT_BGR24, + .mbus_code = MEDIA_BUS_FMT_BGR888_1X24, + .depth = 24, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RGB888, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RGB888, + }, + }, + /* Bayer formats */ + { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, + .depth = 8, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW8, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, + .depth = 8, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW8, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, + .depth = 8, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW8, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, + .depth = 8, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW8, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW8, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR10P, + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG10, + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG10P, + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG10P, + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB10, + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB10P, + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, + .depth = 10, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW10, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW10 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR12, + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SBGGR12P, + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG12, + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGBRG12P, + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG12, + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SGRBG12P, + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB12, + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12, + }, + }, + { + .fourcc = V4L2_PIX_FMT_SRGGB12P, + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, + .depth = 12, + .cplanes = 1, + .mipi = { + .dt = MIPI_CSI2_DT_RAW12, + .ctrl0_val = RKCIF_MIPI_CTRL0_TYPE_RAW12 | RKCIF_MIPI_CTRL0_COMPACT_EN, + }, + }, +}; + +static const struct rkcif_input_fmt mipi_in_fmts[] = { + /* YUV formats */ + { + .mbus_code = MEDIA_BUS_FMT_YUYV8_1X16, + }, + { + .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16, + }, + { + .mbus_code = MEDIA_BUS_FMT_YVYU8_1X16, + }, + { + .mbus_code = MEDIA_BUS_FMT_VYUY8_1X16, + }, + /* RGB formats */ + { + .mbus_code = MEDIA_BUS_FMT_RGB888_1X24, + }, + { + .mbus_code = MEDIA_BUS_FMT_BGR888_1X24, + }, + /* Bayer formats */ + { + .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8, + }, + { + .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8, + }, + { + .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8, + }, + { + .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8, + }, + { + .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10, + }, + { + .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10, + }, + { + .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10, + }, + { + .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10, + }, + { + .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12, + }, + { + .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12, + }, + { + .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12, + }, + { + .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12, + }, +}; + +const struct rkcif_mipi_match_data rk3568_vicap_mipi_match_data = { + .mipi_num = 1, + .regs = { + [RKCIF_MIPI_CTRL] = 0x20, + [RKCIF_MIPI_INTEN] = 0xa4, + [RKCIF_MIPI_INTSTAT] = 0xa8, + }, + .regs_id = { + [RKCIF_ID0] = { + [RKCIF_MIPI_CTRL0] = 0x00, + [RKCIF_MIPI_CTRL1] = 0x04, + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x24, + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x2c, + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x34, + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x3c, + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x28, + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x30, + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x38, + [RKCIF_MIPI_FRAME1_VLW_UV] = 0x40, + [RKCIF_MIPI_CROP_START] = 0xbc, + }, + [RKCIF_ID1] = { + [RKCIF_MIPI_CTRL0] = 0x08, + [RKCIF_MIPI_CTRL1] = 0x0c, + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x44, + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x4c, + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x54, + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x5c, + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x48, + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x50, + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x58, + [RKCIF_MIPI_FRAME1_VLW_UV] = 0x60, + [RKCIF_MIPI_CROP_START] = 0xc0, + }, + [RKCIF_ID2] = { + [RKCIF_MIPI_CTRL0] = 0x10, + [RKCIF_MIPI_CTRL1] = 0x14, + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x64, + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x6c, + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x74, + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x7c, + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x68, + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x70, + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x78, + [RKCIF_MIPI_FRAME1_VLW_UV] = 0x80, + [RKCIF_MIPI_CROP_START] = 0xc4, + }, + [RKCIF_ID3] = { + [RKCIF_MIPI_CTRL0] = 0x18, + [RKCIF_MIPI_CTRL1] = 0x1c, + [RKCIF_MIPI_FRAME0_ADDR_Y] = 0x84, + [RKCIF_MIPI_FRAME0_ADDR_UV] = 0x8c, + [RKCIF_MIPI_FRAME0_VLW_Y] = 0x94, + [RKCIF_MIPI_FRAME0_VLW_UV] = 0x9c, + [RKCIF_MIPI_FRAME1_ADDR_Y] = 0x88, + [RKCIF_MIPI_FRAME1_ADDR_UV] = 0x90, + [RKCIF_MIPI_FRAME1_VLW_Y] = 0x98, + [RKCIF_MIPI_FRAME1_VLW_UV] = 0xa0, + [RKCIF_MIPI_CROP_START] = 0xc8, + }, + }, + .blocks = { + { + .offset = 0x80, + }, + }, +}; + +static inline unsigned int rkcif_mipi_get_reg(struct rkcif_interface *interface, + unsigned int index) +{ + struct rkcif_device *rkcif = interface->rkcif; + unsigned int block, offset, reg; + + block = interface->index - RKCIF_MIPI_BASE; + + if (WARN_ON(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) || + WARN_ON(index > RKCIF_MIPI_REGISTER_MAX)) + return RKCIF_REGISTER_NOTSUPPORTED; + + offset = rkcif->match_data->mipi->blocks[block].offset; + reg = rkcif->match_data->mipi->regs[index]; + if (reg == RKCIF_REGISTER_NOTSUPPORTED) + return reg; + + return offset + reg; +} + +static inline unsigned int rkcif_mipi_id_get_reg(struct rkcif_stream *stream, + unsigned int index) +{ + struct rkcif_device *rkcif = stream->rkcif; + unsigned int block, id, offset, reg; + + block = stream->interface->index - RKCIF_MIPI_BASE; + id = stream->id; + + if (WARN_ON(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) || + WARN_ON(id > RKCIF_ID_MAX) || + WARN_ON(index > RKCIF_MIPI_ID_REGISTER_MAX)) + return RKCIF_REGISTER_NOTSUPPORTED; + + offset = rkcif->match_data->mipi->blocks[block].offset; + reg = rkcif->match_data->mipi->regs_id[id][index]; + if (reg == RKCIF_REGISTER_NOTSUPPORTED) + return reg; + + return offset + reg; +} + +static inline __maybe_unused void +rkcif_mipi_write(struct rkcif_interface *interface, unsigned int index, u32 val) +{ + unsigned int addr = rkcif_mipi_get_reg(interface, index); + + if (addr == RKCIF_REGISTER_NOTSUPPORTED) + return; + + writel(val, interface->rkcif->base_addr + addr); +} + +static inline __maybe_unused void +rkcif_mipi_stream_write(struct rkcif_stream *stream, unsigned int index, + u32 val) +{ + unsigned int addr = rkcif_mipi_id_get_reg(stream, index); + + if (addr == RKCIF_REGISTER_NOTSUPPORTED) + return; + + writel(val, stream->rkcif->base_addr + addr); +} + +static inline __maybe_unused u32 +rkcif_mipi_read(struct rkcif_interface *interface, unsigned int index) +{ + unsigned int addr = rkcif_mipi_get_reg(interface, index); + + if (addr == RKCIF_REGISTER_NOTSUPPORTED) + return 0; + + return readl(interface->rkcif->base_addr + addr); +} + +static inline __maybe_unused u32 +rkcif_mipi_stream_read(struct rkcif_stream *stream, unsigned int index) +{ + unsigned int addr = rkcif_mipi_id_get_reg(stream, index); + + if (addr == RKCIF_REGISTER_NOTSUPPORTED) + return 0; + + return readl(stream->rkcif->base_addr + addr); +} + +static void rkcif_mipi_queue_buffer(struct rkcif_stream *stream, + unsigned int index) +{ + struct rkcif_buffer *buffer = stream->buffers[index]; + u32 frm_addr_y, frm_addr_uv; + + frm_addr_y = index ? RKCIF_MIPI_FRAME1_ADDR_Y : + RKCIF_MIPI_FRAME0_ADDR_Y; + frm_addr_uv = index ? RKCIF_MIPI_FRAME1_ADDR_UV : + RKCIF_MIPI_FRAME0_ADDR_UV; + + rkcif_mipi_stream_write(stream, frm_addr_y, + buffer->buff_addr[RKCIF_PLANE_Y]); + rkcif_mipi_stream_write(stream, frm_addr_uv, + buffer->buff_addr[RKCIF_PLANE_UV]); +} + +static int rkcif_mipi_start_streaming(struct rkcif_stream *stream) +{ + struct rkcif_interface *interface = stream->interface; + const struct rkcif_output_fmt *active_out_fmt; + struct v4l2_subdev_state *state; + u32 ctrl0 = 0, ctrl1 = 0, int_temp = 0, int_mask = 0, vlw = 0; + u16 height, width; + int ret = -EINVAL; + + state = v4l2_subdev_lock_and_get_active_state(&interface->sd); + + active_out_fmt = rkcif_stream_find_output_fmt(stream, false, + stream->pix.pixelformat); + if (!active_out_fmt) + goto out; + + height = stream->pix.height; + width = stream->pix.width; + /* TODO there may be different factors and/or alignment constraints */ + vlw = ALIGN(width * 2, 8); + + ctrl0 |= active_out_fmt->mipi.dt << 10; + ctrl0 |= active_out_fmt->mipi.ctrl0_val; + ctrl0 |= RKCIF_MIPI_CTRL0_CROP_EN; + ctrl0 |= RKCIF_MIPI_CTRL0_CAP_EN; + + ctrl1 = RKCIF_XY_COORD(width, height); + + int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id); + int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id); + + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN); + int_temp |= int_mask; + rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp); + + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT); + int_temp &= ~int_mask; + rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp); + + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_Y, vlw); + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_Y, vlw); + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_UV, vlw); + rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_UV, vlw); + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, 0x0); + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL1, ctrl1); + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, ctrl0); + + ret = 0; + +out: + v4l2_subdev_unlock_state(state); + return ret; +} + +static void rkcif_mipi_stop_streaming(struct rkcif_stream *stream) +{ + struct rkcif_interface *interface = stream->interface; + struct v4l2_subdev_state *state; + u32 int_temp = 0, int_mask = 0; + + state = v4l2_subdev_lock_and_get_active_state(&interface->sd); + + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, 0); + + int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id); + int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id); + + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN); + int_temp &= ~int_mask; + rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp); + + int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT); + int_temp &= ~int_mask; + rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp); + + stream->stopping = false; + + v4l2_subdev_unlock_state(state); +} + +static void rkcif_mipi_set_crop(struct rkcif_stream *stream, u16 left, u16 top) +{ + u32 val; + + val = RKCIF_XY_COORD(left, top); + rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, val); +} + irqreturn_t rkcif_mipi_isr(int irq, void *ctx) { + struct device *dev = ctx; + struct rkcif_device *rkcif = dev_get_drvdata(dev); irqreturn_t ret = IRQ_NONE; + u32 intstat; + + for (int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) { + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; + struct rkcif_interface *interface = &rkcif->interfaces[index]; + + intstat = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT); + rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, intstat); + + for (int j = 0; j < interface->streams_num; j++) { + struct rkcif_stream *stream = &interface->streams[j]; + + if (intstat & RKCIF_MIPI_INT_FRAME0_END(stream->id) || + intstat & RKCIF_MIPI_INT_FRAME1_END(stream->id)) { + rkcif_stream_pingpong(stream); + ret = IRQ_HANDLED; + } + } + } return ret; } int rkcif_mipi_register(struct rkcif_device *rkcif) { + int ret, i; + + if (!rkcif->match_data->mipi) + return 0; + + for (i = 0; i < rkcif->match_data->mipi->mipi_num; i++) { + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; + struct rkcif_interface *interface = &rkcif->interfaces[index]; + + interface->index = index; + interface->type = RKCIF_IF_MIPI; + interface->in_fmts = mipi_in_fmts; + interface->in_fmts_num = ARRAY_SIZE(mipi_in_fmts); + interface->set_crop = rkcif_mipi_set_crop; + interface->streams_num = 0; + ret = rkcif_interface_register(rkcif, interface); + if (ret) + continue; + + for (int j = 0; j < 4; j++) { + struct rkcif_stream *stream = &interface->streams[j]; + + stream->id = j; + stream->interface = interface; + stream->out_fmts = mipi_out_fmts; + stream->out_fmts_num = ARRAY_SIZE(mipi_out_fmts); + stream->queue_buffer = rkcif_mipi_queue_buffer; + stream->start_streaming = rkcif_mipi_start_streaming; + stream->stop_streaming = rkcif_mipi_stop_streaming; + ret = rkcif_stream_register(rkcif, stream); + if (ret) + goto err; + interface->streams_num++; + } + } + return 0; + +err: + for (; i >= 0; i--) { + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; + struct rkcif_interface *interface = &rkcif->interfaces[index]; + + for (int j = 0; j < interface->streams_num; j++) + rkcif_stream_unregister(&interface->streams[j]); + + rkcif_interface_unregister(interface); + } + return ret; } void rkcif_mipi_unregister(struct rkcif_device *rkcif) { + if (!rkcif->match_data->mipi) + return; + + for (int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) { + enum rkcif_interface_index index = RKCIF_MIPI_BASE + i; + struct rkcif_interface *interface = &rkcif->interfaces[index]; + + for (int j = 0; j < interface->streams_num; j++) + rkcif_stream_unregister(&interface->streams[j]); + + rkcif_interface_unregister(interface); + } } diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h index ee1a50a59505..48d04a60c750 100644 --- a/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h +++ b/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.h @@ -11,6 +11,8 @@ #include "rkcif-common.h" +extern const struct rkcif_mipi_match_data rk3568_vicap_mipi_match_data; + int rkcif_mipi_register(struct rkcif_device *rkcif); void rkcif_mipi_unregister(struct rkcif_device *rkcif); diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-common.h b/drivers/media/platform/rockchip/rkcif/rkcif-common.h index 32f6f0238656..99249a85048e 100644 --- a/drivers/media/platform/rockchip/rkcif/rkcif-common.h +++ b/drivers/media/platform/rockchip/rkcif/rkcif-common.h @@ -93,9 +93,14 @@ struct rkcif_output_fmt { u32 fourcc; u32 mbus_code; u8 cplanes; + u8 depth; union { u32 dvp_fmt_val; + struct { + u8 dt; + u32 ctrl0_val; + } mipi; }; }; @@ -183,6 +188,16 @@ struct rkcif_interface { void (*set_crop)(struct rkcif_stream *stream, u16 left, u16 top); }; +struct rkcif_mipi_match_data { + unsigned int mipi_num; + unsigned int regs[RKCIF_MIPI_REGISTER_MAX]; + unsigned int regs_id[RKCIF_ID_MAX][RKCIF_MIPI_ID_REGISTER_MAX]; + + struct { + unsigned int offset; + } blocks[RKCIF_MIPI_MAX - RKCIF_MIPI_BASE]; +}; + struct rkcif_dvp_match_data { const struct rkcif_input_fmt *in_fmts; unsigned int in_fmts_num; @@ -198,6 +213,7 @@ struct rkcif_match_data { const char *const *clks; unsigned int clks_num; const struct rkcif_dvp_match_data *dvp; + const struct rkcif_mipi_match_data *mipi; }; struct rkcif_device { diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c index 2f45229183f6..5cc4e458ffa1 100644 --- a/drivers/media/platform/rockchip/rkcif/rkcif-dev.c +++ b/drivers/media/platform/rockchip/rkcif/rkcif-dev.c @@ -49,6 +49,7 @@ static const struct rkcif_match_data rk3568_vicap_match_data = { .clks = rk3568_vicap_clks, .clks_num = ARRAY_SIZE(rk3568_vicap_clks), .dvp = &rk3568_vicap_dvp_match_data, + .mipi = &rk3568_vicap_mipi_match_data, }; static const struct of_device_id rkcif_plat_of_match[] = { diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-interface.c b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c index 7131de68de2c..163ee9e2fc6f 100644 --- a/drivers/media/platform/rockchip/rkcif/rkcif-interface.c +++ b/drivers/media/platform/rockchip/rkcif/rkcif-interface.c @@ -188,7 +188,10 @@ static int rkcif_interface_enable_streams(struct v4l2_subdev *sd, stream = &interface->streams[RKCIF_ID0]; rkcif_interface_apply_crop(stream, state); } else { - /* TODO implement for MIPI */ + for_each_active_route(&state->routing, route) { + stream = &interface->streams[route->sink_stream]; + rkcif_interface_apply_crop(stream, state); + } } mask = v4l2_subdev_state_xlate_streams(state, RKCIF_IF_PAD_SINK, diff --git a/drivers/media/platform/rockchip/rkcif/rkcif-regs.h b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h index 07fd64174e80..3d1f0c45c638 100644 --- a/drivers/media/platform/rockchip/rkcif/rkcif-regs.h +++ b/drivers/media/platform/rockchip/rkcif/rkcif-regs.h @@ -30,7 +30,29 @@ enum rkcif_dvp_register_index { RKCIF_DVP_REGISTER_MAX }; -#define RKCIF_REGISTER_NOTSUPPORTED 0x420000 +enum rkcif_mipi_register_index { + RKCIF_MIPI_CTRL, + RKCIF_MIPI_INTEN, + RKCIF_MIPI_INTSTAT, + RKCIF_MIPI_REGISTER_MAX +}; + +enum rkcif_mipi_id_register_index { + RKCIF_MIPI_CTRL0, + RKCIF_MIPI_CTRL1, + RKCIF_MIPI_FRAME0_ADDR_Y, + RKCIF_MIPI_FRAME0_ADDR_UV, + RKCIF_MIPI_FRAME0_VLW_Y, + RKCIF_MIPI_FRAME0_VLW_UV, + RKCIF_MIPI_FRAME1_ADDR_Y, + RKCIF_MIPI_FRAME1_ADDR_UV, + RKCIF_MIPI_FRAME1_VLW_Y, + RKCIF_MIPI_FRAME1_VLW_UV, + RKCIF_MIPI_CROP_START, + RKCIF_MIPI_ID_REGISTER_MAX +}; + +#define RKCIF_REGISTER_NOTSUPPORTED 0x420000 #define RKCIF_FETCH_Y(VAL) ((VAL) & 0x1fff)