get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2220312,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2220312/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-gpio/patch/20260406-gmsl2-3_serdes-v10-18-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-18-645560fedca5@analog.com>",
    "date": "2026-04-06T20:14:57",
    "name": "[v10,18/22] media: i2c: maxim-serdes: add MAX9296A driver",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "aa294038ac2c4b3786ef1863109304572348f2ac",
    "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-18-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/2220312/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2220312/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "\n <linux-gpio+bounces-34744-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=PcWJOm6I;\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-34744-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=\"PcWJOm6I\"",
            "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 4fqLNX2gMDz1yFt\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 07 Apr 2026 06:22:36 +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 30DEF306628E\n\tfor <incoming@patchwork.ozlabs.org>; Mon,  6 Apr 2026 20:16:39 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 0462B3A5E8C;\n\tMon,  6 Apr 2026 20:15:25 +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 C32EC3A0B3B;\n\tMon,  6 Apr 2026 20:15:22 +0000 (UTC)",
            "by smtp.kernel.org (Postfix) with ESMTPS id A784DC2BCB1;\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 9E1AAFB5161;\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=JYmxWSJYpxzvJwMTKct5dHUenExEjb7TfMxQLGjOr7IVdTtCQC58lQdMZytvUK2tU0Dy5t/zBWMYk4/ArGML0CIRGDxO+74/04QdKF6eR554y6CeQHEWtgkPoNwuTGOZo65iOKtP4w3qyK3ZKrBTmJbMYqrNdtXc60StbVxa7W8=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775506522; c=relaxed/simple;\n\tbh=33yrHc9Ffob7NeIPSf016o2sZDkf6XAOhETUbUDDSX4=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=Lh9Tn4p1GVxMTdtbmlb3fCXh/fs2+Ng+TAHuz93xmZ50XfcZo7hN76DwxVu93a8AZCu90dqKXaVTDuhHMkOsiuvwDoCS5HsYasXb1ufixA4ZetLgLHCB5BmbnX+h3tj7iXa9JiGtfJXWGBOa1b0L8lkBUqJCSWiuQken+dXfXso=",
        "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=PcWJOm6I; 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=33yrHc9Ffob7NeIPSf016o2sZDkf6XAOhETUbUDDSX4=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From;\n\tb=PcWJOm6IYDsK6PiAd5pp2r+edF86R9bnd5lna4yFGn89ORoZSpZsOIaZOMv4bOMch\n\t 3JYunjqGYq6qUrMGhhJyrp7H19fzb8fbJpoKu0FihADvB53Lw72/xBk987oE5jC9Vt\n\t FnpiJ5uSZC2emJQflOGnRTt6OvUe9TkVehNhIskygHO6CVuM+EqwJ3dwQV8eMrsoUs\n\t ONtqboZHDcU2jjOBZHoqyjQuqbiu72zJrfiM+FPx2KvQUzeOM40O5Z8WzqffF/3mmT\n\t a0A1fY354srlXQ2KlvjyDctjLxIBdCabyJVeUnzgZKor8MTM7I80kwTn+7DBPfxWDZ\n\t JHMPJkxL+w5NA==",
        "From": "Dumitru Ceclan via B4 Relay\n <devnull+dumitru.ceclan.analog.com@kernel.org>",
        "Date": "Mon, 06 Apr 2026 23:14:57 +0300",
        "Subject": "[PATCH v10 18/22] media: i2c: maxim-serdes: add MAX9296A 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": "7bit",
        "Message-Id": "<20260406-gmsl2-3_serdes-v10-18-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>",
        "X-Mailer": "b4 0.14.3",
        "X-Developer-Signature": "v=1; a=ed25519-sha256; t=1775506518; l=44177;\n i=dumitru.ceclan@analog.com; s=20240313; h=from:subject:message-id;\n bh=5FMSWyPfilmttjT8dgfIqiBjoRFqLIk4yV8cf/AXT50=;\n b=E/WFMK+MhzZCNTzXrYmYJmXVk37zVRrfogJkHo5xeLUqhJUVNrQAehKFUYl0d/h/di7Yqtj7O\n QoFPbnbEPNQABjz1Z7yFIfRXeOUKQIVJYVXnFBQCxUZ2yNq7e6F0VCz",
        "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 MAX9296A driver that also supports MAX96714, MAX96714F,\nMAX96714R, MAX96716A and MAX96792A.\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>\n---\n drivers/media/i2c/maxim-serdes/Kconfig    |   13 +\n drivers/media/i2c/maxim-serdes/Makefile   |    1 +\n drivers/media/i2c/maxim-serdes/max9296a.c | 1358 +++++++++++++++++++++++++++++\n 3 files changed, 1372 insertions(+)",
    "diff": "diff --git a/drivers/media/i2c/maxim-serdes/Kconfig b/drivers/media/i2c/maxim-serdes/Kconfig\nindex f060307e3de3..bbfe2d530dbc 100644\n--- a/drivers/media/i2c/maxim-serdes/Kconfig\n+++ b/drivers/media/i2c/maxim-serdes/Kconfig\n@@ -45,3 +45,16 @@ config VIDEO_MAX96724\n \n \t  To compile this driver as a module, choose M here: the module\n \t  will be called max96724.\n+\n+config VIDEO_MAX9296A\n+\ttristate \"Maxim MAX9296A Dual Deserializer support\"\n+\tdepends on I2C\n+\tselect VIDEO_MAXIM_SERDES\n+\thelp\n+\t  This driver supports the Maxim MAX9296A, MAX96716A, MAX96792A\n+\t  Dual Deserializers, and the MAX96714, MAX96714F, MAX96714R\n+\t  Single Deserializers, which  convert from up to two GMSL2/3\n+\t  links to up to two MIPI D-PHY outputs.\n+\n+\t  To compile this driver as a module, choose M here: the module\n+\t  will be called max9296a.\ndiff --git a/drivers/media/i2c/maxim-serdes/Makefile b/drivers/media/i2c/maxim-serdes/Makefile\nindex b6d5aebfaee1..ae306bc33bfb 100644\n--- a/drivers/media/i2c/maxim-serdes/Makefile\n+++ b/drivers/media/i2c/maxim-serdes/Makefile\n@@ -3,3 +3,4 @@ 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\n+obj-$(CONFIG_VIDEO_MAX9296A) += max9296a.o\ndiff --git a/drivers/media/i2c/maxim-serdes/max9296a.c b/drivers/media/i2c/maxim-serdes/max9296a.c\nnew file mode 100644\nindex 000000000000..2c779d43d91f\n--- /dev/null\n+++ b/drivers/media/i2c/maxim-serdes/max9296a.c\n@@ -0,0 +1,1358 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * Maxim MAX9296A Quad GMSL2 Deserializer Driver\n+ *\n+ * Copyright (C) 2025 Analog Devices Inc.\n+ */\n+\n+#include <linux/bitfield.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/regmap.h>\n+\n+#include <media/mipi-csi2.h>\n+\n+#include \"max_des.h\"\n+\n+#define MAX9296A_REG0\t\t\t\t0x0\n+\n+#define MAX9296A_REG1\t\t\t\t0x1\n+#define MAX9296A_REG1_RX_RATE_A\t\t\tGENMASK(1, 0)\n+#define MAX9296A_REG1_RX_RATE_3GBPS\t\t0b01\n+#define MAX9296A_REG1_RX_RATE_6GBPS\t\t0b10\n+#define MAX9296A_REG1_RX_RATE_12GBPS\t\t0b11\n+\n+#define MAX9296A_REG2\t\t\t\t0x2\n+#define MAX9296A_REG2_VID_EN(p)\t\t\tBIT((p) + 4)\n+\n+#define MAX9296A_REG4\t\t\t\t0x4\n+#define MAX9296A_REG4_GMSL3_X(x)\t\tBIT((x) + 6)\n+#define MAX9296A_REG4_RX_RATE_B\t\t\tGENMASK(1, 0)\n+\n+#define MAX9296A_REG6\t\t\t\t0x6\n+#define MAX9296A_REG6_GMSL2_X(x)\t\tBIT((x) + 6)\n+\n+#define MAX9296A_CTRL0\t\t\t\t0x10\n+#define MAX9296A_CTRL0_LINK_CFG\t\t\tGENMASK(1, 0)\n+#define MAX9296A_CTRL0_AUTO_LINK\t\tBIT(4)\n+#define MAX9296A_CTRL0_RESET_ONESHOT\t\tBIT(5)\n+#define MAX9296A_CTRL0_RESET_ALL\t\tBIT(7)\n+\n+#define MAX9296A_CTRL2\t\t\t\t0x12\n+#define MAX9296A_CTRL2_RESET_ONESHOT_B\t\tBIT(5)\n+\n+#define MAX9296A_MIPI_TX0(x)\t\t\t(0x28 + (x) * 0x5000)\n+#define MAX9296A_MIPI_TX0_RX_FEC_EN\t\tBIT(1)\n+\n+#define MAX9296A_IO_CHK0\t\t\t0x38\n+#define MAX9296A_IO_CHK0_PIN_DRV_EN_0\t\tGENMASK(1, 0)\n+#define MAX9296A_IO_CHK0_PIN_DRV_EN_0_25MHZ\t0b00\n+#define MAX9296A_IO_CHK0_PIN_DRV_EN_0_75MHZ\t0b01\n+#define MAX9296A_IO_CHK0_PIN_DRV_EN_0_USE_PIPE\t0b10\n+\n+#define MAX9296A_RX50(p)\t\t\t(0x50 + (p))\n+#define MAX9296A_RX50_STR_SEL\t\t\tGENMASK(1, 0)\n+\n+#define MAX9296A_VIDEO_PIPE_EN\t\t\t0x160\n+#define MAX9296A_VIDEO_PIPE_EN_MASK(p)\t\tBIT(p)\n+\n+#define MAX9296A_VIDEO_PIPE_SEL\t\t\t0x161\n+#define MAX9296A_VIDEO_PIPE_SEL_STREAM(p)\t(GENMASK(1, 0) << ((p) * 3))\n+#define MAX9296A_VIDEO_PIPE_SEL_LINK(p)\t\tBIT(2 + (p) * 3)\n+\n+#define MAX9296A_VPRBS(p)\t\t\t(0x1fc + (p) * 0x20)\n+#define MAX9296A_VPRBS_VIDEO_LOCK\t\tBIT(0)\n+#define MAX9296A_VPRBS_PATGEN_CLK_SRC\t\tBIT(7)\n+#define MAX9296A_VPRBS_PATGEN_CLK_SRC_150MHZ\t0b0\n+#define MAX9296A_VPRBS_PATGEN_CLK_SRC_600MHZ\t0b1\n+\n+#define MAX9296A_PATGEN_0\t\t\t0x240\n+#define MAX9296A_PATGEN_0_VTG_MODE\t\tGENMASK(1, 0)\n+#define MAX9296A_PATGEN_0_VTG_MODE_FREE_RUNNING\t0b11\n+#define MAX9296A_PATGEN_0_DE_INV\t\tBIT(2)\n+#define MAX9296A_PATGEN_0_HS_INV\t\tBIT(3)\n+#define MAX9296A_PATGEN_0_VS_INV\t\tBIT(4)\n+#define MAX9296A_PATGEN_0_GEN_DE\t\tBIT(5)\n+#define MAX9296A_PATGEN_0_GEN_HS\t\tBIT(6)\n+#define MAX9296A_PATGEN_0_GEN_VS\t\tBIT(7)\n+\n+#define MAX9296A_PATGEN_1\t\t\t0x241\n+#define MAX9296A_PATGEN_1_PATGEN_MODE\t\tGENMASK(5, 4)\n+#define MAX9296A_PATGEN_1_PATGEN_MODE_DISABLED\t0b00\n+#define MAX9296A_PATGEN_1_PATGEN_MODE_CHECKER\t0b11\n+#define MAX9296A_PATGEN_1_PATGEN_MODE_GRADIENT\t0b10\n+\n+#define MAX9296A_VS_DLY_2\t\t\t0x242\n+#define MAX9296A_VS_HIGH_2\t\t\t0x245\n+#define MAX9296A_VS_LOW_2\t\t\t0x248\n+#define MAX9296A_V2H_2\t\t\t\t0x24b\n+#define MAX9296A_HS_HIGH_1\t\t\t0x24e\n+#define MAX9296A_HS_LOW_1\t\t\t0x250\n+#define MAX9296A_HS_CNT_1\t\t\t0x252\n+#define MAX9296A_V2D_2\t\t\t\t0x254\n+#define MAX9296A_DE_HIGH_1\t\t\t0x257\n+#define MAX9296A_DE_LOW_1\t\t\t0x259\n+#define MAX9296A_DE_CNT_1\t\t\t0x25b\n+#define MAX9296A_GRAD_INCR\t\t\t0x25d\n+#define MAX9296A_CHKR_COLOR_A_L\t\t\t0x25e\n+#define MAX9296A_CHKR_COLOR_B_L\t\t\t0x261\n+#define MAX9296A_CHKR_RPT_A\t\t\t0x264\n+#define MAX9296A_CHKR_RPT_B\t\t\t0x265\n+#define MAX9296A_CHKR_ALT\t\t\t0x266\n+\n+#define MAX9296A_BACKTOP12\t\t\t0x313\n+#define MAX9296A_BACKTOP12_CSI_OUT_EN\t\tBIT(1)\n+\n+#define MAX9296A_BACKTOP21\t\t\t0x31c\n+#define MAX9296A_BACKTOP21_BPP8DBL(p)\t\tBIT(4 + (p))\n+\n+#define MAX9296A_BACKTOP22(x)\t\t\t(0x31d + (x) * 0x3)\n+#define MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL\tGENMASK(4, 0)\n+#define MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL_EN\tBIT(5)\n+\n+#define MAX9296A_BACKTOP24\t\t\t0x31f\n+#define MAX9296A_BACKTOP24_BPP8DBL_MODE(p)\tBIT(4 + (p))\n+\n+#define MAX9296A_BACKTOP32\t\t\t0x327\n+#define MAX9296A_BACKTOP32_BPP10DBL(p)\t\tBIT(p)\n+#define MAX9296A_BACKTOP32_BPP10DBL_MODE(p)\tBIT(4 + (p))\n+\n+#define MAX9296A_BACKTOP33\t\t\t0x328\n+#define MAX9296A_BACKTOP32_BPP12DBL(p)\t\tBIT(p)\n+\n+#define MAX9296A_MIPI_PHY0\t\t\t0x330\n+#define MAX9296A_MIPI_PHY0_FORCE_CSI_OUT_EN\tBIT(7)\n+\n+#define MAX9296A_MIPI_PHY2\t\t\t0x332\n+#define MAX9296A_MIPI_PHY2_PHY_STDBY_N(x)\t(GENMASK(5, 4) << ((x) * 2))\n+\n+#define MAX9296A_MIPI_PHY3(x)\t\t\t(0x333 + (x))\n+#define MAX9296A_MIPI_PHY3_PHY_LANE_MAP_4\tGENMASK(7, 0)\n+\n+#define MAX9296A_MIPI_PHY5(x)\t\t\t(0x335 + (x))\n+#define MAX9296A_MIPI_PHY5_PHY_POL_MAP_0_1\tGENMASK(1, 0)\n+#define MAX9296A_MIPI_PHY5_PHY_POL_MAP_2_3\tGENMASK(4, 3)\n+#define MAX9296A_MIPI_PHY5_PHY_POL_MAP_CLK(x)\tBIT((x) == 0 ? 5 : 2)\n+\n+#define MAX9296A_MIPI_PHY18\t\t\t0x342\n+#define MAX9296A_MIPI_PHY18_CSI2_TX_PKT_CNT(x)\t(GENMASK(3, 0) << (4 * (x)))\n+\n+#define MAX9296A_MIPI_PHY20(x)\t\t\t(0x344 + (x))\n+\n+#define MAX9296A_MIPI_TX3(x)\t\t\t(0x403 + (x) * 0x40)\n+#define MAX9296A_MIPI_TX3_DESKEW_INIT_8X32K\tFIELD_PREP(GENMASK(2, 0), 0b001)\n+#define MAX9296A_MIPI_TX3_DESKEW_INIT_AUTO\tBIT(7)\n+\n+#define MAX9296A_MIPI_TX4(x)\t\t\t(0x404 + (x) * 0x40)\n+#define MAX9296A_MIPI_TX4_DESKEW_PER_2K\t\tFIELD_PREP(GENMASK(2, 0), 0b001)\n+#define MAX9296A_MIPI_TX4_DESKEW_PER_AUTO\tBIT(7)\n+\n+#define MAX9296A_MIPI_TX10(x)\t\t\t(0x40a + (x) * 0x40)\n+#define MAX9296A_MIPI_TX10_CSI2_LANE_CNT\tGENMASK(7, 6)\n+#define MAX9296A_MIPI_TX10_CSI2_CPHY_EN\t\tBIT(5)\n+\n+#define MAX9296A_MIPI_TX11(p)\t\t\t(0x40b + (p) * 0x40)\n+#define MAX9296A_MIPI_TX12(p)\t\t\t(0x40c + (p) * 0x40)\n+\n+#define MAX9296A_MIPI_TX13(p, x)\t\t(0x40d + (p) * 0x40 + (x) * 0x2)\n+#define MAX9296A_MIPI_TX13_MAP_SRC_DT\t\tGENMASK(5, 0)\n+#define MAX9296A_MIPI_TX13_MAP_SRC_VC\t\tGENMASK(7, 6)\n+\n+#define MAX9296A_MIPI_TX14(p, x)\t\t(0x40e + (p) * 0x40 + (x) * 0x2)\n+#define MAX9296A_MIPI_TX14_MAP_DST_DT\t\tGENMASK(5, 0)\n+#define MAX9296A_MIPI_TX14_MAP_DST_VC\t\tGENMASK(7, 6)\n+\n+#define MAX9296A_MIPI_TX45(p, x)\t\t(0x42d + (p) * 0x40 + (x) / 4)\n+#define MAX9296A_MIPI_TX45_MAP_DPHY_DEST(x)\t(GENMASK(1, 0) << (2 * ((x) % 4)))\n+\n+#define MAX9296A_MIPI_TX51(x)\t\t\t(0x433 + (x) * 0x40)\n+#define MAX9296A_MIPI_TX51_ALT_MEM_MAP_12\tBIT(0)\n+#define MAX9296A_MIPI_TX51_ALT_MEM_MAP_8\tBIT(1)\n+#define MAX9296A_MIPI_TX51_ALT_MEM_MAP_10\tBIT(2)\n+#define MAX9296A_MIPI_TX51_ALT2_MEM_MAP_8\tBIT(4)\n+\n+#define MAX9296A_MIPI_TX52(x)\t\t\t(0x434 +  (x) * 0x40)\n+#define MAX9296A_MIPI_TX52_TUN_DEST\t\tBIT(1)\n+#define MAX9296A_MIPI_TX52_TUN_EN\t\tBIT(0)\n+\n+#define MAX9296A_GMSL1_EN\t\t\t0xf00\n+#define MAX9296A_GMSL1_EN_LINK_EN\t\tGENMASK(1, 0)\n+\n+#define MAX9296A_RLMS3E(x)\t\t\t(0x143e + (x) * 0x100)\n+#define MAX9296A_RLMS3F(x)\t\t\t(0x143f + (x) * 0x100)\n+#define MAX9296A_RLMS49(x)\t\t\t(0x1449 + (x) * 0x100)\n+#define MAX9296A_RLMS7E(x)\t\t\t(0x147e + (x) * 0x100)\n+#define MAX9296A_RLMS7F(x)\t\t\t(0x147f + (x) * 0x100)\n+#define MAX9296A_RLMSA3(x)\t\t\t(0x14a3 + (x) * 0x100)\n+#define MAX9296A_RLMSA5(x)\t\t\t(0x14a5 + (x) * 0x100)\n+#define MAX9296A_RLMSD8(x)\t\t\t(0x14d8 + (x) * 0x100)\n+\n+#define MAX9296A_DPLL_0(x)\t\t\t(0x1c00 + (x) * 0x100)\n+#define MAX9296A_DPLL_0_CONFIG_SOFT_RST_N\tBIT(0)\n+\n+#define MAX9296A_PIPES_NUM\t\t\t4\n+#define MAX9296A_PHYS_NUM\t\t\t2\n+\n+static const struct regmap_config max9296a_i2c_regmap = {\n+\t.reg_bits = 16,\n+\t.val_bits = 8,\n+};\n+\n+struct max9296a_priv {\n+\tstruct max_des des;\n+\tconst struct max9296a_chip_info *info;\n+\n+\tstruct device *dev;\n+\tstruct i2c_client *client;\n+\tstruct regmap *regmap;\n+\n+\tstruct gpio_desc *gpiod_pwdn;\n+};\n+\n+struct max9296a_chip_info {\n+\tconst struct max_des_info *info;\n+\tconst struct max_des_ops *ops;\n+\tconst struct reg_sequence *rlms_adjust_sequence;\n+\tunsigned int rlms_adjust_sequence_len;\n+\tunsigned int max_register;\n+\tunsigned int pipe_hw_ids[MAX9296A_PIPES_NUM];\n+\tunsigned int phy_hw_ids[MAX9296A_PHYS_NUM];\n+\tbool has_per_link_reset;\n+\tbool phy0_lanes_0_1_on_second_phy;\n+\tbool polarity_on_physical_lanes;\n+\tbool supports_cphy;\n+\tbool supports_phy_log;\n+};\n+\n+#define des_to_priv(_des) \\\n+\tcontainer_of(_des, struct max9296a_priv, des)\n+\n+static int max9296a_wait_for_device(struct max9296a_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, MAX9296A_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 max9296a_reset(struct max9296a_priv *priv)\n+{\n+\tint ret;\n+\n+\tret = max9296a_wait_for_device(priv);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_set_bits(priv->regmap, MAX9296A_CTRL0,\n+\t\t\t      MAX9296A_CTRL0_RESET_ALL);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tmsleep(100);\n+\n+\treturn max9296a_wait_for_device(priv);\n+}\n+\n+static unsigned int max9296a_pipe_id(struct max9296a_priv *priv,\n+\t\t\t\t     struct max_des_pipe *pipe)\n+{\n+\treturn priv->info->pipe_hw_ids[pipe->index];\n+}\n+\n+static unsigned int max9296a_phy_id(struct max9296a_priv *priv,\n+\t\t\t\t    struct max_des_phy *phy)\n+{\n+\treturn priv->info->phy_hw_ids[phy->index];\n+}\n+\n+static int __maybe_unused max9296a_reg_read(struct max_des *des, unsigned int reg,\n+\t\t\t\t\t    unsigned int *val)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_read(priv->regmap, reg, val);\n+}\n+\n+static int __maybe_unused max9296a_reg_write(struct max_des *des, unsigned int reg,\n+\t\t\t\t\t     unsigned int val)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_write(priv->regmap, reg, val);\n+}\n+\n+static int max9626a_log_pipe_status(struct max_des *des,\n+\t\t\t\t    struct max_des_pipe *pipe)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\tunsigned int val;\n+\tint ret;\n+\n+\tret = regmap_read(priv->regmap, MAX9296A_VPRBS(index), &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tvideo_lock: %u\\n\",\n+\t\t !!(val & MAX9296A_VPRBS_VIDEO_LOCK));\n+\n+\treturn 0;\n+}\n+\n+static int max9296a_log_phy_status(struct max_des *des,\n+\t\t\t\t   struct max_des_phy *phy)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = phy->index;\n+\tunsigned int val;\n+\tint ret;\n+\n+\tif (!priv->info->supports_phy_log)\n+\t\treturn 0;\n+\n+\tret = regmap_read(priv->regmap, MAX9296A_MIPI_PHY18, &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tcsi2_pkt_cnt: %lu\\n\",\n+\t\t field_get(MAX9296A_MIPI_PHY18_CSI2_TX_PKT_CNT(index), val));\n+\n+\tret = regmap_read(priv->regmap, MAX9296A_MIPI_PHY20(index), &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tdev_info(priv->dev, \"\\tphy_pkt_cnt: %u\\n\", val);\n+\n+\treturn 0;\n+}\n+\n+static int max9296a_set_enable(struct max_des *des, bool enable)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP12,\n+\t\t\t\t  MAX9296A_BACKTOP12_CSI_OUT_EN, enable);\n+}\n+\n+static int max9296a_init_tpg(struct max_des *des)\n+{\n+\tconst struct reg_sequence regs[] = {\n+\t\t{ MAX9296A_GRAD_INCR, MAX_SERDES_GRAD_INCR },\n+\t\tREG_SEQUENCE_3_LE(MAX9296A_CHKR_COLOR_A_L,\n+\t\t\t\t  MAX_SERDES_CHECKER_COLOR_A),\n+\t\tREG_SEQUENCE_3_LE(MAX9296A_CHKR_COLOR_B_L,\n+\t\t\t\t  MAX_SERDES_CHECKER_COLOR_B),\n+\t\t{ MAX9296A_CHKR_RPT_A, MAX_SERDES_CHECKER_SIZE },\n+\t\t{ MAX9296A_CHKR_RPT_B, MAX_SERDES_CHECKER_SIZE },\n+\t\t{ MAX9296A_CHKR_ALT, MAX_SERDES_CHECKER_SIZE },\n+\t};\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_multi_reg_write(priv->regmap, regs, ARRAY_SIZE(regs));\n+}\n+\n+static int max9296a_init(struct max_des *des)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tint ret;\n+\n+\tif (priv->info->rlms_adjust_sequence) {\n+\t\tret = regmap_multi_reg_write(priv->regmap,\n+\t\t\t\t\t     priv->info->rlms_adjust_sequence,\n+\t\t\t\t\t     priv->info->rlms_adjust_sequence_len);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn max9296a_init_tpg(des);\n+}\n+\n+static int max9296a_init_phy(struct max_des *des, struct max_des_phy *phy)\n+{\n+\tstruct max9296a_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 hw_index = max9296a_phy_id(priv, phy);\n+\tunsigned int index = phy->index;\n+\tunsigned int used_data_lanes = 0;\n+\tunsigned int val;\n+\tunsigned int i;\n+\tint ret;\n+\n+\tif (is_cphy && !priv->info->supports_cphy) {\n+\t\tdev_err(priv->dev, \"CPHY not supported\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tnum_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy);\n+\n+\t/*\n+\t * MAX9296A has four PHYs, but does not support single-PHY configurations,\n+\t * only double-PHY configurations, even when only using two lanes.\n+\t * For PHY 0 + PHY 1, PHY 1 is the master PHY.\n+\t * For PHY 2 + PHY 3, PHY 2 is the master PHY.\n+\t * Clock is always on the master PHY.\n+\t * For first pair of PHYs, first lanes are on the master PHY.\n+\t * For second pair of PHYs, first lanes are on the master PHY too.\n+\t *\n+\t * PHY 0 + 1\n+\t * CLK = PHY 1\n+\t * PHY1 Lane 0 = D0\n+\t * PHY1 Lane 1 = D1\n+\t * PHY0 Lane 0 = D2\n+\t * PHY0 Lane 1 = D3\n+\t *\n+\t * PHY 2 + 3\n+\t * CLK = PHY 2\n+\t * PHY2 Lane 0 = D0\n+\t * PHY2 Lane 1 = D1\n+\t * PHY3 Lane 0 = D2\n+\t * PHY3 Lane 1 = D3\n+\t *\n+\t * MAX96714 only has two PHYs which cannot support single-PHY configurations.\n+\t * Clock is always on the master PHY, first lanes are on PHY 0, even if\n+\t * PHY 1 is the master PHY.\n+\t *\n+\t * PHY 0 + 1\n+\t * CLK = PHY 1\n+\t * PHY0 Lane 0 = D0\n+\t * PHY0 Lane 1 = D1\n+\t * PHY1 Lane 0 = D2\n+\t * PHY1 Lane 1 = D3\n+\t */\n+\n+\t/* Configure a lane count. */\n+\tret = regmap_update_bits(priv->regmap, MAX9296A_MIPI_TX10(hw_index),\n+\t\t\t\t MAX9296A_MIPI_TX10_CSI2_LANE_CNT,\n+\t\t\t\t FIELD_PREP(MAX9296A_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, MAX9296A_MIPI_TX10(hw_index),\n+\t\t\t\t MAX9296A_MIPI_TX10_CSI2_CPHY_EN, is_cphy);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Configure lane mapping. */\n+\t/*\n+\t * The lane of each PHY can be mapped to physical lanes 0, 1, 2, and 3.\n+\t * This mapping is exclusive, multiple lanes, even if unused cannot be\n+\t * mapped to the same physical lane.\n+\t * Each lane mapping is represented as two bits.\n+\t */\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 (phy->index == 0 && priv->info->phy0_lanes_0_1_on_second_phy)\n+\t\tval = ((val & 0xf) << 4) | ((val >> 4) & 0xf);\n+\n+\tret = regmap_update_bits(priv->regmap, MAX9296A_MIPI_PHY3(index),\n+\t\t\t\t MAX9296A_MIPI_PHY3_PHY_LANE_MAP_4,\n+\t\t\t\t FIELD_PREP(MAX9296A_MIPI_PHY3_PHY_LANE_MAP_4, val));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/*\n+\t * Configure lane polarity.\n+\t *\n+\t * PHY 0 and 1 are on register 0x335.\n+\t * PHY 2 and 3 are on register 0x336.\n+\t *\n+\t * Each PHY has 3 bits of polarity configuration.\n+\t *\n+\t * On MAX9296A, each bit represents the lane polarity of logical lanes.\n+\t * Each of these lanes can be mapped to any physical lane.\n+\t * 0th bit is for lane 0.\n+\t * 1st bit is for lane 1.\n+\t * 2nd bit is for clock lane.\n+\t *\n+\t * On MAX96714, each bit represents the lane polarity of physical lanes.\n+\t * 0th bit for physical lane 0.\n+\t * 1st bit for physical lane 1.\n+\t * 2nd bit for clock lane of PHY 0, the slave PHY, which is unused.\n+\t *\n+\t * 3rd bit for physical lane 2.\n+\t * 4th bit for physical lane 3.\n+\t * 5th bit for clock lane of PHY 1, the master PHY.\n+\t */\n+\n+\tfor (i = 0, val = 0; i < num_data_lanes; i++) {\n+\t\tunsigned int map;\n+\n+\t\tif (!phy->mipi.lane_polarities[i + 1])\n+\t\t\tcontinue;\n+\n+\t\t/*\n+\t\t * The numbers inside the data_lanes array specify the hardware\n+\t\t * lane each logical lane maps to.\n+\t\t * If polarity is set for the physical lanes, retrieve the\n+\t\t * physical lane matching the logical lane from data_lanes.\n+\t\t * Otherwise, when polarity is set for the logical lanes\n+\t\t * the index of the polarity can be used.\n+\t\t */\n+\n+\t\tif (priv->info->polarity_on_physical_lanes)\n+\t\t\tmap = phy->mipi.data_lanes[i] - 1;\n+\t\telse\n+\t\t\tmap = i;\n+\n+\t\tval |= BIT(map);\n+\t}\n+\n+\tif (phy->index == 0 && priv->info->phy0_lanes_0_1_on_second_phy)\n+\t\tval = ((val & 0x3) << 2) | ((val >> 2) & 0x3);\n+\n+\tret = regmap_update_bits(priv->regmap, MAX9296A_MIPI_PHY5(index),\n+\t\t\t\t MAX9296A_MIPI_PHY5_PHY_POL_MAP_0_1 |\n+\t\t\t\t MAX9296A_MIPI_PHY5_PHY_POL_MAP_2_3,\n+\t\t\t\t FIELD_PREP(MAX9296A_MIPI_PHY5_PHY_POL_MAP_0_1, val) |\n+\t\t\t\t FIELD_PREP(MAX9296A_MIPI_PHY5_PHY_POL_MAP_2_3, val >> 2));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_PHY5(index),\n+\t\t\t\t MAX9296A_MIPI_PHY5_PHY_POL_MAP_CLK(index),\n+\t\t\t\t phy->mipi.lane_polarities[0]);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Put DPLL block into reset. */\n+\tret = regmap_clear_bits(priv->regmap, MAX9296A_DPLL_0(hw_index),\n+\t\t\t\tMAX9296A_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, MAX9296A_BACKTOP22(hw_index),\n+\t\t\t\t MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL,\n+\t\t\t\t FIELD_PREP(MAX9296A_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, MAX9296A_BACKTOP22(hw_index),\n+\t\t\t      MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL_EN);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Pull DPLL block out of reset. */\n+\tret = regmap_set_bits(priv->regmap, MAX9296A_DPLL_0(hw_index),\n+\t\t\t      MAX9296A_DPLL_0_CONFIG_SOFT_RST_N);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (dpll_freq > 1500000000ull) {\n+\t\t/* Enable initial deskew with 2 x 32k UI. */\n+\t\tret = regmap_write(priv->regmap, MAX9296A_MIPI_TX3(hw_index),\n+\t\t\t\t   MAX9296A_MIPI_TX3_DESKEW_INIT_AUTO |\n+\t\t\t\t   MAX9296A_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, MAX9296A_MIPI_TX4(hw_index),\n+\t\t\t\t   MAX9296A_MIPI_TX4_DESKEW_PER_AUTO |\n+\t\t\t\t   MAX9296A_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, MAX9296A_MIPI_TX3(hw_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, MAX9296A_MIPI_TX4(hw_index), 0x0);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int max9296a_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 max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int phy_id = max9296a_phy_id(priv, phy);\n+\tint ret;\n+\n+\t/* Set alternate memory map modes. */\n+\tret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX51(phy_id),\n+\t\t\t\t MAX9296A_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, MAX9296A_MIPI_TX51(phy_id),\n+\t\t\t\t MAX9296A_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, MAX9296A_MIPI_TX51(phy_id),\n+\t\t\t\t MAX9296A_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, MAX9296A_MIPI_TX51(phy_id),\n+\t\t\t\t  MAX9296A_MIPI_TX51_ALT2_MEM_MAP_8,\n+\t\t\t\t  mode->alt2_mem_map8);\n+}\n+\n+static int max9296a_set_phy_enable(struct max_des *des, struct max_des_phy *phy,\n+\t\t\t\t   bool enable)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_MIPI_PHY2,\n+\t\t\t\t  MAX9296A_MIPI_PHY2_PHY_STDBY_N(phy->index), enable);\n+}\n+\n+static int max9296a_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 max9296a_priv *priv = des_to_priv(des);\n+\tstruct max_des_phy *phy = &des->phys[remap->phy];\n+\tunsigned int phy_id = max9296a_phy_id(priv, phy);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\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, MAX9296A_MIPI_TX13(index, i),\n+\t\t\t   FIELD_PREP(MAX9296A_MIPI_TX13_MAP_SRC_DT,\n+\t\t\t\t      remap->from_dt) |\n+\t\t\t   FIELD_PREP(MAX9296A_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, MAX9296A_MIPI_TX14(index, i),\n+\t\t\t   FIELD_PREP(MAX9296A_MIPI_TX14_MAP_DST_DT,\n+\t\t\t\t      remap->to_dt) |\n+\t\t\t   FIELD_PREP(MAX9296A_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, MAX9296A_MIPI_TX45(index, i),\n+\t\t\t\t  MAX9296A_MIPI_TX45_MAP_DPHY_DEST(i),\n+\t\t\t\t  field_prep(MAX9296A_MIPI_TX45_MAP_DPHY_DEST(i),\n+\t\t\t\t\t     phy_id));\n+}\n+\n+static int max9296a_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 max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\tint ret;\n+\n+\tret = regmap_write(priv->regmap, MAX9296A_MIPI_TX11(index), mask);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_write(priv->regmap, MAX9296A_MIPI_TX12(index), mask >> 8);\n+}\n+\n+static int max9296a_set_pipe_enable(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t    bool enable)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_REG2,\n+\t\t\t\t  MAX9296A_REG2_VID_EN(index), enable);\n+}\n+\n+static int max96714_set_pipe_enable(struct max_des *des, struct max_des_pipe *pipe,\n+\t\t\t\t    bool enable)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_VIDEO_PIPE_EN,\n+\t\t\t\t  MAX9296A_VIDEO_PIPE_EN_MASK(index - 1), enable);\n+}\n+\n+static int max96714_set_pipe_tunnel_enable(struct max_des *des,\n+\t\t\t\t\t   struct max_des_pipe *pipe, bool enable)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX52(index),\n+\t\t\t\t  MAX9296A_MIPI_TX52_TUN_EN, enable);\n+}\n+\n+static int max9296a_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 max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\n+\treturn regmap_update_bits(priv->regmap, MAX9296A_RX50(index), MAX9296A_RX50_STR_SEL,\n+\t\t\t\t  FIELD_PREP(MAX9296A_RX50_STR_SEL, pipe->stream_id));\n+}\n+\n+static int max96714_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 max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\n+\treturn regmap_update_bits(priv->regmap, MAX9296A_VIDEO_PIPE_SEL,\n+\t\t\t\t  MAX9296A_VIDEO_PIPE_SEL_STREAM(index),\n+\t\t\t\t  field_prep(MAX9296A_VIDEO_PIPE_SEL_STREAM(index),\n+\t\t\t\t\t     stream_id));\n+}\n+\n+static int max96716a_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 max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = pipe->index;\n+\n+\treturn regmap_update_bits(priv->regmap, MAX9296A_VIDEO_PIPE_SEL,\n+\t\t\t\t  MAX9296A_VIDEO_PIPE_SEL_LINK(index),\n+\t\t\t\t  field_prep(MAX9296A_VIDEO_PIPE_SEL_LINK(index),\n+\t\t\t\t\t     link->index));\n+}\n+\n+static int max96716a_set_pipe_tunnel_phy(struct max_des *des,\n+\t\t\t\t\t struct max_des_pipe *pipe,\n+\t\t\t\t\t struct max_des_phy *phy)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX52(index),\n+\t\t\t\t  MAX9296A_MIPI_TX52_TUN_DEST, phy->index);\n+}\n+\n+static int max9296a_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 max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = max9296a_pipe_id(priv, pipe);\n+\tint ret;\n+\n+\t/* Set 8bit double mode. */\n+\tret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP21,\n+\t\t\t\t MAX9296A_BACKTOP21_BPP8DBL(index), mode->dbl8);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP24,\n+\t\t\t\t MAX9296A_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+\tret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP32,\n+\t\t\t\t MAX9296A_BACKTOP32_BPP10DBL(index), mode->dbl10);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP32,\n+\t\t\t\t MAX9296A_BACKTOP32_BPP10DBL_MODE(index),\n+\t\t\t\t mode->dbl10mode);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Set 12bit double mode. */\n+\t/* TODO: check support for double mode on MAX96714. */\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP33,\n+\t\t\t\t  MAX9296A_BACKTOP32_BPP12DBL(index), mode->dbl12);\n+}\n+\n+static int max9296a_reset_link(struct max9296a_priv *priv, unsigned int index)\n+{\n+\tunsigned int reg, mask;\n+\n+\tif (index == 0) {\n+\t\treg = MAX9296A_CTRL0;\n+\t\tmask = MAX9296A_CTRL0_RESET_ONESHOT;\n+\t} else {\n+\t\treg = MAX9296A_CTRL2;\n+\t\tmask = MAX9296A_CTRL2_RESET_ONESHOT_B;\n+\t}\n+\n+\treturn regmap_set_bits(priv->regmap, reg, mask);\n+}\n+\n+static int max9296a_select_links(struct max_des *des, unsigned int mask)\n+{\n+\tstruct max9296a_priv *priv = des_to_priv(des);\n+\tint ret;\n+\n+\tif (des->info->num_links == 1)\n+\t\treturn 0;\n+\n+\tif (!mask) {\n+\t\tdev_err(priv->dev, \"Disable all links unsupported\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = regmap_update_bits(priv->regmap, MAX9296A_GMSL1_EN,\n+\t\t\t\t MAX9296A_GMSL1_EN_LINK_EN,\n+\t\t\t\t FIELD_PREP(MAX9296A_GMSL1_EN_LINK_EN, mask));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_update_bits(priv->regmap, MAX9296A_CTRL0,\n+\t\t\t\t MAX9296A_CTRL0_AUTO_LINK |\n+\t\t\t\t MAX9296A_CTRL0_LINK_CFG |\n+\t\t\t\t MAX9296A_CTRL0_RESET_ONESHOT,\n+\t\t\t\t FIELD_PREP(MAX9296A_CTRL0_LINK_CFG, mask) |\n+\t\t\t\t FIELD_PREP(MAX9296A_CTRL0_RESET_ONESHOT, 1));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (priv->info->has_per_link_reset) {\n+\t\tret = max9296a_reset_link(priv, 1);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\t}\n+\n+\tmsleep(200);\n+\n+\treturn 0;\n+}\n+\n+static int max9296a_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 max9296a_priv *priv = des_to_priv(des);\n+\tunsigned int index = link->index;\n+\tbool gmsl3_en = version == MAX_SERDES_GMSL_3_12GBPS;\n+\tunsigned int reg, mask, val;\n+\tint ret;\n+\n+\tif (des->info->needs_single_link_version)\n+\t\tindex = 0;\n+\n+\tif (index == 0) {\n+\t\treg = MAX9296A_REG1;\n+\t\tmask = MAX9296A_REG1_RX_RATE_A;\n+\t} else {\n+\t\treg = MAX9296A_REG4;\n+\t\tmask = MAX9296A_REG4_RX_RATE_B;\n+\t}\n+\n+\tif (version == MAX_SERDES_GMSL_3_12GBPS)\n+\t\tval = MAX9296A_REG1_RX_RATE_12GBPS;\n+\telse if (version == MAX_SERDES_GMSL_2_6GBPS)\n+\t\tval = MAX9296A_REG1_RX_RATE_6GBPS;\n+\telse\n+\t\tval = MAX9296A_REG1_RX_RATE_3GBPS;\n+\n+\tret = regmap_update_bits(priv->regmap, reg, mask, field_prep(mask, val));\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tif (!(des->info->versions & BIT(MAX_SERDES_GMSL_3_12GBPS)))\n+\t\treturn 0;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX0(index),\n+\t\t\t\t MAX9296A_MIPI_TX0_RX_FEC_EN, gmsl3_en);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = regmap_assign_bits(priv->regmap, MAX9296A_REG6,\n+\t\t\t\t MAX9296A_REG6_GMSL2_X(index), !gmsl3_en);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_REG4,\n+\t\t\t\t  MAX9296A_REG4_GMSL3_X(index), gmsl3_en);\n+}\n+\n+static int max9296a_set_tpg_timings(struct max9296a_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(MAX9296A_VS_DLY_2, tm->vs_dly),\n+\t\tREG_SEQUENCE_3(MAX9296A_VS_HIGH_2, tm->vs_high),\n+\t\tREG_SEQUENCE_3(MAX9296A_VS_LOW_2, tm->vs_low),\n+\t\tREG_SEQUENCE_3(MAX9296A_V2H_2, tm->v2h),\n+\t\tREG_SEQUENCE_2(MAX9296A_HS_HIGH_1, tm->hs_high),\n+\t\tREG_SEQUENCE_2(MAX9296A_HS_LOW_1, tm->hs_low),\n+\t\tREG_SEQUENCE_2(MAX9296A_HS_CNT_1, tm->hs_cnt),\n+\t\tREG_SEQUENCE_3(MAX9296A_V2D_2, tm->v2d),\n+\t\tREG_SEQUENCE_2(MAX9296A_DE_HIGH_1, tm->de_high),\n+\t\tREG_SEQUENCE_2(MAX9296A_DE_LOW_1, tm->de_low),\n+\t\tREG_SEQUENCE_2(MAX9296A_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, MAX9296A_PATGEN_0,\n+\t\t\t    FIELD_PREP(MAX9296A_PATGEN_0_VTG_MODE,\n+\t\t\t\t       MAX9296A_PATGEN_0_VTG_MODE_FREE_RUNNING) |\n+\t\t\t    FIELD_PREP(MAX9296A_PATGEN_0_DE_INV, tm->de_inv) |\n+\t\t\t    FIELD_PREP(MAX9296A_PATGEN_0_HS_INV, tm->hs_inv) |\n+\t\t\t    FIELD_PREP(MAX9296A_PATGEN_0_VS_INV, tm->vs_inv) |\n+\t\t\t    FIELD_PREP(MAX9296A_PATGEN_0_GEN_DE, tm->gen_de) |\n+\t\t\t    FIELD_PREP(MAX9296A_PATGEN_0_GEN_HS, tm->gen_hs) |\n+\t\t\t    FIELD_PREP(MAX9296A_PATGEN_0_GEN_VS, tm->gen_vs));\n+}\n+\n+static int max9296a_set_tpg_clk(struct max9296a_priv *priv, u32 clock)\n+{\n+\tbool patgen_clk_src = 0;\n+\tu8 pin_drv_en;\n+\tint ret;\n+\n+\tswitch (clock) {\n+\tcase 25000000:\n+\t\tpin_drv_en = MAX9296A_IO_CHK0_PIN_DRV_EN_0_25MHZ;\n+\t\tbreak;\n+\tcase 75000000:\n+\t\tpin_drv_en = MAX9296A_IO_CHK0_PIN_DRV_EN_0_75MHZ;\n+\t\tbreak;\n+\tcase 150000000:\n+\t\tpin_drv_en = MAX9296A_IO_CHK0_PIN_DRV_EN_0_USE_PIPE;\n+\t\tpatgen_clk_src = MAX9296A_VPRBS_PATGEN_CLK_SRC_150MHZ;\n+\t\tbreak;\n+\tcase 600000000:\n+\t\tpin_drv_en = MAX9296A_IO_CHK0_PIN_DRV_EN_0_USE_PIPE;\n+\t\tpatgen_clk_src = MAX9296A_VPRBS_PATGEN_CLK_SRC_600MHZ;\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, MAX9296A_VPRBS(0),\n+\t\t\t\t MAX9296A_VPRBS_PATGEN_CLK_SRC,\n+\t\t\t\t FIELD_PREP(MAX9296A_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, MAX9296A_IO_CHK0,\n+\t\t\t\t  MAX9296A_IO_CHK0_PIN_DRV_EN_0,\n+\t\t\t\t  FIELD_PREP(MAX9296A_IO_CHK0_PIN_DRV_EN_0,\n+\t\t\t\t\t     pin_drv_en));\n+}\n+\n+static int max9296a_set_tpg_mode(struct max9296a_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 = MAX9296A_PATGEN_1_PATGEN_MODE_GRADIENT;\n+\t\tbreak;\n+\tcase MAX_SERDES_TPG_PATTERN_CHECKERBOARD:\n+\t\tpatgen_mode = MAX9296A_PATGEN_1_PATGEN_MODE_CHECKER;\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn regmap_update_bits(priv->regmap, MAX9296A_PATGEN_1,\n+\t\t\t\t  MAX9296A_PATGEN_1_PATGEN_MODE,\n+\t\t\t\t  FIELD_PREP(MAX9296A_PATGEN_1_PATGEN_MODE,\n+\t\t\t\t\t     enable ? patgen_mode\n+\t\t\t\t\t\t    : MAX9296A_PATGEN_1_PATGEN_MODE_DISABLED));\n+}\n+\n+static int max9296a_set_tpg(struct max_des *des,\n+\t\t\t    const struct max_serdes_tpg_entry *entry)\n+{\n+\tstruct max9296a_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 = max9296a_set_tpg_timings(priv, &timings);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = max9296a_set_tpg_clk(priv, timings.clock);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tret = max9296a_set_tpg_mode(priv, entry);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn regmap_assign_bits(priv->regmap, MAX9296A_MIPI_PHY0,\n+\t\t\t\t  MAX9296A_MIPI_PHY0_FORCE_CSI_OUT_EN, !!entry);\n+}\n+\n+static const struct max_serdes_tpg_entry max9296a_tpg_entries[] = {\n+\tMAX_TPG_ENTRY_640X480P60_RGB888,\n+\tMAX_TPG_ENTRY_1920X1080P30_RGB888,\n+\tMAX_TPG_ENTRY_1920X1080P60_RGB888,\n+};\n+\n+#ifdef CONFIG_VIDEO_ADV_DEBUG\n+#define MAX9296A_DEBUG_OPS \\\n+\t.reg_read = max9296a_reg_read, \\\n+\t.reg_write = max9296a_reg_write,\n+#else\n+#define MAX9296A_DEBUG_OPS\n+#endif\n+\n+#define MAX9296A_COMMON_INFO \\\n+\t.num_remaps_per_pipe = 16, \\\n+\t.tpg_entries = { \\\n+\t\t.num_entries = ARRAY_SIZE(max9296a_tpg_entries), \\\n+\t\t.entries = max9296a_tpg_entries, \\\n+\t}, \\\n+\t.tpg_patterns = BIT(MAX_SERDES_TPG_PATTERN_CHECKERBOARD) | \\\n+\t\t\tBIT(MAX_SERDES_TPG_PATTERN_GRADIENT)\n+\n+#define MAX9296A_COMMON_OPS \\\n+\tMAX9296A_DEBUG_OPS \\\n+\t.log_pipe_status = max9626a_log_pipe_status, \\\n+\t.log_phy_status = max9296a_log_phy_status, \\\n+\t.set_enable = max9296a_set_enable, \\\n+\t.init = max9296a_init, \\\n+\t.init_phy = max9296a_init_phy, \\\n+\t.set_phy_mode = max9296a_set_phy_mode, \\\n+\t.set_phy_enable = max9296a_set_phy_enable, \\\n+\t.set_pipe_remap = max9296a_set_pipe_remap, \\\n+\t.set_pipe_remaps_enable = max9296a_set_pipe_remaps_enable, \\\n+\t.set_pipe_mode = max9296a_set_pipe_mode, \\\n+\t.set_tpg = max9296a_set_tpg, \\\n+\t.select_links = max9296a_select_links, \\\n+\t.set_link_version = max9296a_set_link_version\n+\n+static int max9296a_probe(struct i2c_client *client)\n+{\n+\tstruct regmap_config i2c_regmap = max9296a_i2c_regmap;\n+\tstruct device *dev = &client->dev;\n+\tstruct max9296a_priv *priv;\n+\tint ret;\n+\n+\tpriv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);\n+\tif (!priv)\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+\ti2c_regmap.max_register = priv->info->max_register;\n+\tpriv->regmap = devm_regmap_init_i2c(client, &i2c_regmap);\n+\tif (IS_ERR(priv->regmap))\n+\t\treturn PTR_ERR(priv->regmap);\n+\n+\tpriv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, \"powerdown\",\n+\t\t\t\t\t\t   GPIOD_OUT_HIGH);\n+\tif (IS_ERR(priv->gpiod_pwdn))\n+\t\treturn PTR_ERR(priv->gpiod_pwdn);\n+\n+\tif (priv->gpiod_pwdn) {\n+\t\t/* PWDN must be held for 1us for reset */\n+\t\tudelay(1);\n+\n+\t\tgpiod_set_value_cansleep(priv->gpiod_pwdn, 0);\n+\t\t/* Maximum power-up time (tLOCK) 4ms */\n+\t\tusleep_range(4000, 5000);\n+\t}\n+\n+\tpriv->des.info = priv->info->info;\n+\tpriv->des.ops = priv->info->ops;\n+\n+\tret = max9296a_reset(priv);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\treturn max_des_probe(client, &priv->des);\n+}\n+\n+static void max9296a_remove(struct i2c_client *client)\n+{\n+\tstruct max9296a_priv *priv = i2c_get_clientdata(client);\n+\n+\tmax_des_remove(&priv->des);\n+\n+\tgpiod_set_value_cansleep(priv->gpiod_pwdn, 1);\n+}\n+\n+static const struct max_serdes_phys_config max9296a_phys_configs[] = {\n+\t{ { 4, 4 } },\n+};\n+\n+static const struct max_serdes_phys_config max96714_phys_configs[] = {\n+\t{ { 4 } },\n+};\n+\n+static const struct max_des_info max9296a_des_info = {\n+\tMAX9296A_COMMON_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.needs_single_link_version = true,\n+\t.needs_unique_stream_id = true,\n+\t.phys_configs = {\n+\t\t.num_configs = ARRAY_SIZE(max9296a_phys_configs),\n+\t\t.configs = max9296a_phys_configs,\n+\t},\n+\t.fix_tx_ids = true,\n+\t.use_atr = true,\n+\t.num_pipes = 4,\n+\t.num_phys = 2,\n+\t.num_links = 2,\n+};\n+\n+static const struct max_des_ops max9296a_ops = {\n+\tMAX9296A_COMMON_OPS,\n+\t.set_pipe_stream_id = max9296a_set_pipe_stream_id,\n+\t.set_pipe_enable = max9296a_set_pipe_enable,\n+};\n+\n+static const struct max9296a_chip_info max9296a_info = {\n+\t.info = &max9296a_des_info,\n+\t.ops = &max9296a_ops,\n+\t.max_register = 0x1f00,\n+\t.phy0_lanes_0_1_on_second_phy = true,\n+\t.pipe_hw_ids = { 0, 1, 2, 3 },\n+\t.phy_hw_ids = { 1, 2 },\n+};\n+\n+static const struct max_des_info max96714_des_info = {\n+\tMAX9296A_COMMON_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.phys_configs = {\n+\t\t.num_configs = ARRAY_SIZE(max96714_phys_configs),\n+\t\t.configs = max96714_phys_configs,\n+\t},\n+\t.tpg_mode = MAX_SERDES_GMSL_PIXEL_MODE,\n+\t.num_pipes = 1,\n+\t.num_phys = 1,\n+\t.num_links = 1,\n+};\n+\n+static const struct max_des_ops max96714_ops = {\n+\tMAX9296A_COMMON_OPS,\n+\t.set_pipe_stream_id = max96714_set_pipe_stream_id,\n+\t.set_pipe_enable = max96714_set_pipe_enable,\n+\t.set_pipe_tunnel_enable = max96714_set_pipe_tunnel_enable,\n+};\n+\n+/*\n+ * These register writes are described as required in MAX96714 datasheet\n+ * Page 53, Section Register Map, to optimize link performance in 6Gbps\n+ * and 3Gbps links for all cable lengths.\n+ */\n+static const struct reg_sequence max96714_rlms_reg_sequence[] = {\n+\t{ MAX9296A_RLMS3E(0), 0xfd },\n+\t{ MAX9296A_RLMS3F(0), 0x3d },\n+\t{ MAX9296A_RLMS49(0), 0xf5 },\n+\t{ MAX9296A_RLMS7E(0), 0xa8 },\n+\t{ MAX9296A_RLMS7F(0), 0x68 },\n+\t{ MAX9296A_RLMSA3(0), 0x30 },\n+\t{ MAX9296A_RLMSA5(0), 0x70 },\n+\t{ MAX9296A_RLMSD8(0), 0x07 },\n+};\n+\n+static const struct max9296a_chip_info max96714_info = {\n+\t.info = &max96714_des_info,\n+\t.ops = &max96714_ops,\n+\t.max_register = 0x5011,\n+\t.polarity_on_physical_lanes = true,\n+\t.supports_phy_log = true,\n+\t.rlms_adjust_sequence = max96714_rlms_reg_sequence,\n+\t.rlms_adjust_sequence_len = ARRAY_SIZE(max96714_rlms_reg_sequence),\n+\t.pipe_hw_ids = { 1 },\n+\t.phy_hw_ids = { 1 },\n+};\n+\n+static const struct max_des_info max96714f_des_info = {\n+\tMAX9296A_COMMON_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.phys_configs = {\n+\t\t.num_configs = ARRAY_SIZE(max96714_phys_configs),\n+\t\t.configs = max96714_phys_configs,\n+\t},\n+\t.tpg_mode = MAX_SERDES_GMSL_PIXEL_MODE,\n+\t.num_pipes = 1,\n+\t.num_phys = 1,\n+\t.num_links = 1,\n+};\n+\n+static const struct max_des_ops max96714f_ops = {\n+\tMAX9296A_COMMON_OPS,\n+\t.set_pipe_stream_id = max96714_set_pipe_stream_id,\n+\t.set_pipe_enable = max96714_set_pipe_enable,\n+\t.set_pipe_tunnel_enable = max96714_set_pipe_tunnel_enable,\n+};\n+\n+static const struct max9296a_chip_info max96714f_info = {\n+\t.info = &max96714f_des_info,\n+\t.ops = &max96714f_ops,\n+\t.max_register = 0x5011,\n+\t.polarity_on_physical_lanes = true,\n+\t.supports_phy_log = true,\n+\t.rlms_adjust_sequence = max96714_rlms_reg_sequence,\n+\t.rlms_adjust_sequence_len = ARRAY_SIZE(max96714_rlms_reg_sequence),\n+\t.pipe_hw_ids = { 1 },\n+\t.phy_hw_ids = { 1 },\n+};\n+\n+static const struct max_des_info max96716a_des_info = {\n+\tMAX9296A_COMMON_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.use_atr = true,\n+\t.phys_configs = {\n+\t\t.num_configs = ARRAY_SIZE(max9296a_phys_configs),\n+\t\t.configs = max9296a_phys_configs,\n+\t},\n+\t.tpg_mode = MAX_SERDES_GMSL_PIXEL_MODE,\n+\t.num_pipes = 2,\n+\t.num_phys = 2,\n+\t.num_links = 2,\n+};\n+\n+static const struct max_des_ops max96716a_ops = {\n+\tMAX9296A_COMMON_OPS,\n+\t.set_pipe_stream_id = max96714_set_pipe_stream_id,\n+\t.set_pipe_link = max96716a_set_pipe_link,\n+\t.set_pipe_enable = max96714_set_pipe_enable,\n+\t.set_pipe_tunnel_phy = max96716a_set_pipe_tunnel_phy,\n+\t.set_pipe_tunnel_enable = max96714_set_pipe_tunnel_enable,\n+};\n+\n+static const struct max9296a_chip_info max96716a_info = {\n+\t.info = &max96716a_des_info,\n+\t.ops = &max96716a_ops,\n+\t.max_register = 0x52d6,\n+\t.has_per_link_reset = true,\n+\t.phy0_lanes_0_1_on_second_phy = true,\n+\t.supports_cphy = true,\n+\t.supports_phy_log = true,\n+\t.pipe_hw_ids = { 1, 2 },\n+\t.phy_hw_ids = { 1, 2 },\n+};\n+\n+static const struct max_des_info max96792a_des_info = {\n+\tMAX9296A_COMMON_INFO,\n+\t.versions = BIT(MAX_SERDES_GMSL_2_3GBPS) |\n+\t\t    BIT(MAX_SERDES_GMSL_2_6GBPS) |\n+\t\t    BIT(MAX_SERDES_GMSL_3_12GBPS),\n+\t.modes = BIT(MAX_SERDES_GMSL_PIXEL_MODE) |\n+\t\t BIT(MAX_SERDES_GMSL_TUNNEL_MODE),\n+\t.use_atr = true,\n+\t.phys_configs = {\n+\t\t.num_configs = ARRAY_SIZE(max9296a_phys_configs),\n+\t\t.configs = max9296a_phys_configs,\n+\t},\n+\t.tpg_mode = MAX_SERDES_GMSL_PIXEL_MODE,\n+\t.num_pipes = 2,\n+\t.num_phys = 2,\n+\t.num_links = 2,\n+};\n+\n+static const struct max_des_ops max96792a_ops = {\n+\tMAX9296A_COMMON_OPS,\n+\t.set_pipe_stream_id = max96714_set_pipe_stream_id,\n+\t.set_pipe_enable = max96714_set_pipe_enable,\n+\t.set_pipe_tunnel_phy = max96716a_set_pipe_tunnel_phy,\n+\t.set_pipe_tunnel_enable = max96714_set_pipe_tunnel_enable,\n+};\n+\n+static const struct max9296a_chip_info max96792a_info = {\n+\t.info = &max96792a_des_info,\n+\t.ops = &max96792a_ops,\n+\t.max_register = 0x52d6,\n+\t.has_per_link_reset = true,\n+\t.phy0_lanes_0_1_on_second_phy = true,\n+\t.supports_cphy = true,\n+\t.supports_phy_log = true,\n+\t.pipe_hw_ids = { 1, 2 },\n+\t.phy_hw_ids = { 1, 2 },\n+};\n+\n+static const struct of_device_id max9296a_of_table[] = {\n+\t{ .compatible = \"maxim,max9296a\", .data = &max9296a_info },\n+\t{ .compatible = \"maxim,max96714\", .data = &max96714_info },\n+\t{ .compatible = \"maxim,max96714f\", .data = &max96714f_info },\n+\t{ .compatible = \"maxim,max96714r\", .data = &max96714f_info },\n+\t{ .compatible = \"maxim,max96716a\", .data = &max96716a_info },\n+\t{ .compatible = \"maxim,max96792a\", .data = &max96792a_info },\n+\t{ },\n+};\n+MODULE_DEVICE_TABLE(of, max9296a_of_table);\n+\n+static struct i2c_driver max9296a_i2c_driver = {\n+\t.driver\t= {\n+\t\t.name = \"max9296a\",\n+\t\t.of_match_table\t= max9296a_of_table,\n+\t},\n+\t.probe = max9296a_probe,\n+\t.remove = max9296a_remove,\n+};\n+\n+module_i2c_driver(max9296a_i2c_driver);\n+\n+MODULE_IMPORT_NS(\"MAX_SERDES\");\n+MODULE_DESCRIPTION(\"Maxim MAX9296A Quad GMSL2 Deserializer Driver\");\n+MODULE_AUTHOR(\"Cosmin Tanislav <cosmin.tanislav@analog.com>\");\n+MODULE_LICENSE(\"GPL\");\n",
    "prefixes": [
        "v10",
        "18/22"
    ]
}