Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2220311/?format=api
{ "id": 2220311, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2220311/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260406-gmsl2-3_serdes-v10-17-645560fedca5@analog.com/", "project": { "id": 42, "url": "http://patchwork.ozlabs.org/api/1.1/projects/42/?format=api", "name": "Linux GPIO development", "link_name": "linux-gpio", "list_id": "linux-gpio.vger.kernel.org", "list_email": "linux-gpio@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260406-gmsl2-3_serdes-v10-17-645560fedca5@analog.com>", "date": "2026-04-06T20:14:56", "name": "[v10,17/22] media: i2c: maxim-serdes: add MAX96724 driver", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "0cc6e70ea4ad392fe1b3024785080761576f841f", "submitter": { "id": 88270, "url": "http://patchwork.ozlabs.org/api/1.1/people/88270/?format=api", "name": "Dumitru Ceclan via B4 Relay", "email": "devnull+dumitru.ceclan.analog.com@kernel.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260406-gmsl2-3_serdes-v10-17-645560fedca5@analog.com/mbox/", "series": [ { "id": 498894, "url": "http://patchwork.ozlabs.org/api/1.1/series/498894/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/list/?series=498894", "date": "2026-04-06T20:14:42", "name": "media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers", "version": 10, "mbox": "http://patchwork.ozlabs.org/series/498894/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2220311/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2220311/checks/", "tags": {}, "headers": { "Return-Path": "\n <linux-gpio+bounces-34743-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-gpio@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=TlpqxBTz;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-gpio+bounces-34743-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"TlpqxBTz\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201" ], "Received": [ "from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fqLNP6ygDz1yFt\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 07 Apr 2026 06:22:29 +1000 (AEST)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 7E72D306242B\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 6 Apr 2026 20:16:33 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id ABD2D3A545D;\n\tMon, 6 Apr 2026 20:15:24 +0000 (UTC)", "from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id B04303A0B20;\n\tMon, 6 Apr 2026 20:15:22 +0000 (UTC)", "by smtp.kernel.org (Postfix) with ESMTPS id 93A44C2BCB0;\n\tMon, 6 Apr 2026 20:15:22 +0000 (UTC)", "from aws-us-west-2-korg-lkml-1.web.codeaurora.org\n (localhost.localdomain [127.0.0.1])\n\tby smtp.lore.kernel.org (Postfix) with ESMTP id 8B6FDFB5160;\n\tMon, 6 Apr 2026 20:15:22 +0000 (UTC)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775506522; cv=none;\n b=ao3Pkk5sFMCjUfQpu/jRvRWPBHh1FZv+uXAoKMLby+3i9v0xJgjuUF09aasMOIiCqs2CzQsyeX3vBSvOhNaLZFZ0dzNvcg/ZwnoM8BmK5lj8DS5giT0+TKVLudqgpKazFoV3uAT5sSNMD21s2s7g31Iz67+ju/mra2kbCvGBEiw=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775506522; c=relaxed/simple;\n\tbh=GWPbgEBb19QYua6mCTlTzqVd4vIdhEZnmLJZTFAuth0=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=bUykhVgK9WxsT+mHXOi2UvjkxYrLO0vjTcjOrh4/ARMpb02JlZa/5r5Uh4T8TgfgILTBCDkMjSAlbujJacdKl+1FSMFgu1tx1FbIO1CDC/mdTeKV6nxQ+XAVaTLcMPWxNMTof80eL91xENWSe3cVtM9wXA0inqLmG3Isc3oANTs=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=TlpqxBTz; arc=none smtp.client-ip=10.30.226.201", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1775506522;\n\tbh=GWPbgEBb19QYua6mCTlTzqVd4vIdhEZnmLJZTFAuth0=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From;\n\tb=TlpqxBTzHigZNgm2zQRO75Zhz/+In4U3ac4T0aZnwWDMw+0zMgwHW+eNCeYSxjV7Y\n\t POo0vqk/JJ3PsyVYQX1smfs4xMe5nuvy5oSqtJZruWCQabmz3qnwJI9GQ0UUPd7GtI\n\t utJRWwPS5Yj6cku2qkrMJbp+hS/B1Btb9roIpZWUr1HVK1ljliaO9MNr5jaIIk5uhx\n\t mQqV+CzCBQXdk+Mil7G8s2NkC4GXOJNHg5Fo1cPOU6aVWiQ9T2THtntfqycT8RT/KL\n\t 7HDml1GZA1HoCR3N87FZmg7BnU6h1nXTG70Fo75Z1KMPYb+kcEPZbLjLJspN8o2ejI\n\t F+4FvFKkXR7bA==", "From": "Dumitru Ceclan via B4 Relay\n <devnull+dumitru.ceclan.analog.com@kernel.org>", "Date": "Mon, 06 Apr 2026 23:14:56 +0300", "Subject": "[PATCH v10 17/22] media: i2c: maxim-serdes: add MAX96724 driver", "Precedence": "bulk", "X-Mailing-List": "linux-gpio@vger.kernel.org", "List-Id": "<linux-gpio.vger.kernel.org>", "List-Subscribe": "<mailto:linux-gpio+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-gpio+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "8bit", "Message-Id": "<20260406-gmsl2-3_serdes-v10-17-645560fedca5@analog.com>", "References": "<20260406-gmsl2-3_serdes-v10-0-645560fedca5@analog.com>", "In-Reply-To": "<20260406-gmsl2-3_serdes-v10-0-645560fedca5@analog.com>", "To": "Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>,\n Mauro Carvalho Chehab <mchehab@kernel.org>,\n Sakari Ailus <sakari.ailus@linux.intel.com>,\n Laurent Pinchart <laurent.pinchart@ideasonboard.com>,\n Julien Massot <julien.massot@collabora.com>, Rob Herring <robh@kernel.org>,\n\t=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>,\n Greg Kroah-Hartman <gregkh@linuxfoundation.org>,\n Cosmin Tanislav <cosmin.tanislav@analog.com>", "Cc": "mitrutzceclan@gmail.com, linux-media@vger.kernel.org,\n linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,\n linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, =?utf-8?q?Nikla?=\n\t=?utf-8?q?s_S=C3=B6derlund?= <niklas.soderlund+renesas@ragnatech.se>,\n Martin Hecht <Martin.Hecht@avnet.eu>,\n Cosmin Tanislav <demonsingur@gmail.com>, Cory Keitz <ckeitz@amazon.com>", "X-Mailer": "b4 0.14.3", "X-Developer-Signature": "v=1; a=ed25519-sha256; t=1775506518; l=42303;\n i=dumitru.ceclan@analog.com; s=20240313; h=from:subject:message-id;\n bh=CaIU8+ZcOKWMfVLHoUa8dokUTQY/Jaykz5CwHogwD6A=;\n b=UDOC+MyOgrdNjq3u0GZ6sJ/DpWAKjY2fLhHpYVD836buQosaYWr0wniuiBZi2OSQN9gh9A+55\n C0v2TudqVfkBua8jHjVXhUkAT08NvqZu+TqWpEcBSXMOVDRCELUvKJn", "X-Developer-Key": "i=dumitru.ceclan@analog.com; a=ed25519;\n pk=HdqMlVyrcazwoiai7oN6ghU+Bj1pusGUFRl30jhS7Bo=", "X-Endpoint-Received": "by B4 Relay for dumitru.ceclan@analog.com/20240313\n with auth_id=140", "X-Original-From": "Dumitru Ceclan <dumitru.ceclan@analog.com>", "Reply-To": "dumitru.ceclan@analog.com" }, "content": "From: Cosmin Tanislav <demonsingur@gmail.com>\n\nAdd a new MAX96724 driver that also supports MAX96712, MAX96724F\nand MAX96724R.\n\nIntegrate it with the common deserializer framework, while keeping\ncompatibility with existing usecases, avoiding code duplication, and\nalso enabling more features across all chips.\n\nSigned-off-by: Cosmin Tanislav <demonsingur@gmail.com>\nTested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>\nTested-by: Cory Keitz <ckeitz@amazon.com>\n---\n drivers/media/i2c/maxim-serdes/Kconfig | 12 +\n drivers/media/i2c/maxim-serdes/Makefile | 1 +\n drivers/media/i2c/maxim-serdes/max96724.c | 1261 +++++++++++++++++++++++++++++\n 3 files changed, 1274 insertions(+)", "diff": "diff --git a/drivers/media/i2c/maxim-serdes/Kconfig b/drivers/media/i2c/maxim-serdes/Kconfig\nindex ddbb5791e934..f060307e3de3 100644\n--- a/drivers/media/i2c/maxim-serdes/Kconfig\n+++ b/drivers/media/i2c/maxim-serdes/Kconfig\n@@ -33,3 +33,15 @@ config VIDEO_MAX96717\n \n \t To compile this driver as a module, choose M here: the module\n \t will be called max96717.\n+\n+config VIDEO_MAX96724\n+\ttristate \"Maxim MAX96724 Quad Deserializer support\"\n+\tdepends on I2C\n+\tselect VIDEO_MAXIM_SERDES\n+\thelp\n+\t This driver supports the Maxim MAX96712, MAX96724, MAX96724F,\n+\t MAX96724R Quad Deserializers, which convert from four GMSL2\n+\t links to up to four MIPI D-PHY or C-PHY outputs.\n+\n+\t To compile this driver as a module, choose M here: the module\n+\t will be called max96724.\ndiff --git a/drivers/media/i2c/maxim-serdes/Makefile b/drivers/media/i2c/maxim-serdes/Makefile\nindex 04abda6a5437..b6d5aebfaee1 100644\n--- a/drivers/media/i2c/maxim-serdes/Makefile\n+++ b/drivers/media/i2c/maxim-serdes/Makefile\n@@ -2,3 +2,4 @@\n max-serdes-objs := max_serdes.o max_ser.o max_des.o\n obj-$(CONFIG_VIDEO_MAXIM_SERDES) += max-serdes.o\n obj-$(CONFIG_VIDEO_MAX96717) += max96717.o\n+obj-$(CONFIG_VIDEO_MAX96724) += max96724.o\ndiff --git a/drivers/media/i2c/maxim-serdes/max96724.c b/drivers/media/i2c/maxim-serdes/max96724.c\nnew file mode 100644\nindex 000000000000..347d423caaab\n--- /dev/null\n+++ b/drivers/media/i2c/maxim-serdes/max96724.c\n@@ -0,0 +1,1261 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Maxim MAX96724 Quad GMSL2 Deserializer Driver\n+ *\n+ * Copyright (C) 2025 Analog Devices Inc.\n+ */\n+\n+#include <linux/bitfield.h>\n+#include <linux/delay.h>\n+#include <linux/gpio/consumer.h>\n+#include <linux/i2c.h>\n+#include <linux/iopoll.h>\n+#include <linux/module.h>\n+#include <linux/of_graph.h>\n+#include <linux/property.h>\n+#include <linux/regmap.h>\n+\n+#include \"max_des.h\"\n+\n+#define MAX96724_REG0\t\t\t\t0x0\n+\n+#define MAX96724_REG3\t\t\t\t0x3\n+#define MAX96724_REG3_CC_PORT_SEL(n)\t\tGENMASK((n) * 2 + 1, (n) * 2)\n+#define MAX96724_REG3_CC_PORT_SEL_MASK\t\t(MAX96724_REG3_CC_PORT_SEL(0) | \\\n+\t\t\t\t\t\t MAX96724_REG3_CC_PORT_SEL(1) | \\\n+\t\t\t\t\t\t MAX96724_REG3_CC_PORT_SEL(2) | \\\n+\t\t\t\t\t\t MAX96724_REG3_CC_PORT_SEL(3))\n+#define MAX96724_REG3_CC_PORT_SEL_PORT0\t\t0x2\n+#define MAX96724_REG3_CC_PORT_SEL_PORT1\t\t0x1\n+#define MAX96724_REG3_CC_PORT_CFG(sel) \\\n+\t(FIELD_PREP(MAX96724_REG3_CC_PORT_SEL(0), (sel)) | \\\n+\t FIELD_PREP(MAX96724_REG3_CC_PORT_SEL(1), (sel)) | \\\n+\t FIELD_PREP(MAX96724_REG3_CC_PORT_SEL(2), (sel)) | \\\n+\t FIELD_PREP(MAX96724_REG3_CC_PORT_SEL(3), (sel)))\n+#define MAX96724_REG3_CC_PORT_CFG_PORT0 \\\n+\tMAX96724_REG3_CC_PORT_CFG(MAX96724_REG3_CC_PORT_SEL_PORT0)\n+#define MAX96724_REG3_CC_PORT_CFG_PORT1 \\\n+\tMAX96724_REG3_CC_PORT_CFG(MAX96724_REG3_CC_PORT_SEL_PORT1)\n+\n+#define MAX96724_REG6\t\t\t\t0x6\n+#define MAX96724_REG6_LINK_EN\t\t\tGENMASK(3, 0)\n+\n+#define MAX96724_REG7\t\t\t\t0x7\n+#define MAX96724_REG7_CC_CROSSOVER_SEL\t\tGENMASK(7, 4)\n+\n+#define MAX96724_DEBUG_EXTRA\t\t\t0x9\n+#define MAX96724_DEBUG_EXTRA_PCLK_SRC\t\tGENMASK(1, 0)\n+#define MAX96724_DEBUG_EXTRA_PCLK_SRC_25MHZ\t0b00\n+#define MAX96724_DEBUG_EXTRA_PCLK_SRC_75MHZ\t0b01\n+#define MAX96724_DEBUG_EXTRA_PCLK_SRC_USE_PIPE\t0b10\n+\n+#define MAX96724_REG26(x)\t\t\t(0x10 + (x) / 2)\n+#define MAX96724_REG26_RX_RATE_PHY(x)\t\t(GENMASK(1, 0) << (4 * ((x) % 2)))\n+#define MAX96724_REG26_RX_RATE_3GBPS\t\t0b01\n+#define MAX96724_REG26_RX_RATE_6GBPS\t\t0b10\n+\n+#define MAX96724_PWR1\t\t\t\t0x13\n+#define MAX96724_PWR1_RESET_ALL\t\t\tBIT(6)\n+\n+#define MAX96724_CTRL1\t\t\t\t0x18\n+#define MAX96724_CTRL1_RESET_ONESHOT\t\tGENMASK(3, 0)\n+\n+#define MAX96724_VIDEO_PIPE_SEL(p)\t\t(0xf0 + (p) / 2)\n+#define MAX96724_VIDEO_PIPE_SEL_STREAM(p)\t(GENMASK(1, 0) << (4 * ((p) % 2)))\n+#define MAX96724_VIDEO_PIPE_SEL_LINK(p)\t\t(GENMASK(3, 2) << (4 * ((p) % 2)))\n+\n+#define MAX96724_VIDEO_PIPE_EN\t\t\t0xf4\n+#define MAX96724_VIDEO_PIPE_EN_MASK(p)\t\tBIT(p)\n+#define MAX96724_VIDEO_PIPE_EN_STREAM_SEL_ALL\tBIT(4)\n+\n+#define MAX96724_VPRBS(p)\t\t\t(0x1dc + (p) * 0x20)\n+#define MAX96724_VPRBS_VIDEO_LOCK\t\tBIT(0)\n+#define MAX96724_VPRBS_PATGEN_CLK_SRC\t\tBIT(7)\n+#define MAX96724_VPRBS_PATGEN_CLK_SRC_150MHZ\t0b0\n+#define MAX96724_VPRBS_PATGEN_CLK_SRC_375MHZ\t0b1\n+\n+#define MAX96724_BACKTOP12\t\t\t0x40b\n+#define MAX96724_BACKTOP12_CSI_OUT_EN\t\tBIT(1)\n+\n+#define MAX96724_BACKTOP21(p)\t\t\t(0x414 + (p) / 4 * 0x20)\n+#define MAX96724_BACKTOP21_BPP8DBL(p)\t\tBIT(4 + (p) % 4)\n+\n+#define MAX96724_BACKTOP22(x)\t\t\t(0x415 + (x) * 0x3)\n+#define MAX96724_BACKTOP22_PHY_CSI_TX_DPLL\tGENMASK(4, 0)\n+#define MAX96724_BACKTOP22_PHY_CSI_TX_DPLL_EN\tBIT(5)\n+\n+#define MAX96724_BACKTOP24(p)\t\t\t(0x417 + (p) / 4 * 0x20)\n+#define MAX96724_BACKTOP24_BPP8DBL_MODE(p)\tBIT(4 + (p) % 4)\n+\n+#define MAX96724_BACKTOP30(p)\t\t\t(0x41d + (p) / 4 * 0x20)\n+#define MAX96724_BACKTOP30_BPP10DBL3\t\tBIT(4)\n+#define MAX96724_BACKTOP30_BPP10DBL3_MODE\tBIT(5)\n+\n+#define MAX96724_BACKTOP31(p)\t\t\t(0x41e + (p) / 4 * 0x20)\n+#define MAX96724_BACKTOP31_BPP10DBL2\t\tBIT(6)\n+#define MAX96724_BACKTOP31_BPP10DBL2_MODE\tBIT(7)\n+\n+#define MAX96724_BACKTOP32(p)\t\t\t(0x41f + (p) / 4 * 0x20)\n+#define MAX96724_BACKTOP32_BPP12(p)\t\tBIT(p)\n+#define MAX96724_BACKTOP32_BPP10DBL0\t\tBIT(4)\n+#define MAX96724_BACKTOP32_BPP10DBL0_MODE\tBIT(5)\n+#define MAX96724_BACKTOP32_BPP10DBL1\t\tBIT(6)\n+#define MAX96724_BACKTOP32_BPP10DBL1_MODE\tBIT(7)\n+\n+#define MAX96724_MIPI_PHY0\t\t\t0x8a0\n+#define MAX96724_MIPI_PHY0_PHY_CONFIG\t\tGENMASK(4, 0)\n+#define MAX96724_MIPI_PHY0_PHY_4X2\t\tBIT(0)\n+#define MAX96724_MIPI_PHY0_PHY_2X4\t\tBIT(2)\n+#define MAX96724_MIPI_PHY0_PHY_1X4A_2X2\t\tBIT(3)\n+#define MAX96724_MIPI_PHY0_PHY_1X4B_2X2\t\tBIT(4)\n+#define MAX96724_MIPI_PHY0_FORCE_CSI_OUT_EN\tBIT(7)\n+\n+#define MAX96724_MIPI_PHY2\t\t\t0x8a2\n+#define MAX96724_MIPI_PHY2_PHY_STDB_N_4(x)\t(GENMASK(5, 4) << ((x) / 2 * 2))\n+#define MAX96724_MIPI_PHY2_PHY_STDB_N_2(x)\t(BIT(4 + (x)))\n+\n+#define MAX96724_MIPI_PHY3(x)\t\t\t(0x8a3 + (x) / 2)\n+#define MAX96724_MIPI_PHY3_PHY_LANE_MAP_4\tGENMASK(7, 0)\n+#define MAX96724_MIPI_PHY3_PHY_LANE_MAP_2(x)\t(GENMASK(3, 0) << (4 * ((x) % 2)))\n+\n+#define MAX96724_MIPI_PHY5(x)\t\t\t(0x8a5 + (x) / 2)\n+#define MAX96724_MIPI_PHY5_PHY_POL_MAP_4_0_1\tGENMASK(1, 0)\n+#define MAX96724_MIPI_PHY5_PHY_POL_MAP_4_2_3\tGENMASK(4, 3)\n+#define MAX96724_MIPI_PHY5_PHY_POL_MAP_4_CLK\tBIT(5)\n+#define MAX96724_MIPI_PHY5_PHY_POL_MAP_2(x)\t(GENMASK(1, 0) << (3 * ((x) % 2)))\n+#define MAX96724_MIPI_PHY5_PHY_POL_MAP_2_CLK(x)\tBIT(2 + 3 * ((x) % 2))\n+\n+#define MAX96724_MIPI_PHY13\t\t\t0x8ad\n+#define MAX96724_MIPI_PHY13_T_T3_PREBEGIN\tGENMASK(5, 0)\n+#define MAX96724_MIPI_PHY13_T_T3_PREBEGIN_64X7\tFIELD_PREP(MAX96724_MIPI_PHY13_T_T3_PREBEGIN, 63)\n+\n+#define MAX96724_MIPI_PHY14\t\t\t0x8ae\n+#define MAX96724_MIPI_PHY14_T_T3_PREP\t\tGENMASK(1, 0)\n+#define MAX96724_MIPI_PHY14_T_T3_PREP_55NS\tFIELD_PREP(MAX96724_MIPI_PHY14_T_T3_PREP, 0b01)\n+#define MAX96724_MIPI_PHY14_T_T3_POST\t\tGENMASK(6, 2)\n+#define MAX96724_MIPI_PHY14_T_T3_POST_32X7\tFIELD_PREP(MAX96724_MIPI_PHY14_T_T3_POST, 31)\n+\n+#define MAX96724_MIPI_CTRL_SEL\t\t\t0x8ca\n+#define MAX96724_MIPI_CTRL_SEL_MASK(p)\t\t(GENMASK(1, 0) << ((p) * 2))\n+\n+#define MAX96724_MIPI_PHY25(x)\t\t\t(0x8d0 + (x) / 2)\n+#define MAX96724_MIPI_PHY25_CSI2_TX_PKT_CNT(x)\t(GENMASK(3, 0) << (4 * ((x) % 2)))\n+\n+#define MAX96724_MIPI_PHY27(x)\t\t\t(0x8d2 + (x) / 2)\n+#define MAX96724_MIPI_PHY27_PHY_PKT_CNT(x)\t(GENMASK(3, 0) << (4 * ((x) % 2)))\n+\n+#define MAX96724_MIPI_TX3(x)\t\t\t(0x903 + (x) * 0x40)\n+#define MAX96724_MIPI_TX3_DESKEW_INIT_8X32K\tFIELD_PREP(GENMASK(2, 0), 0b001)\n+#define MAX96724_MIPI_TX3_DESKEW_INIT_AUTO\tBIT(7)\n+\n+#define MAX96724_MIPI_TX4(x)\t\t\t(0x904 + (x) * 0x40)\n+#define MAX96724_MIPI_TX4_DESKEW_PER_2K\t\tFIELD_PREP(GENMASK(2, 0), 0b001)\n+#define MAX96724_MIPI_TX4_DESKEW_PER_AUTO\tBIT(7)\n+\n+#define MAX96724_MIPI_TX10(x)\t\t\t(0x90a + (x) * 0x40)\n+#define MAX96724_MIPI_TX10_CSI2_CPHY_EN\t\tBIT(5)\n+#define MAX96724_MIPI_TX10_CSI2_LANE_CNT\tGENMASK(7, 6)\n+\n+#define MAX96724_MIPI_TX11(p)\t\t\t(0x90b + (p) * 0x40)\n+#define MAX96724_MIPI_TX12(p)\t\t\t(0x90c + (p) * 0x40)\n+\n+#define MAX96724_MIPI_TX13(p, x)\t\t(0x90d + (p) * 0x40 + (x) * 0x2)\n+#define MAX96724_MIPI_TX13_MAP_SRC_DT\t\tGENMASK(5, 0)\n+#define MAX96724_MIPI_TX13_MAP_SRC_VC\t\tGENMASK(7, 6)\n+\n+#define MAX96724_MIPI_TX14(p, x)\t\t(0x90e + (p) * 0x40 + (x) * 0x2)\n+#define MAX96724_MIPI_TX14_MAP_DST_DT\t\tGENMASK(5, 0)\n+#define MAX96724_MIPI_TX14_MAP_DST_VC\t\tGENMASK(7, 6)\n+\n+#define MAX96724_MIPI_TX45(p, x)\t\t(0x92d + (p) * 0x40 + (x) / 4)\n+#define MAX96724_MIPI_TX45_MAP_DPHY_DEST(x)\t(GENMASK(1, 0) << (2 * ((x) % 4)))\n+\n+#define MAX96724_MIPI_TX51(x)\t\t\t(0x933 + (x) * 0x40)\n+#define MAX96724_MIPI_TX51_ALT_MEM_MAP_12\tBIT(0)\n+#define MAX96724_MIPI_TX51_ALT_MEM_MAP_8\tBIT(1)\n+#define MAX96724_MIPI_TX51_ALT_MEM_MAP_10\tBIT(2)\n+#define MAX96724_MIPI_TX51_ALT2_MEM_MAP_8\tBIT(4)\n+\n+#define MAX96724_MIPI_TX54(x)\t\t\t(0x936 + (x) * 0x40)\n+#define MAX96724_MIPI_TX54_TUN_EN\t\tBIT(0)\n+\n+#define MAX96724_MIPI_TX57(x)\t\t\t(0x939 + (x) * 0x40)\n+#define MAX96724_MIPI_TX57_TUN_DEST\t\tGENMASK(5, 4)\n+#define MAX96724_MIPI_TX57_DIS_AUTO_TUN_DET\tBIT(6)\n+#define MAX96724_DET(p)\t\t\t\tBIT(p)\n+\n+#define MAX96724_PATGEN_0\t\t\t0x1050\n+#define MAX96724_PATGEN_0_VTG_MODE\t\tGENMASK(1, 0)\n+#define MAX96724_PATGEN_0_VTG_MODE_FREE_RUNNING\t0b11\n+#define MAX96724_PATGEN_0_DE_INV\t\tBIT(2)\n+#define MAX96724_PATGEN_0_HS_INV\t\tBIT(3)\n+#define MAX96724_PATGEN_0_VS_INV\t\tBIT(4)\n+#define MAX96724_PATGEN_0_GEN_DE\t\tBIT(5)\n+#define MAX96724_PATGEN_0_GEN_HS\t\tBIT(6)\n+#define MAX96724_PATGEN_0_GEN_VS\t\tBIT(7)\n+\n+#define MAX96724_PATGEN_1\t\t\t0x1051\n+#define MAX96724_PATGEN_1_PATGEN_MODE\t\tGENMASK(5, 4)\n+#define MAX96724_PATGEN_1_PATGEN_MODE_DISABLED\t0b00\n+#define MAX96724_PATGEN_1_PATGEN_MODE_CHECKER\t0b01\n+#define MAX96724_PATGEN_1_PATGEN_MODE_GRADIENT\t0b10\n+\n+#define MAX96724_VS_DLY_2\t\t\t0x1052\n+#define MAX96724_VS_HIGH_2\t\t\t0x1055\n+#define MAX96724_VS_LOW_2\t\t\t0x1058\n+#define MAX96724_V2H_2\t\t\t\t0x105b\n+#define MAX96724_HS_HIGH_1\t\t\t0x105e\n+#define MAX96724_HS_LOW_1\t\t\t0x1060\n+#define MAX96724_HS_CNT_1\t\t\t0x1062\n+#define MAX96724_V2D_2\t\t\t\t0x1064\n+#define MAX96724_DE_HIGH_1\t\t\t0x1067\n+#define MAX96724_DE_LOW_1\t\t\t0x1069\n+#define MAX96724_DE_CNT_1\t\t\t0x106b\n+#define MAX96724_GRAD_INCR\t\t\t0x106d\n+#define MAX96724_CHKR_COLOR_A_L\t\t\t0x106e\n+#define MAX96724_CHKR_COLOR_B_L\t\t\t0x1071\n+#define MAX96724_CHKR_RPT_A\t\t\t0x1074\n+#define MAX96724_CHKR_RPT_B\t\t\t0x1075\n+#define MAX96724_CHKR_ALT\t\t\t0x1076\n+\n+#define MAX96724_DE_DET\t\t\t\t0x11f0\n+#define MAX96724_HS_DET\t\t\t\t0x11f1\n+#define MAX96724_VS_DET\t\t\t\t0x11f2\n+#define MAX96724_HS_POL\t\t\t\t0x11f3\n+#define MAX96724_VS_POL\t\t\t\t0x11f4\n+#define MAX96724_DET(p)\t\t\t\tBIT(p)\n+\n+#define MAX96724_DPLL_0(x)\t\t\t(0x1c00 + (x) * 0x100)\n+#define MAX96724_DPLL_0_CONFIG_SOFT_RST_N\tBIT(0)\n+\n+#define MAX96724_PHY1_ALT_CLOCK\t\t\t5\n+\n+static const struct regmap_config max96724_i2c_regmap = {\n+\t.reg_bits = 16,\n+\t.val_bits = 8,\n+\t.max_register = 0x1f00,\n+};\n+\n+struct max96724_priv {\n+\tstruct max_des des;\n+\tconst struct max96724_chip_info *info;\n+\n+\tstruct device *dev;\n+\tstruct i2c_client *client;\n+\tstruct regmap *regmap;\n+\n+\tstruct gpio_desc *gpiod_enable;\n+\tunsigned int cc_port_cfg;\n+};\n+\n+struct max96724_chip_info {\n+\tunsigned int versions;\n+\tunsigned int modes;\n+\tbool supports_pipe_stream_autoselect;\n+\tunsigned int num_pipes;\n+\n+\tint (*set_pipe_phy)(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t struct max_des_phy *phy);\n+\tint (*set_pipe_tunnel_phy)(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t struct max_des_phy *phy);\n+\tint (*set_pipe_tunnel_enable)(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t bool enable);\n+};\n+\n+#define des_to_priv(_des) \\\n+\tcontainer_of(_des, struct max96724_priv, des)\n+\n+static int max96724_wait_for_device(struct max96724_priv *priv)\n+{\n+\tunsigned int val;\n+\tint ret, err;\n+\n+\terr = read_poll_timeout(regmap_read, ret,\n+\t\t\t\t!ret && val,\n+\t\t\t\t100 * USEC_PER_MSEC,\n+\t\t\t\t1 * USEC_PER_SEC, false,\n+\t\t\t\tpriv->regmap, MAX96724_REG0, &val);\n+\tif (err)\n+\t\tdev_err(priv->dev, \"Timeout waiting for deserializer: %d\\n\", ret);\n+\n+\treturn err;\n+}\n+\n+static int max96724_reset(struct max96724_priv *priv)\n+{\n+\tint ret;\n+\n+\tret = max96724_wait_for_device(priv);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_update_bits(priv->regmap, MAX96724_PWR1,\n+\t\t\t\t MAX96724_PWR1_RESET_ALL,\n+\t\t\t\t FIELD_PREP(MAX96724_PWR1_RESET_ALL, 1));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tfsleep(10000);\n+\n+\tret = max96724_wait_for_device(priv);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Restore I2C control-channel access after a reset. */\n+\treturn regmap_update_bits(priv->regmap, MAX96724_REG3,\n+\t\t\t\t MAX96724_REG3_CC_PORT_SEL_MASK,\n+\t\t\t\t priv->cc_port_cfg);\n+}\n+\n+static int __maybe_unused max96724_reg_read(struct max_des *des, unsigned int reg,\n+\t\t\t\t\t unsigned int *val)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_read(priv->regmap, reg, val);\n+}\n+\n+static int __maybe_unused max96724_reg_write(struct max_des *des, unsigned int reg,\n+\t\t\t\t\t unsigned int val)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_write(priv->regmap, reg, val);\n+}\n+\n+static unsigned int max96724_phy_id(struct max_des *des, struct max_des_phy *phy)\n+{\n+\tunsigned int num_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy);\n+\n+\t/* PHY 1 is the master PHY when combining PHY 0 and PHY 1. */\n+\tif (phy->index == 0 && num_hw_data_lanes == 4)\n+\t\treturn 1;\n+\n+\tif (phy->index == 1 && !des->phys[1].enabled)\n+\t\treturn 0;\n+\n+\treturn phy->index;\n+}\n+\n+static int max96724_log_pipe_status(struct max_des *des,\n+\t\t\t\t struct max_des_pipe *pipe)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\tunsigned int val, mask;\n+\tint ret;\n+\n+\tret = regmap_read(priv->regmap, MAX96724_VPRBS(index), &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tvideo_lock: %u\\n\",\n+\t\t !!(val & MAX96724_VPRBS_VIDEO_LOCK));\n+\n+\tmask = MAX96724_DET(index);\n+\n+\tret = regmap_read(priv->regmap, MAX96724_DE_DET, &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tde_det: %u\\n\", !!(val & mask));\n+\n+\tret = regmap_read(priv->regmap, MAX96724_HS_DET, &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\ths_det: %u\\n\", !!(val & mask));\n+\n+\tret = regmap_read(priv->regmap, MAX96724_VS_DET, &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tvs_det: %u\\n\", !!(val & mask));\n+\n+\tret = regmap_read(priv->regmap, MAX96724_HS_POL, &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\ths_pol: %u\\n\", !!(val & mask));\n+\n+\tret = regmap_read(priv->regmap, MAX96724_VS_POL, &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tvs_pol: %u\\n\", !!(val & mask));\n+\n+\treturn 0;\n+}\n+\n+static int max96724_log_phy_status(struct max_des *des,\n+\t\t\t\t struct max_des_phy *phy)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = max96724_phy_id(des, phy);\n+\tunsigned int val;\n+\tint ret;\n+\n+\tret = regmap_read(priv->regmap, MAX96724_MIPI_PHY25(index), &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tcsi2_pkt_cnt: %lu\\n\",\n+\t\t field_get(MAX96724_MIPI_PHY25_CSI2_TX_PKT_CNT(index), val));\n+\n+\tret = regmap_read(priv->regmap, MAX96724_MIPI_PHY27(index), &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tphy_pkt_cnt: %lu\\n\",\n+\t\t field_get(MAX96724_MIPI_PHY27_PHY_PKT_CNT(index), val));\n+\n+\treturn 0;\n+}\n+\n+static int max96724_set_enable(struct max_des *des, bool enable)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX96724_BACKTOP12,\n+\t\t\t\t MAX96724_BACKTOP12_CSI_OUT_EN, enable);\n+}\n+\n+static const unsigned int max96724_phys_configs_reg_val[] = {\n+\tMAX96724_MIPI_PHY0_PHY_1X4A_2X2,\n+\tMAX96724_MIPI_PHY0_PHY_2X4,\n+\n+\tMAX96724_MIPI_PHY0_PHY_4X2,\n+\tMAX96724_MIPI_PHY0_PHY_1X4A_2X2,\n+\tMAX96724_MIPI_PHY0_PHY_1X4B_2X2,\n+\tMAX96724_MIPI_PHY0_PHY_2X4,\n+};\n+\n+static const struct max_serdes_phys_config max96724_phys_configs[] = {\n+\t/*\n+\t * PHY 1 can be in 4-lane mode (combining lanes of PHY 0 and PHY 1)\n+\t * but only use the data lanes of PHY0, while continuing to use the\n+\t * clock lane of PHY 1.\n+\t * Specifying clock-lanes as 5 turns on alternate clocking mode.\n+\t */\n+\t{ { 2, 0, 2, 2 }, { MAX96724_PHY1_ALT_CLOCK, 0, 0, 0 } },\n+\t{ { 2, 0, 4, 0 }, { MAX96724_PHY1_ALT_CLOCK, 0, 0, 0 } },\n+\n+\t/*\n+\t * When combining PHY 0 and PHY 1 to make them function in 4-lane mode,\n+\t * PHY 1 is the master PHY, but we use PHY 0 here to maintain\n+\t * compatibility.\n+\t */\n+\t{ { 2, 2, 2, 2 } },\n+\t{ { 4, 0, 2, 2 } },\n+\t{ { 2, 2, 4, 0 } },\n+\t{ { 4, 0, 4, 0 } },\n+};\n+\n+static int max96724_init_tpg(struct max_des *des)\n+{\n+\tconst struct reg_sequence regs[] = {\n+\t\t{ MAX96724_GRAD_INCR, MAX_SERDES_GRAD_INCR },\n+\t\tREG_SEQUENCE_3_LE(MAX96724_CHKR_COLOR_A_L,\n+\t\t\t\t MAX_SERDES_CHECKER_COLOR_A),\n+\t\tREG_SEQUENCE_3_LE(MAX96724_CHKR_COLOR_B_L,\n+\t\t\t\t MAX_SERDES_CHECKER_COLOR_B),\n+\t\t{ MAX96724_CHKR_RPT_A, MAX_SERDES_CHECKER_SIZE },\n+\t\t{ MAX96724_CHKR_RPT_B, MAX_SERDES_CHECKER_SIZE },\n+\t\t{ MAX96724_CHKR_ALT, MAX_SERDES_CHECKER_SIZE },\n+\t};\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_multi_reg_write(priv->regmap, regs, ARRAY_SIZE(regs));\n+}\n+\n+static int max96724_init(struct max_des *des)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int i;\n+\tint ret;\n+\n+\tif (priv->info->set_pipe_tunnel_enable) {\n+\t\tfor (i = 0; i < des->info->num_pipes; i++) {\n+\t\t\tret = regmap_set_bits(priv->regmap, MAX96724_MIPI_TX57(i),\n+\t\t\t\t\t MAX96724_MIPI_TX57_DIS_AUTO_TUN_DET);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tif (priv->info->supports_pipe_stream_autoselect) {\n+\t\t/* Enable stream autoselect. */\n+\t\tret = regmap_set_bits(priv->regmap, MAX96724_VIDEO_PIPE_EN,\n+\t\t\t\t MAX96724_VIDEO_PIPE_EN_STREAM_SEL_ALL);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\t/* Enable I2C control ports crossover. */\n+\tret = regmap_set_bits(priv->regmap, MAX96724_REG7,\n+\t\t\t MAX96724_REG7_CC_CROSSOVER_SEL);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Set PHY mode. */\n+\tret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY0,\n+\t\t\t\t MAX96724_MIPI_PHY0_PHY_CONFIG,\n+\t\t\t\t max96724_phys_configs_reg_val[des->phys_config]);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn max96724_init_tpg(des);\n+}\n+\n+static int max96724_init_phy(struct max_des *des, struct max_des_phy *phy)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tbool is_cphy = phy->bus_type == V4L2_MBUS_CSI2_CPHY;\n+\tunsigned int num_data_lanes = phy->mipi.num_data_lanes;\n+\tunsigned int dpll_freq = is_cphy ? phy->link_frequency\n+\t\t\t\t\t : phy->link_frequency * 2;\n+\tunsigned int num_hw_data_lanes;\n+\tunsigned int index;\n+\tunsigned int used_data_lanes = 0;\n+\tunsigned int val, mask;\n+\tunsigned int i;\n+\tint ret;\n+\n+\tindex = max96724_phy_id(des, phy);\n+\tnum_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy);\n+\n+\tret = regmap_update_bits(priv->regmap, MAX96724_MIPI_TX10(index),\n+\t\t\t\t MAX96724_MIPI_TX10_CSI2_LANE_CNT,\n+\t\t\t\t FIELD_PREP(MAX96724_MIPI_TX10_CSI2_LANE_CNT,\n+\t\t\t\t\t num_data_lanes - 1));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX10(index),\n+\t\t\t\t MAX96724_MIPI_TX10_CSI2_CPHY_EN, is_cphy);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Configure lane mapping. */\n+\tval = 0;\n+\tfor (i = 0; i < num_hw_data_lanes ; i++) {\n+\t\tunsigned int map;\n+\n+\t\tif (i < num_data_lanes)\n+\t\t\tmap = phy->mipi.data_lanes[i] - 1;\n+\t\telse\n+\t\t\tmap = ffz(used_data_lanes);\n+\n+\t\tval |= map << (i * 2);\n+\t\tused_data_lanes |= BIT(map);\n+\t}\n+\n+\tif (num_hw_data_lanes == 4)\n+\t\tmask = MAX96724_MIPI_PHY3_PHY_LANE_MAP_4;\n+\telse\n+\t\tmask = MAX96724_MIPI_PHY3_PHY_LANE_MAP_2(index);\n+\n+\tret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY3(index),\n+\t\t\t\t mask, field_prep(mask, val));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Configure lane polarity. */\n+\tfor (i = 0, val = 0; i < num_data_lanes; i++)\n+\t\tif (phy->mipi.lane_polarities[i + 1])\n+\t\t\tval |= BIT(i);\n+\n+\tif (num_hw_data_lanes == 4) {\n+\t\tret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY5(index),\n+\t\t\t\t\t MAX96724_MIPI_PHY5_PHY_POL_MAP_4_0_1 |\n+\t\t\t\t\t MAX96724_MIPI_PHY5_PHY_POL_MAP_4_2_3,\n+\t\t\t\t\t FIELD_PREP(MAX96724_MIPI_PHY5_PHY_POL_MAP_4_0_1,\n+\t\t\t\t\t\t val) |\n+\t\t\t\t\t FIELD_PREP(MAX96724_MIPI_PHY5_PHY_POL_MAP_4_2_3,\n+\t\t\t\t\t\t val >> 2));\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_PHY5(index),\n+\t\t\t\t\t MAX96724_MIPI_PHY5_PHY_POL_MAP_4_CLK,\n+\t\t\t\t\t phy->mipi.lane_polarities[0]);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t} else {\n+\t\tret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY5(index),\n+\t\t\t\t\t MAX96724_MIPI_PHY5_PHY_POL_MAP_2(index),\n+\t\t\t\t\t field_prep(MAX96724_MIPI_PHY5_PHY_POL_MAP_2(index), val));\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_PHY5(index),\n+\t\t\t\t\t MAX96724_MIPI_PHY5_PHY_POL_MAP_2_CLK(index),\n+\t\t\t\t\t phy->mipi.lane_polarities[0]);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tif (!is_cphy && dpll_freq > 1500000000ull) {\n+\t\t/* Enable initial deskew with 2 x 32k UI. */\n+\t\tret = regmap_write(priv->regmap, MAX96724_MIPI_TX3(index),\n+\t\t\t\t MAX96724_MIPI_TX3_DESKEW_INIT_AUTO |\n+\t\t\t\t MAX96724_MIPI_TX3_DESKEW_INIT_8X32K);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\t/* Enable periodic deskew with 2 x 1k UI.. */\n+\t\tret = regmap_write(priv->regmap, MAX96724_MIPI_TX4(index),\n+\t\t\t\t MAX96724_MIPI_TX4_DESKEW_PER_AUTO |\n+\t\t\t\t MAX96724_MIPI_TX4_DESKEW_PER_2K);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t} else {\n+\t\t/* Disable initial deskew. */\n+\t\tret = regmap_write(priv->regmap, MAX96724_MIPI_TX3(index), 0x0);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\t/* Disable periodic deskew. */\n+\t\tret = regmap_write(priv->regmap, MAX96724_MIPI_TX4(index), 0x0);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tif (is_cphy) {\n+\t\t/* Configure C-PHY timings. */\n+\t\tret = regmap_write(priv->regmap, MAX96724_MIPI_PHY13,\n+\t\t\t\t MAX96724_MIPI_PHY13_T_T3_PREBEGIN_64X7);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tret = regmap_write(priv->regmap, MAX96724_MIPI_PHY14,\n+\t\t\t\t MAX96724_MIPI_PHY14_T_T3_PREP_55NS |\n+\t\t\t\t MAX96724_MIPI_PHY14_T_T3_POST_32X7);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\t/* Put DPLL block into reset. */\n+\tret = regmap_clear_bits(priv->regmap, MAX96724_DPLL_0(index),\n+\t\t\t\tMAX96724_DPLL_0_CONFIG_SOFT_RST_N);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Set DPLL frequency. */\n+\tret = regmap_update_bits(priv->regmap, MAX96724_BACKTOP22(index),\n+\t\t\t\t MAX96724_BACKTOP22_PHY_CSI_TX_DPLL,\n+\t\t\t\t FIELD_PREP(MAX96724_BACKTOP22_PHY_CSI_TX_DPLL,\n+\t\t\t\t\t div_u64(dpll_freq, 100000000)));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Enable DPLL frequency. */\n+\tret = regmap_set_bits(priv->regmap, MAX96724_BACKTOP22(index),\n+\t\t\t MAX96724_BACKTOP22_PHY_CSI_TX_DPLL_EN);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Pull DPLL block out of reset. */\n+\treturn regmap_set_bits(priv->regmap, MAX96724_DPLL_0(index),\n+\t\t\t MAX96724_DPLL_0_CONFIG_SOFT_RST_N);\n+}\n+\n+static int max96724_set_phy_mode(struct max_des *des, struct max_des_phy *phy,\n+\t\t\t\t struct max_des_phy_mode *mode)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = max96724_phy_id(des, phy);\n+\tint ret;\n+\n+\t/* Set alternate memory map modes. */\n+\tret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index),\n+\t\t\t\t MAX96724_MIPI_TX51_ALT_MEM_MAP_12,\n+\t\t\t\t mode->alt_mem_map12);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index),\n+\t\t\t\t MAX96724_MIPI_TX51_ALT_MEM_MAP_8,\n+\t\t\t\t mode->alt_mem_map8);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index),\n+\t\t\t\t MAX96724_MIPI_TX51_ALT_MEM_MAP_10,\n+\t\t\t\t mode->alt_mem_map10);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index),\n+\t\t\t\t MAX96724_MIPI_TX51_ALT2_MEM_MAP_8,\n+\t\t\t\t mode->alt2_mem_map8);\n+}\n+\n+static int max96724_set_phy_enable(struct max_des *des, struct max_des_phy *phy,\n+\t\t\t\t bool enable)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = max96724_phy_id(des, phy);\n+\tunsigned int num_hw_data_lanes;\n+\tunsigned int mask;\n+\n+\tnum_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy);\n+\n+\tif (num_hw_data_lanes == 4)\n+\t\t/* PHY 1 -> bits [1:0] */\n+\t\t/* PHY 2 -> bits [3:2] */\n+\t\tmask = MAX96724_MIPI_PHY2_PHY_STDB_N_4(index);\n+\telse\n+\t\tmask = MAX96724_MIPI_PHY2_PHY_STDB_N_2(index);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX96724_MIPI_PHY2, mask, enable);\n+}\n+\n+static int max96724_set_pipe_remap(struct max_des *des,\n+\t\t\t\t struct max_des_pipe *pipe,\n+\t\t\t\t unsigned int i,\n+\t\t\t\t struct max_des_remap *remap)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tstruct max_des_phy *phy = &des->phys[remap->phy];\n+\tunsigned int phy_id = max96724_phy_id(des, phy);\n+\tunsigned int index = pipe->index;\n+\tint ret;\n+\n+\t/* Set source Data Type and Virtual Channel. */\n+\t/* TODO: implement extended Virtual Channel. */\n+\tret = regmap_write(priv->regmap, MAX96724_MIPI_TX13(index, i),\n+\t\t\t FIELD_PREP(MAX96724_MIPI_TX13_MAP_SRC_DT,\n+\t\t\t\t remap->from_dt) |\n+\t\t\t FIELD_PREP(MAX96724_MIPI_TX13_MAP_SRC_VC,\n+\t\t\t\t remap->from_vc));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Set destination Data Type and Virtual Channel. */\n+\t/* TODO: implement extended Virtual Channel. */\n+\tret = regmap_write(priv->regmap, MAX96724_MIPI_TX14(index, i),\n+\t\t\t FIELD_PREP(MAX96724_MIPI_TX14_MAP_DST_DT,\n+\t\t\t\t remap->to_dt) |\n+\t\t\t FIELD_PREP(MAX96724_MIPI_TX14_MAP_DST_VC,\n+\t\t\t\t remap->to_vc));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Set destination PHY. */\n+\treturn regmap_update_bits(priv->regmap, MAX96724_MIPI_TX45(index, i),\n+\t\t\t\t MAX96724_MIPI_TX45_MAP_DPHY_DEST(i),\n+\t\t\t\t field_prep(MAX96724_MIPI_TX45_MAP_DPHY_DEST(i),\n+\t\t\t\t\t phy_id));\n+}\n+\n+static int max96724_set_pipe_remaps_enable(struct max_des *des,\n+\t\t\t\t\t struct max_des_pipe *pipe,\n+\t\t\t\t\t unsigned int mask)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\tint ret;\n+\n+\tret = regmap_write(priv->regmap, MAX96724_MIPI_TX11(index), mask);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_write(priv->regmap, MAX96724_MIPI_TX12(index), mask >> 8);\n+}\n+\n+static int max96724_set_pipe_tunnel_phy(struct max_des *des,\n+\t\t\t\t\tstruct max_des_pipe *pipe,\n+\t\t\t\t\tstruct max_des_phy *phy)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int phy_index = max96724_phy_id(des, phy);\n+\n+\treturn regmap_update_bits(priv->regmap, MAX96724_MIPI_TX57(pipe->index),\n+\t\t\t\t MAX96724_MIPI_TX57_TUN_DEST,\n+\t\t\t\t FIELD_PREP(MAX96724_MIPI_TX57_TUN_DEST,\n+\t\t\t\t\t phy_index));\n+}\n+\n+static int max96724_set_pipe_phy(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t struct max_des_phy *phy)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int phy_index = max96724_phy_id(des, phy);\n+\n+\treturn regmap_update_bits(priv->regmap, MAX96724_MIPI_CTRL_SEL,\n+\t\t\t\t MAX96724_MIPI_CTRL_SEL_MASK(pipe->index),\n+\t\t\t\t field_prep(MAX96724_MIPI_CTRL_SEL_MASK(pipe->index),\n+\t\t\t\t\t phy_index));\n+}\n+\n+static int max96724_set_pipe_enable(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t bool enable)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX96724_VIDEO_PIPE_EN,\n+\t\t\t\t MAX96724_VIDEO_PIPE_EN_MASK(index), enable);\n+}\n+\n+static int max96724_set_pipe_stream_id(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t unsigned int stream_id)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\n+\treturn regmap_update_bits(priv->regmap, MAX96724_VIDEO_PIPE_SEL(index),\n+\t\t\t\t MAX96724_VIDEO_PIPE_SEL_STREAM(index),\n+\t\t\t\t field_prep(MAX96724_VIDEO_PIPE_SEL_STREAM(index),\n+\t\t\t\t\t stream_id));\n+}\n+\n+static int max96724_set_pipe_link(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t struct max_des_link *link)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\n+\treturn regmap_update_bits(priv->regmap, MAX96724_VIDEO_PIPE_SEL(index),\n+\t\t\t\t MAX96724_VIDEO_PIPE_SEL_LINK(index),\n+\t\t\t\t field_prep(MAX96724_VIDEO_PIPE_SEL_LINK(index),\n+\t\t\t\t\t link->index));\n+}\n+\n+static int max96724_set_pipe_mode(struct max_des *des,\n+\t\t\t\t struct max_des_pipe *pipe,\n+\t\t\t\t struct max_des_pipe_mode *mode)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\tunsigned int reg, mask, mode_mask;\n+\tint ret;\n+\n+\t/* Set 8bit double mode. */\n+\tret = regmap_assign_bits(priv->regmap, MAX96724_BACKTOP21(index),\n+\t\t\t\t MAX96724_BACKTOP21_BPP8DBL(index), mode->dbl8);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX96724_BACKTOP24(index),\n+\t\t\t\t MAX96724_BACKTOP24_BPP8DBL_MODE(index),\n+\t\t\t\t mode->dbl8mode);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Set 10bit double mode. */\n+\tif (index % 4 == 3) {\n+\t\treg = MAX96724_BACKTOP30(index);\n+\t\tmask = MAX96724_BACKTOP30_BPP10DBL3;\n+\t\tmode_mask = MAX96724_BACKTOP30_BPP10DBL3_MODE;\n+\t} else if (index % 4 == 2) {\n+\t\treg = MAX96724_BACKTOP31(index);\n+\t\tmask = MAX96724_BACKTOP31_BPP10DBL2;\n+\t\tmode_mask = MAX96724_BACKTOP31_BPP10DBL2_MODE;\n+\t} else if (index % 4 == 1) {\n+\t\treg = MAX96724_BACKTOP32(index);\n+\t\tmask = MAX96724_BACKTOP32_BPP10DBL1;\n+\t\tmode_mask = MAX96724_BACKTOP32_BPP10DBL1_MODE;\n+\t} else {\n+\t\treg = MAX96724_BACKTOP32(index);\n+\t\tmask = MAX96724_BACKTOP32_BPP10DBL0;\n+\t\tmode_mask = MAX96724_BACKTOP32_BPP10DBL0_MODE;\n+\t}\n+\n+\tret = regmap_assign_bits(priv->regmap, reg, mask, mode->dbl10);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, reg, mode_mask, mode->dbl10mode);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Set 12bit double mode. */\n+\treturn regmap_assign_bits(priv->regmap, MAX96724_BACKTOP32(index),\n+\t\t\t\t MAX96724_BACKTOP32_BPP12(index), mode->dbl12);\n+}\n+\n+static int max96724_set_pipe_tunnel_enable(struct max_des *des,\n+\t\t\t\t\t struct max_des_pipe *pipe, bool enable)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX54(pipe->index),\n+\t\t\t\t MAX96724_MIPI_TX54_TUN_EN, enable);\n+}\n+\n+static int max96724_select_links(struct max_des *des, unsigned int mask)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int val = 0;\n+\tunsigned int i;\n+\tint ret;\n+\n+\tfor (i = 0; i < des->info->num_links; i++) {\n+\t\tif (!(mask & BIT(i)))\n+\t\t\tval |= MAX96724_REG3_CC_PORT_SEL(i);\n+\t}\n+\n+\tret = regmap_write(priv->regmap, MAX96724_REG3, val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_update_bits(priv->regmap, MAX96724_REG6, MAX96724_REG6_LINK_EN,\n+\t\t\t\t field_prep(MAX96724_REG6_LINK_EN, mask));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_set_bits(priv->regmap, MAX96724_CTRL1,\n+\t\t\t MAX96724_CTRL1_RESET_ONESHOT);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmsleep(60);\n+\n+\treturn 0;\n+}\n+\n+static int max96724_set_link_version(struct max_des *des,\n+\t\t\t\t struct max_des_link *link,\n+\t\t\t\t enum max_serdes_gmsl_version version)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tunsigned int index = link->index;\n+\tunsigned int val;\n+\n+\tif (version == MAX_SERDES_GMSL_2_6GBPS)\n+\t\tval = MAX96724_REG26_RX_RATE_6GBPS;\n+\telse\n+\t\tval = MAX96724_REG26_RX_RATE_3GBPS;\n+\n+\treturn regmap_update_bits(priv->regmap, MAX96724_REG26(index),\n+\t\t\t\t MAX96724_REG26_RX_RATE_PHY(index),\n+\t\t\t\t field_prep(MAX96724_REG26_RX_RATE_PHY(index), val));\n+}\n+\n+static int max96724_set_tpg_timings(struct max96724_priv *priv,\n+\t\t\t\t const struct max_serdes_tpg_timings *tm)\n+{\n+\tconst struct reg_sequence regs[] = {\n+\t\tREG_SEQUENCE_3(MAX96724_VS_DLY_2, tm->vs_dly),\n+\t\tREG_SEQUENCE_3(MAX96724_VS_HIGH_2, tm->vs_high),\n+\t\tREG_SEQUENCE_3(MAX96724_VS_LOW_2, tm->vs_low),\n+\t\tREG_SEQUENCE_3(MAX96724_V2H_2, tm->v2h),\n+\t\tREG_SEQUENCE_2(MAX96724_HS_HIGH_1, tm->hs_high),\n+\t\tREG_SEQUENCE_2(MAX96724_HS_LOW_1, tm->hs_low),\n+\t\tREG_SEQUENCE_2(MAX96724_HS_CNT_1, tm->hs_cnt),\n+\t\tREG_SEQUENCE_3(MAX96724_V2D_2, tm->v2d),\n+\t\tREG_SEQUENCE_2(MAX96724_DE_HIGH_1, tm->de_high),\n+\t\tREG_SEQUENCE_2(MAX96724_DE_LOW_1, tm->de_low),\n+\t\tREG_SEQUENCE_2(MAX96724_DE_CNT_1, tm->de_cnt),\n+\t};\n+\tint ret;\n+\n+\tret = regmap_multi_reg_write(priv->regmap, regs, ARRAY_SIZE(regs));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_write(priv->regmap, MAX96724_PATGEN_0,\n+\t\t\t FIELD_PREP(MAX96724_PATGEN_0_VTG_MODE,\n+\t\t\t\t MAX96724_PATGEN_0_VTG_MODE_FREE_RUNNING) |\n+\t\t\t FIELD_PREP(MAX96724_PATGEN_0_DE_INV, tm->de_inv) |\n+\t\t\t FIELD_PREP(MAX96724_PATGEN_0_HS_INV, tm->hs_inv) |\n+\t\t\t FIELD_PREP(MAX96724_PATGEN_0_VS_INV, tm->vs_inv) |\n+\t\t\t FIELD_PREP(MAX96724_PATGEN_0_GEN_DE, tm->gen_de) |\n+\t\t\t FIELD_PREP(MAX96724_PATGEN_0_GEN_HS, tm->gen_hs) |\n+\t\t\t FIELD_PREP(MAX96724_PATGEN_0_GEN_VS, tm->gen_vs));\n+}\n+\n+static int max96724_set_tpg_clk(struct max96724_priv *priv, u32 clock)\n+{\n+\tbool patgen_clk_src = 0;\n+\tu8 pclk_src;\n+\tint ret;\n+\n+\tswitch (clock) {\n+\tcase 25000000:\n+\t\tpclk_src = MAX96724_DEBUG_EXTRA_PCLK_SRC_25MHZ;\n+\t\tbreak;\n+\tcase 75000000:\n+\t\tpclk_src = MAX96724_DEBUG_EXTRA_PCLK_SRC_75MHZ;\n+\t\tbreak;\n+\tcase 150000000:\n+\t\tpclk_src = MAX96724_DEBUG_EXTRA_PCLK_SRC_USE_PIPE;\n+\t\tpatgen_clk_src = MAX96724_VPRBS_PATGEN_CLK_SRC_150MHZ;\n+\t\tbreak;\n+\tcase 375000000:\n+\t\tpclk_src = MAX96724_DEBUG_EXTRA_PCLK_SRC_USE_PIPE;\n+\t\tpatgen_clk_src = MAX96724_VPRBS_PATGEN_CLK_SRC_375MHZ;\n+\t\tbreak;\n+\tcase 0:\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/*\n+\t * TPG data is always injected on link 0, which is always routed to\n+\t * pipe 0.\n+\t */\n+\tret = regmap_update_bits(priv->regmap, MAX96724_VPRBS(0),\n+\t\t\t\t MAX96724_VPRBS_PATGEN_CLK_SRC,\n+\t\t\t\t FIELD_PREP(MAX96724_VPRBS_PATGEN_CLK_SRC,\n+\t\t\t\t\t patgen_clk_src));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_update_bits(priv->regmap, MAX96724_DEBUG_EXTRA,\n+\t\t\t\t MAX96724_DEBUG_EXTRA_PCLK_SRC,\n+\t\t\t\t FIELD_PREP(MAX96724_DEBUG_EXTRA_PCLK_SRC,\n+\t\t\t\t\t pclk_src));\n+}\n+\n+static int max96724_set_tpg_mode(struct max96724_priv *priv, bool enable)\n+{\n+\tunsigned int patgen_mode;\n+\n+\tswitch (priv->des.tpg_pattern) {\n+\tcase MAX_SERDES_TPG_PATTERN_GRADIENT:\n+\t\tpatgen_mode = MAX96724_PATGEN_1_PATGEN_MODE_GRADIENT;\n+\t\tbreak;\n+\tcase MAX_SERDES_TPG_PATTERN_CHECKERBOARD:\n+\t\tpatgen_mode = MAX96724_PATGEN_1_PATGEN_MODE_CHECKER;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn regmap_update_bits(priv->regmap, MAX96724_PATGEN_1,\n+\t\t\t\t MAX96724_PATGEN_1_PATGEN_MODE,\n+\t\t\t\t FIELD_PREP(MAX96724_PATGEN_1_PATGEN_MODE,\n+\t\t\t\t\t enable ? patgen_mode\n+\t\t\t\t\t\t : MAX96724_PATGEN_1_PATGEN_MODE_DISABLED));\n+}\n+\n+static int max96724_set_tpg(struct max_des *des,\n+\t\t\t const struct max_serdes_tpg_entry *entry)\n+{\n+\tstruct max96724_priv *priv = des_to_priv(des);\n+\tstruct max_serdes_tpg_timings timings = { 0 };\n+\tint ret;\n+\n+\tret = max_serdes_get_tpg_timings(entry, &timings);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = max96724_set_tpg_timings(priv, &timings);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = max96724_set_tpg_clk(priv, timings.clock);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = max96724_set_tpg_mode(priv, entry);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX96724_MIPI_PHY0,\n+\t\t\t\t MAX96724_MIPI_PHY0_FORCE_CSI_OUT_EN, !!entry);\n+}\n+\n+static const struct max_serdes_tpg_entry max96724_tpg_entries[] = {\n+\tMAX_TPG_ENTRY_640X480P60_RGB888,\n+\tMAX_TPG_ENTRY_1920X1080P30_RGB888,\n+\tMAX_TPG_ENTRY_1920X1080P60_RGB888,\n+};\n+\n+static const struct max_des_info max96724_des_info = {\n+\t.num_phys = 4,\n+\t.num_links = 4,\n+\t.num_remaps_per_pipe = 16,\n+\t.phys_configs = {\n+\t\t.num_configs = ARRAY_SIZE(max96724_phys_configs),\n+\t\t.configs = max96724_phys_configs,\n+\t},\n+\t.tpg_entries = {\n+\t\t.num_entries = ARRAY_SIZE(max96724_tpg_entries),\n+\t\t.entries = max96724_tpg_entries,\n+\t},\n+\t.tpg_mode = MAX_SERDES_GMSL_PIXEL_MODE,\n+\t.tpg_patterns = BIT(MAX_SERDES_TPG_PATTERN_CHECKERBOARD) |\n+\t\t\tBIT(MAX_SERDES_TPG_PATTERN_GRADIENT),\n+\t.use_atr = true,\n+};\n+\n+static const struct max_des_ops max96724_des_ops = {\n+#ifdef CONFIG_VIDEO_ADV_DEBUG\n+\t.reg_read = max96724_reg_read,\n+\t.reg_write = max96724_reg_write,\n+#endif\n+\t.log_pipe_status = max96724_log_pipe_status,\n+\t.log_phy_status = max96724_log_phy_status,\n+\t.set_enable = max96724_set_enable,\n+\t.init = max96724_init,\n+\t.init_phy = max96724_init_phy,\n+\t.set_phy_mode = max96724_set_phy_mode,\n+\t.set_phy_enable = max96724_set_phy_enable,\n+\t.set_pipe_stream_id = max96724_set_pipe_stream_id,\n+\t.set_pipe_link = max96724_set_pipe_link,\n+\t.set_pipe_enable = max96724_set_pipe_enable,\n+\t.set_pipe_remap = max96724_set_pipe_remap,\n+\t.set_pipe_remaps_enable = max96724_set_pipe_remaps_enable,\n+\t.set_pipe_mode = max96724_set_pipe_mode,\n+\t.set_tpg = max96724_set_tpg,\n+\t.select_links = max96724_select_links,\n+\t.set_link_version = max96724_set_link_version,\n+};\n+\n+static const struct max96724_chip_info max96724_info = {\n+\t.versions = BIT(MAX_SERDES_GMSL_2_3GBPS) |\n+\t\t BIT(MAX_SERDES_GMSL_2_6GBPS),\n+\t.modes = BIT(MAX_SERDES_GMSL_PIXEL_MODE) |\n+\t\t BIT(MAX_SERDES_GMSL_TUNNEL_MODE),\n+\t.set_pipe_tunnel_enable = max96724_set_pipe_tunnel_enable,\n+\t.set_pipe_phy = max96724_set_pipe_phy,\n+\t.set_pipe_tunnel_phy = max96724_set_pipe_tunnel_phy,\n+\t.supports_pipe_stream_autoselect = true,\n+\t.num_pipes = 4,\n+};\n+\n+static const struct max96724_chip_info max96724f_info = {\n+\t.versions = BIT(MAX_SERDES_GMSL_2_3GBPS),\n+\t.modes = BIT(MAX_SERDES_GMSL_PIXEL_MODE) |\n+\t\t BIT(MAX_SERDES_GMSL_TUNNEL_MODE),\n+\t.set_pipe_tunnel_enable = max96724_set_pipe_tunnel_enable,\n+\t.set_pipe_phy = max96724_set_pipe_phy,\n+\t.set_pipe_tunnel_phy = max96724_set_pipe_tunnel_phy,\n+\t.supports_pipe_stream_autoselect = true,\n+\t.num_pipes = 4,\n+};\n+\n+static const struct max96724_chip_info max96712_info = {\n+\t.versions = BIT(MAX_SERDES_GMSL_2_3GBPS) |\n+\t\t BIT(MAX_SERDES_GMSL_2_6GBPS),\n+\t.modes = BIT(MAX_SERDES_GMSL_PIXEL_MODE),\n+\t.num_pipes = 8,\n+};\n+\n+static int max96724_probe(struct i2c_client *client)\n+{\n+\tstruct device *dev = &client->dev;\n+\tstruct max96724_priv *priv;\n+\tstruct max_des_info *info;\n+\tstruct max_des_ops *ops;\n+\tu32 cc_port;\n+\tint ret;\n+\n+\tpriv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);\n+\tif (!priv)\n+\t\treturn -ENOMEM;\n+\n+\tinfo = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);\n+\tif (!info)\n+\t\treturn -ENOMEM;\n+\n+\tops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL);\n+\tif (!ops)\n+\t\treturn -ENOMEM;\n+\n+\tpriv->info = device_get_match_data(dev);\n+\tif (!priv->info) {\n+\t\tdev_err(dev, \"Failed to get match data\\n\");\n+\t\treturn -ENODEV;\n+\t}\n+\n+\tpriv->dev = dev;\n+\tpriv->client = client;\n+\ti2c_set_clientdata(client, priv);\n+\n+\tpriv->regmap = devm_regmap_init_i2c(client, &max96724_i2c_regmap);\n+\tif (IS_ERR(priv->regmap))\n+\t\treturn PTR_ERR(priv->regmap);\n+\n+\tpriv->gpiod_enable = devm_gpiod_get_optional(&client->dev, \"enable\",\n+\t\t\t\t\t\t GPIOD_OUT_LOW);\n+\tif (IS_ERR(priv->gpiod_enable))\n+\t\treturn PTR_ERR(priv->gpiod_enable);\n+\n+\tif (priv->gpiod_enable) {\n+\t\t/* PWDN must be held for 1us for reset */\n+\t\tudelay(1);\n+\n+\t\tgpiod_set_value_cansleep(priv->gpiod_enable, 1);\n+\n+\t\t/* Maximum power-up time (tLOCK) 4ms */\n+\t\tusleep_range(4000, 5000);\n+\t}\n+\n+\tpriv->cc_port_cfg = MAX96724_REG3_CC_PORT_CFG_PORT0;\n+\n+\tret = device_property_read_u32(dev, \"maxim,control-channel-port\",\n+\t\t\t\t &cc_port);\n+\tif (!ret) {\n+\t\tswitch (cc_port) {\n+\t\tcase 0:\n+\t\t\tpriv->cc_port_cfg = MAX96724_REG3_CC_PORT_CFG_PORT0;\n+\t\t\tbreak;\n+\t\tcase 1:\n+\t\t\tpriv->cc_port_cfg = MAX96724_REG3_CC_PORT_CFG_PORT1;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tdev_err(dev, \"Invalid control-channel port %u\\n\", cc_port);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\t} else if (ret != -ENODATA && ret != -ENOENT && ret != -EINVAL) {\n+\t\treturn ret;\n+\t}\n+\n+\t*info = max96724_des_info;\n+\tinfo->versions = priv->info->versions;\n+\tinfo->modes = priv->info->modes;\n+\tinfo->num_pipes = priv->info->num_pipes;\n+\tpriv->des.info = info;\n+\n+\t*ops = max96724_des_ops;\n+\tops->set_pipe_tunnel_enable = priv->info->set_pipe_tunnel_enable;\n+\tops->set_pipe_phy = priv->info->set_pipe_phy;\n+\tops->set_pipe_tunnel_phy = priv->info->set_pipe_tunnel_phy;\n+\tpriv->des.ops = ops;\n+\n+\tret = max96724_reset(priv);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn max_des_probe(client, &priv->des);\n+}\n+\n+static void max96724_remove(struct i2c_client *client)\n+{\n+\tstruct max96724_priv *priv = i2c_get_clientdata(client);\n+\n+\tmax_des_remove(&priv->des);\n+\n+\tgpiod_set_value_cansleep(priv->gpiod_enable, 0);\n+}\n+\n+static const struct of_device_id max96724_of_table[] = {\n+\t{ .compatible = \"maxim,max96712\", .data = &max96712_info },\n+\t{ .compatible = \"maxim,max96724\", .data = &max96724_info },\n+\t{ .compatible = \"maxim,max96724f\", .data = &max96724f_info },\n+\t{ .compatible = \"maxim,max96724r\", .data = &max96724f_info },\n+\t{ },\n+};\n+MODULE_DEVICE_TABLE(of, max96724_of_table);\n+\n+static struct i2c_driver max96724_i2c_driver = {\n+\t.driver\t= {\n+\t\t.name = \"max96724\",\n+\t\t.of_match_table\t= max96724_of_table,\n+\t},\n+\t.probe = max96724_probe,\n+\t.remove = max96724_remove,\n+};\n+\n+module_i2c_driver(max96724_i2c_driver);\n+\n+MODULE_IMPORT_NS(\"MAX_SERDES\");\n+MODULE_DESCRIPTION(\"Maxim MAX96724 Quad GMSL2 Deserializer Driver\");\n+MODULE_AUTHOR(\"Cosmin Tanislav <cosmin.tanislav@analog.com>\");\n+MODULE_LICENSE(\"GPL\");\n", "prefixes": [ "v10", "17/22" ] }