From patchwork Sat Mar 8 18:33:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871790 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B071D1FDA69; Sat, 8 Mar 2025 18:34:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458876; cv=none; b=HfbmiB/l1dnNtN3cWTcjj15L54VV62x8HVtvDH6USV4nnxtAfLqh3uU0PphnsnYLltAwwC1heEZr13imhDlhQuTNimJGbaUnSZMKwDK/JALwJ3C8F7r26cCqUdDBKlUyteR3e6JOzUOnqVgoByEzuuU2rXPg+WSd5pL5FMB8xms= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458876; c=relaxed/simple; bh=7z6smvZGWZK5IVexMzCPUepQOMHvMOYKwZikRSdeV8w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hEWGi0yt4LHShQwkpxHeSqdZcm/JC+aFlyjusVE+jkGy1+xYXnECz7ENmxX/dl1Syp1m9RiF6koGrHWg5F5jGzE7+Ue1hSyzR+ONYA5tkIi8Ksq1wBcXdbdyjXHqVmQOtFV3Uc4+e4ob17BJq3H/bblOcaaZXxVXtyzvchrX+w8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Wg0/a2WV; arc=none smtp.client-ip=209.85.218.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Wg0/a2WV" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-ab7430e27b2so516737466b.3; Sat, 08 Mar 2025 10:34:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458873; x=1742063673; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jLwWoHn8W9MlyVlWzzyNuJFztVqL0l+N+say9TiSqnw=; b=Wg0/a2WVPddYiWNnmDiphEseMhWxkUuNuTg7ITo8WkPfDmgzVe1fPoQYBedVe/oU95 TAByeYxvubJ5ykrWM/2oATCnR4AvqnhmGVN8DQtmGyxSOf337M77tqTow/ICKFLdDgD5 Re1/8Fz6KvfvHGF7dYF4kXoDNg4tg/f0xO6N+3re1TH0Zopm55bS8MVAii2+FF3WvozX yiq5xixOMt7ZdZ0RARk6Ql5NE9AjvAva/BkeRKhWSd+UtrSVb+V+doiprcXGfNzv/Y9O BvSkgr6JzfpA8xKZd+eUgOXOnDqUqOTQRLYa9jSXJ6hB8gXtQe+8lSpesn2ZIQmEN9x6 hWcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458873; x=1742063673; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jLwWoHn8W9MlyVlWzzyNuJFztVqL0l+N+say9TiSqnw=; b=Szgr+Z833tMYwbekaCnjDIoQdYlf75rf6sAq0kLW+MZ0i5Mj0+YsT5Z5fEdeJgq3Dq QNL409Efp348fb8y2CGs0p8te3qNbUePEA9X4yk0ryuR5GRvrkDe7Vw8KoYZtgS/oQiJ jF77o/L+ZNE54pY8+B68SZT+QzQo4DysOmLiGyU1Dsfv4w6+ZOT4sm6cvtZlT9rfr0wc SnyJGsV3dJz262RIZGzLS/bcJiQQRS+O3XFkd+LZGxSBNOxCPu6ERRLaw1JZdfZf5Sak e0P2plS8sqbsSeGqeMIdRdMmRNs8xoZvHLpsW0aqSz85Y5uKSKdcKiyr7vuSylM9ti45 uckQ== X-Forwarded-Encrypted: i=1; AJvYcCUVlqp2Ora+qc5jWhdfQO7qyWwLeFFLA7DvnJ7Rq0PMEZTk14yKwCj7z4JBdOcWRc32h4RKbAoDj0Ii5IK5@vger.kernel.org, AJvYcCUstHdc/XsFJdUhYwVhHbe3sHIReXLfZIL3U/PtQ0R9Uiu69T8ltPNUtYOLVFs7pNKScWMp2diktp4pT/k=@vger.kernel.org, AJvYcCXkmxnNpnw5kDkEF0Wehym6t55RAZIa1jZJtqmodhQI6pOrzeHtjtVHtp0arxxsBEnqcf5kXUPlUuuR+g==@vger.kernel.org, AJvYcCXmJ8LcGXEh5n68HyBNpQKO9om2utlX/CjfYXGgDRimrjFZKgyWSADvjFzLCuTCPoc0DbNlkfgNCDWl@vger.kernel.org X-Gm-Message-State: AOJu0YzGcrPT2cDRJ8sJck3FQJnbyy/w7CPkrKvpMELN4OpJ9dsgR5EO OJEE0APcw7ygE2O3r+HMQ8n45NJL2t7f3+VKe5ENjLMVaLZ3ZCkz X-Gm-Gg: ASbGncsK4V4t4hfNz1Zgy3OVS9p3h606Iu9X7GfvU+SEHihE7b//PLeq15U6hQPbEez HxxrRYt7+FKk8AqXYgZV2wa9GBcWGFH9yY3JJ6Q+F+BOsbUF9o/d+Bxd+oOoYVGTIkoE99VuIo3 WhhVI3MzAdgxR2D0QfigKoObuj32POc+UawFCBVT/Be4uFJl0lII6thXQ2pNXIlDPNdZL1BPGHE 53uoR3VBvjJMrj0FJNg6Ks2yDOlmiFZ43iuFxcSiByvryv6nRFPPmaSI1sLZZ4N5KNxOtcleWgh NDKxFnHZYUYN2zkETwFYLu9lwcRqdoBq3+hr0ays+6IqsPiuzL/R+siVLA== X-Google-Smtp-Source: AGHT+IHHxecPfjzvfdbEyvTYOJEPLEU7vh7wD68UjIC6rm0+kpYMQ2ocUKFfty06j22eXjZ3vEkUfQ== X-Received: by 2002:a17:906:6a29:b0:abf:40ac:4395 with SMTP id a640c23a62f3a-ac252bb26b7mr1043960266b.31.1741458872544; Sat, 08 Mar 2025 10:34:32 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:32 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 01/24] dt-bindings: media: i2c: max96717: add myself as maintainer Date: Sat, 8 Mar 2025 20:33:30 +0200 Message-ID: <20250308183410.3013996-2-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Analog Devices is taking responsability for the maintenance of the Maxim GMSL2/3 devices. Add myself to the maintainers list and to the device tree bindings. Signed-off-by: Cosmin Tanislav --- Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 1 + MAINTAINERS | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml index d1e8ba6e368e..15ab37702a92 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml @@ -9,6 +9,7 @@ title: MAX96717 CSI-2 to GMSL2 Serializer maintainers: - Julien Massot + - Cosmin Tanislav description: The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input diff --git a/MAINTAINERS b/MAINTAINERS index 1916d0636408..8f463ebca056 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14198,6 +14198,7 @@ F: drivers/media/i2c/max96714.c MAX96717 GMSL2 SERIALIZER DRIVER M: Julien Massot +M: Cosmin Tanislav L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml From patchwork Sat Mar 8 18:33:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872060 Received: from mail-ej1-f47.google.com (mail-ej1-f47.google.com [209.85.218.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20BCE207640; Sat, 8 Mar 2025 18:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458880; cv=none; b=jcMDx+7OCNONgsWmXEnOerMEiL6mpAETp1UpQgHC7nFWHJD5xSlwf2CCD/RH4UOxSPG3vsB4Q4gb2KNFlIiQ//SNNVHvYak93kGLpD2ccl6MdgGXgH54QbCP9+QI0KN9E3yhFdh3w+iPf4J2EXY+DgTh9HbRxBvh3O7ggShnUGQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458880; c=relaxed/simple; bh=AbuPWLIU45qyQVYNe0RinxFUH4fVcFJyxnkCgDaB8A0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UEaq2BLIuqeIvcCehLYWtHecN6fvxHbxTP4SYeFXBIAmgRrSRVBuaYKSEMODC3zNmTJyy6j4YDKVnqhPJnWtu3OihCNxlRxKDDxCnygPT1loyDKVyX+rIEQ7S43LC9CSAvHaUtETDdD5fzagnqfmSTwASh0tFLLPKZGtFbQ95OM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AepU1L1W; arc=none smtp.client-ip=209.85.218.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AepU1L1W" Received: by mail-ej1-f47.google.com with SMTP id a640c23a62f3a-abf3d64849dso340607266b.3; Sat, 08 Mar 2025 10:34:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458876; x=1742063676; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=mkDL/nUvpfh1eHpxumsRvR86QwXqar6N/bhFMrxJa6g=; b=AepU1L1WpsMBlvdCU7rX6TsIttmWPUmmaVEE7GpCbVEQsqJhoPmycvlayYTh9a6jjU 8JbZyvutG67gIv4WNXb1k3+vGBQqpIYYuLs28QPu0ybZoeieTBmbvBb4WV4tn+2vrHyp WSE0YKKwXRk86MWcAmgz1bYMD5q9BJL1AE7e2VLIypZmXzKei4Py2X/ARihAmYpxJepa Z7c/2LwSdMEa8hVO60WOJCKQ2bnuSLo67Vm/o1ywZIcI0K2+DodSrWF6a4HbNYJ+ghFK jgohcLmaaV63H8s31J/yvvkCx2wripXXO521gJ4RLhyGVcdVwft2NIYPFSvViQDrVfYw aIHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458876; x=1742063676; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mkDL/nUvpfh1eHpxumsRvR86QwXqar6N/bhFMrxJa6g=; b=xS6HT98hQSI/MqDOHRrD6XhWzsRpGbfaiNKNunc5f1J/EDsv30QggBcDfcDWo7BZzc zXfWe1K50G2b0pcbQdKR9G+IaU5/nfWGVGhNa6D9AOkvZTzoYnwbx4ZbIcfmckcCp+e5 EB18mJ1Av2gRBdxOOeBTm6GJxEyLXZc7R7zdIz0K2Mu7OF5S8yetMXd9yw4sPcPs6Wo+ CFfyiMLXPmYQ/QF+npwF5z7QNmiHjhZSG+s30FgSU+mGjH3L1NEAo7PRj5/PwQbnO7gz u6TawqYPVfcmZhH07xzj/ernC0SeRvGXz4blguk39NJshGTcn5w9xKpC5l87dutIiGHO wMsg== X-Forwarded-Encrypted: i=1; AJvYcCUvJiU99TJaZEnKctOCULYyPGoeRzGCUp+FDSxU5opz/WkPcnlzV7X3ffiBcA4ms8iFMPHEmXecelwo@vger.kernel.org, AJvYcCVngJlJoFfhV5ca9bNRXI7rZoNmjQbwzQlhRhfjkc+HfG5bAno6rN2GcUV1d1O8LGN3DWRecHj97lfHUeE=@vger.kernel.org, AJvYcCXgEtA22dtVtcQVhob1mAP25kHWc0SWxfBD1VsS5un4FaoN6OuC3mLPGUi0Af8eju8FUQwDeIQcqjhFswne@vger.kernel.org, AJvYcCXsi4T8nfU5D5T5SmVPucSgchCstdVoBk33qbCGVwxb+LUUcanP1GATi3nhQxByWhk1KVfbIzBgMOKT5w==@vger.kernel.org X-Gm-Message-State: AOJu0Yy4eSBc9H2a1ucwhgiKoA395wOsEOvG0QkWlKt+CFPpOE7b3kTy kwHBmxOD/pDbCAUclkPYf/a+lPNMfEWQP+LF4/OrmadHGyJJMcQS X-Gm-Gg: ASbGncvahdKcHtCH5NTzvHoGcJTLpRpid7GFw8VsuEeV/nbi2WJq/PBJFYwfO5Bsv+q tLDEeRv1bU/Cv7qIzcGn91ptS2GdLptxe2ZNuou7QV0aAGYWxBhnHS7pKpgMQHhCHMNsQYU2TqM Ij0nt3x53wD7bWIHQ+eHfp9hnvdWSguBO+M9XCGLZzyMMnIhQIrIiqbOVa9fUhcNUNLVNY1DN2Q S6ahpftWwtcmn9Htek7wn1BoWVlP4euDxgQSAR9rFnoBfWjSsXEnWQd1hRm5gSuAKU4RIBa8VdO czmjOdFettfIt3bqLCFBS1rrL4C9BcKyKk9Upx5bobHUDoOQTwPKt9CwcSvf2CJmWpO7 X-Google-Smtp-Source: AGHT+IEFo+JxS1fGfKbCZ1KRjt4dKQZjHo5NR/dqzrNE9XeFG/awZJXR120fbdrpTpOmQk9ld8OSKA== X-Received: by 2002:a05:6402:518f:b0:5dc:6e27:e6e8 with SMTP id 4fb4d7f45d1cf-5e5e246875fmr19328628a12.24.1741458876037; Sat, 08 Mar 2025 10:34:36 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:35 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 02/24] dt-bindings: media: i2c: max96717: reflow text Date: Sat, 8 Mar 2025 20:33:31 +0200 Message-ID: <20250308183410.3013996-3-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This text is using weird line lengths. Fix it. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96717.yaml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml index 15ab37702a92..1026678a17a7 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml @@ -12,16 +12,15 @@ maintainers: - Cosmin Tanislav description: - The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input - into GMSL2 serial outputs. The device allows the GMSL2 link to - simultaneously transmit bidirectional control-channel data while forward - video transmissions are in progress. The MAX96717 can connect to one - remotely located deserializer using industry-standard coax or STP - interconnects. The device cans operate in pixel or tunnel mode. In pixel mode - the MAX96717 can select the MIPI datatype, while the tunnel mode forward all the MIPI - data received by the serializer. - The MAX96717 supports Reference Over Reverse (channel), - to generate a clock output for the sensor from the GMSL reverse channel. + The MAX96717 serializer converts MIPI CSI-2 D-PHY formatted input into GMSL2 + serial outputs. The device allows the GMSL2 link to simultaneously transmit + bidirectional control-channel data while forward video transmissions are in + progress. The MAX96717 can connect to one remotely located deserializer using + industry-standard coax or STP interconnects. The device cans operate in pixel + or tunnel mode. In pixel mode the MAX96717 can select the MIPI datatype, while + the tunnel mode forward all the MIPI data received by the serializer. + The MAX96717 supports Reference Over Reverse (channel), to generate a clock + output for the sensor from the GMSL reverse channel. The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the forward direction and 187.5Mbps in the reverse direction. From patchwork Sat Mar 8 18:33:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871789 Received: from mail-ej1-f47.google.com (mail-ej1-f47.google.com [209.85.218.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F05D520C02A; Sat, 8 Mar 2025 18:34:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458883; cv=none; b=tWiB9H2wJ5TzcuOBzdXHdjYzcsjR/NwFcA9QS2/ySWVWq8ztdzIteoThB8S2hqhr+YYNKhlGsLupvNh4Fck4tt26PKNR8qANFhYwqxyCtAFV7IM7fl1MPnRcN2HCgKFg5YchwTJGYtSX6LhbsOVrb1ggbmEwBQJpYoQaBx46ykk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458883; c=relaxed/simple; bh=exadcfJVkTurDFUaeZb+RqB2u67LeqpkrFjvwrXOI70=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GxPyfdbSCNEKxEWdTvx4W80iaOq360I1zU0GbQTc1DpCLNZsxiHjcpVoxA5Ge5KVklqWbWeRSSyLjtcj07KsNLJkIkPdhFvLMFRHyzbGFy51L+TvK4f8NNcLIwFHJzooQNup9YOOBF7/0y0RAI3b2pDea3cqCwiMckh4gxUVkes= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=U+BovLYv; arc=none smtp.client-ip=209.85.218.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="U+BovLYv" Received: by mail-ej1-f47.google.com with SMTP id a640c23a62f3a-ac1f5157c90so485719266b.0; Sat, 08 Mar 2025 10:34:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458880; x=1742063680; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VQJEYnQvhExzx8TDjhGPNTh+RNL1iu0t7DvSRmmSgXI=; b=U+BovLYvGVUSnN94yoc1yz1cg4GtlHCiP+IaGvwr0Ubfgk4XKBmng+rb+g3yRkwvlM if9/IDL/SUus+ZRBdv3tzLksHfO6yMDUtHI24xRCoBJC8oxSJZogYS4DE6vAxjZ361cU NAJGTLKfWBuLhV3PjGs5Gei3ZGe62IvxR9R/OUDmdIoQ1fQpC9AetcJR91fZ2m5iveHz 7dpnpnWYsXEep2r60iT7V1Ks5L4xigfbcJV+a8upf9p55N9adP4J9wkD6vtKp2BSZM8Y nSdDOsHFXNI4pBRcQIwLjzY80GoQ2COP0aEKS2RxBElXGS5pN3p57Opfa2B8LjZdSfG9 tP4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458880; x=1742063680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VQJEYnQvhExzx8TDjhGPNTh+RNL1iu0t7DvSRmmSgXI=; b=kXj7cPCoC1pXJ8RZeAQ/pIJGTOQSDKMiD62dvhyQVwmsQwhVZ134gx3IyUKKZN9Boq oVx+lU6bIyMoV4wwa88+38lNX5cnetrV7U+25NgEKAIjKP2MqqLBBmQv18sWnFk9HuMC 4LUpfJAZXhnqbifDa2YtKm5O+gltiwpCO5n1RGhrl4YcArYIfMi/BT/2LKxVTxHeqchi UT5Hl8sUR5i5eUoMkeeBk4V2gXUfeSI0S+MSP+1RFVm8J+u7TGwgtww2mg9pbA/tJvYx f5y2YZ+q26hs0ygVjqjUiTfigiNOysClJol1WtZl0szOovypcAjlb0CsJbCgGUbRd50S +5dA== X-Forwarded-Encrypted: i=1; AJvYcCU8jIHtQNmPnvN2ByNBw0xkg5lAoWTt1j5mFIghzy9WanxYDtY+eSRQhfEDggWTj4h5PKDwnO0a+14V2A==@vger.kernel.org, AJvYcCUdXTv+GI5UpsemjFDWMu9WzBMJxgC7JF3TvyPFGirZ23jGdHWC0H3LL4eas6jUqRClaznj5hWMFiYiBBuw@vger.kernel.org, AJvYcCXC9yd5xB1Wc+avgHlgyWJAYQdFv5ugUyrXLNocVF1ga5h5JwPe6u823iKWamBQ/J0iMkPS3Te+eJLi6sI=@vger.kernel.org, AJvYcCXnzzMdNt+yHKe2cxIQQbeoqOYV+fV0tRKnxUQI04zpV0t52DwjV74Jm345QTxkKK1LwHsT/l5uymrD@vger.kernel.org X-Gm-Message-State: AOJu0YyjhgjBO6yJwS/sc1vl2hwYXJz8nXpemxanuvptFNVcgFuCEphh LVYB9L0bkmESJjCAhcQr/jKTjupPEToIZgDi95iM93kcAmXej2q7 X-Gm-Gg: ASbGncvk4H4jH6GluxoM4B87ra/lvNczPvsEqE+AGsROUrIA0ldkeiTcT+8jqnZidv1 RG1z1wv9K1mobCx6PtP04PFgOPtXm9Z3FmJ1B1GOGtc+QuLq+9MDqVf5TsteDltzJHgp4eDghqz OwpGA0p5iD/lAVRcCr2FVAnKZ6+Ab5LXolI/vLLL7Cf8Q97CjGxF0e5ymY1UOU4PldAK6n3AAxJ Wis/WpGtQfEdukdjGmfro/P+XsIhFatX1edIOPezTL0Sw2yl7zZa4aXGEMlGd3dBiS7xRdx8D5A yzKwirq7TJDhzjD9/z8C7uPW6L8nOhAk4JnaLW3gx5k2+M41d/U+8DeVCQ== X-Google-Smtp-Source: AGHT+IHutThyGnIQqvbIW7Z/8kxkfEm3URL5upQB6kksolklRRYFKs6NUWaDZnidc7rD2PSGBBS0mw== X-Received: by 2002:a17:907:5c1:b0:abf:4bde:51b1 with SMTP id a640c23a62f3a-ac252aadb09mr788726766b.21.1741458880189; Sat, 08 Mar 2025 10:34:40 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:39 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 03/24] dt-bindings: media: i2c: max96717: add support for I2C ATR Date: Sat, 8 Mar 2025 20:33:32 +0200 Message-ID: <20250308183410.3013996-4-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX96717 is capable of address translation for the connected I2C slaves. Add support for I2C ATR while keeping I2C gate for compatibility to support this usecase. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96717.yaml | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml index 1026678a17a7..7d77cc9dcd96 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml @@ -83,14 +83,6 @@ properties: required: - port@1 - i2c-gate: - $ref: /schemas/i2c/i2c-gate.yaml - unevaluatedProperties: false - description: - The MAX96717 will forward the I2C requests from the - incoming GMSL2 link. Therefore, it supports an i2c-gate - subnode to configure a sensor. - required: - compatible - reg @@ -98,6 +90,32 @@ required: additionalProperties: false +allOf: + - $ref: /schemas/i2c/i2c-atr.yaml# + + - oneOf: + - properties: + i2c-gate: + $ref: /schemas/i2c/i2c-gate.yaml + unevaluatedProperties: false + description: + The MAX96717 will forward the I2C requests from the + incoming GMSL2 link. Therefore, it supports an i2c-gate + subnode to configure a sensor. + + - properties: + i2c-alias-pool: + maxItems: 2 + + i2c-atr: + patternProperties: + '^i2c@0': + $ref: /schemas/i2c/i2c-controller.yaml# + properties: + reg: + items: + max: 0 + examples: - | #include From patchwork Sat Mar 8 18:33:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872059 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AED0D20FAA2; Sat, 8 Mar 2025 18:34:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458888; cv=none; b=p0FrWIKk4hcaleHSfIEosW4faH/IJTm7+BVg06xAH55lO6+scXyRPSocPcXEZay/Qs05judsXMDUinEDaUw4+FXRjlTvM7kWRsETpJBlHEQMARZ8Q9uTgy0v5Hhl2r4ZLspvyxG0zaA+rOFEV19us4vsZySmooltFZUN3h9fXPk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458888; c=relaxed/simple; bh=JcNX+Uwj8MrIGD510BeCEpEVIg+bwj5e+9GO+9IhS7U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h1Nrz9XO4uCUVWBUnu9g8BRA9snwyecnaVyn6aJopBKta1FIjy6IC8MBRUsNRP4ZWc9JJZuFJM4kx+W+KnT+nJarbO3Oov9rEDxn3qhvk4rRcg80DE8uMjQlxXb3D+DbeUVuOOTn7jI2QljvVnShnsaFDvsMluIEVSsc7Dz1KrI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=mmGXP7k3; arc=none smtp.client-ip=209.85.208.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="mmGXP7k3" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-5e5deb6482cso4248022a12.1; Sat, 08 Mar 2025 10:34:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458884; x=1742063684; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=H3B4HVT5Pw89yNuuwGAR+e1ksx1vA1Amc86HOn9OXiU=; b=mmGXP7k3SZSDdVAdUpA4k6ONX6KpRfb2jojILfC/uuhu/zAPHxprcUNdUbuZ811Gl6 Yg6npTW17Q2qwMndLf2mmkmdjKk9IfPy8jqyDb/s1qAXB+BnaPaUPUW/mHRfb4B+9Ua4 Y47LLLkP36sEcurfG4UMwbgtkwgekFqohqA5ufZSN8dt9g6aCufz0QjPW84dT11W2B52 u0hAMP+JvhS2rFT+b3CBQUFzsLz+GWlmIvWB9AUWzfFZur7zjvze8qcvYao1+ah3kzwC YVsOtvu15CxV8d2ZGXF6vhYC7d8opKBgF5xGzWn8D7sJ+CfCMU5EtZQRVpMhwFQ1NvK4 7i1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458884; x=1742063684; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H3B4HVT5Pw89yNuuwGAR+e1ksx1vA1Amc86HOn9OXiU=; b=bfcgwB1ITgYb8CXSMbchnKhQiym/AtUyHwsG1IkLnoD7IfXf9H7ZnkWEy1rISjfIPa kOKAtgUToU0dRIrGVxYKho1a+rb6bRUCcXntgkuC+0EwKVJprUnxgUwmCmDonLcMtw2B jfeNXH/esvd0OS8BKEf5dIbbC/3JJUR4eGIL6Eq5R0rbUWUXGsJeYWy2UrXcqDVdo7FQ bqRcD9Q05O41k/cC4KpT9Zz7F0zaFpJhLpM/9W9R51T2n80BS1B7R5Z3rfBZTqoyMxw5 vkYtUPxLLTgj1jOPpRPHRzqhbj1po1IXEI78b4XZwTvxlLidDcVtHmnaTJIDayyEqkbT 4lyw== X-Forwarded-Encrypted: i=1; AJvYcCUv3UqNMNXHLCionUTky6M0rajst/yskBtZBobDDdKpulqhC6ZuZu6aklEn3B5B3c7n6iqQIvh7uks2@vger.kernel.org, AJvYcCW/k5FHvd2sgvr06ImLsE7rBes9xJ4cGcVa2ByVt9ocFVddMCmDmI6CUnKV0zvN75kQZmXfUiX1DAaoh7SH@vger.kernel.org, AJvYcCWW8hWjALFdfKu0AsssxmKBR+RCXK/uJriWAQ41ChSvi/Ox1XdAU65vIGkN5QakwXtxWkdLlUNXA73Qdw==@vger.kernel.org, AJvYcCXXo+iOfu6BZoh27YuTjPy8GY1jDQIWyEmvvjCAKUh+koVBoSlPY7kWdcdFfFfS2GodF0Dq7ikF8MtBIDI=@vger.kernel.org X-Gm-Message-State: AOJu0Ywcnd+cU/uNAMPZV/yVa2aKwCsukkX8tGGO8iMGDDgiRAk3VDaB 2Vu5ygB6dgmSKc+eDtxPvyRlvWeQaZMvYMDVzHUHdi1qrkpgQCKB X-Gm-Gg: ASbGncvjkrH56ACgJ3H+Sjio/YYe/sQKRc1DsjhQlKpRoObB8dWRZC2Q3QElyV3GaQY eux/zIyH+9rDCM/xWA0tR17B9/Lf010r3NP/Iusb4t4yNrpo4RvXf1C4cERDezzhkooNbHU4hVQ bFpnIMwbPAgtv34BVFXp3LGu2Qedkl4XHBakJA6pXsjdpiknFNqFyROBkEDElKjHt1eQrd+2GzW Yln+w0Fwp43YX/uFYhEbOBh5d4M2jnS0r690BPzaMls3Ae7vEfosOFmoJTUJhwbNdq2vbuxnn2d P69rcwS8Ew9Qcoms1yDtr+jZn2vZOSGkv8UcLaZQhdl4bGLmy5FmjiSP3A== X-Google-Smtp-Source: AGHT+IFNSueh0kjG5Dw4oKrSBt0pxkCJRfwG8SDYdVUY+KWspoiw5fa0VzHeIZu860SzagBERe1Ohw== X-Received: by 2002:a17:907:a4c7:b0:abf:6f95:22fc with SMTP id a640c23a62f3a-ac26cc768f8mr411691166b.28.1741458883641; Sat, 08 Mar 2025 10:34:43 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:43 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 04/24] dt-bindings: media: i2c: max96717: add support for pinctrl/pinconf Date: Sat, 8 Mar 2025 20:33:33 +0200 Message-ID: <20250308183410.3013996-5-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX96717 is capable of configuring various pin properties. Add pinctrl/pinconf properties to support this usecase. Signed-off-by: Cosmin Tanislav --- .../media/i2c/maxim,max96717-pinctrl.yaml | 71 +++++++++++++++++++ .../bindings/media/i2c/maxim,max96717.yaml | 16 ++++- MAINTAINERS | 1 + 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml new file mode 100644 index 000000000000..9480d3127643 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2025 Analog Devices Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/maxim,max96717-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Maxim GMSL2 Serializer Pinctrl + +maintainers: + - Cosmin Tanislav + +allOf: + - $ref: /schemas/pinctrl/pincfg-node.yaml# + - $ref: /schemas/pinctrl/pinmux-node.yaml# + +unevaluatedProperties: false + +properties: + function: true + pins: true + drive-open-drain: true + drive-push-pull: true + bias-disable: true + bias-pull-up: true + bias-pull-down: true + output-disable: true + output-enable: true + output-low: true + output-high: true + slew-rate: true + input-enable: true + + maxim,jitter-compensation: + type: boolean + description: Enables jitter compensation. + + maxim,gmsl-tx: + type: boolean + description: Enable transmitting pin value to GMSL link. + + maxim,gmsl-rx: + type: boolean + description: Enable receiving pin value from GMSL link. + + maxim,gmsl-tx-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Identifier used while transmitting value to GMSL link. + Default value matches the pin number. + min: 0 + max: 31 + + maxim,gmsl-rx-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Identifier used while receiving value from GMSL link. + Default value matches the pin number. + min: 0 + max: 31 + + maxim,rclkout-clock: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Clock value. + 0 - XTAL / 1 = 25MHz + 1 - XTAL / 2 = 12.5MHz + 2 - XTAL / 4 = 6.25MHz + 3 - Reference PLL output + min: 0 + max: 3 diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml index 7d77cc9dcd96..20114c252e01 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml @@ -88,7 +88,21 @@ required: - reg - ports -additionalProperties: false +additionalProperties: + anyOf: + - type: object + allOf: + - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml# + + unevaluatedProperties: false + + - type: object + additionalProperties: + type: object + allOf: + - $ref: /schemas/media/i2c/maxim,max96717-pinctrl.yaml# + + unevaluatedProperties: false allOf: - $ref: /schemas/i2c/i2c-atr.yaml# diff --git a/MAINTAINERS b/MAINTAINERS index 8f463ebca056..f8ffb7cff9c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14201,6 +14201,7 @@ M: Julien Massot M: Cosmin Tanislav L: linux-media@vger.kernel.org S: Maintained +F: Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml F: Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml F: drivers/media/i2c/max96717.c From patchwork Sat Mar 8 18:33:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871788 Received: from mail-ed1-f50.google.com (mail-ed1-f50.google.com [209.85.208.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F3780211A33; Sat, 8 Mar 2025 18:34:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458890; cv=none; b=nnN0EYhHnFKxxTxppEah1uIEKr9v2RowW60j5PpVa6KVshjfx1QtLX3UE0TJObNNCy6Bh0xqCAHpKExX3vr/YC0v0R2YGaf1CkZ0V6Jizonz9AwD/lEhxQCElzsMKBihRwEM3FBrhd6UaR8+m8Pkta06BzQmuE6KOxWT0q1Kgdg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458890; c=relaxed/simple; bh=5BmJ708+8yLNhEiLFxS9ZrT1GPmVWS8r+iO9v8SdOuU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FKxWhc3G3fIG7NnpDfrGWrwnvMTyoxLXZ5bIyzjG1YWjPm8q/zw/QrIp85j4iH+D2m4BKKaIDza2hQqznbKO5hIQti+8Fgns6R69TPgj8rDnc4z+HQP7uJXoRDygZiFiqQ0BrBqPBVLtPLyeu8yWE21sbBNVhVUyqMjw/hoH8mE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=lJ9S4yzH; arc=none smtp.client-ip=209.85.208.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="lJ9S4yzH" Received: by mail-ed1-f50.google.com with SMTP id 4fb4d7f45d1cf-5e5c7d6b96fso4772665a12.3; Sat, 08 Mar 2025 10:34:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458887; x=1742063687; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=niTukLIvAiAEZdTX9VzP25J+OMwBy7xtkz5/2stDFtA=; b=lJ9S4yzHMJPmliNAAxnmqQegUhs9/pF8Em9gBiymNEwh6Zeg2v7QcEE45Afxni0gJG N/ZcvEQbZIfEB4Cz2EO7nhFuTg8qPVPGFy5voBPjtcGeSYcShqmG+ELH6X9qbmUuItwv e2rmG3zLocGRnQcOk5BdzZ/O1yH4fbqqKqKAoNnxSlOFr+f4sHplMc40xYmQNgzn6GVe 0/VxkzrH2ltN+QgdD27rnDMtC+3cMRuJ8JkNeEM+N6JBRAycCs2EUnGZxNkLLrQa2+W6 etkx2nDm9Qemtm1MSHEL4YQRm3AxVvAYZDLmyRl0+yM+cl6iF7cuy8GlGk3oew17i+Jr w1Cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458887; x=1742063687; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=niTukLIvAiAEZdTX9VzP25J+OMwBy7xtkz5/2stDFtA=; b=GDeuHYY25BLdeqyRUCMWSy0J2xPVGSDgVVsIGV1MnIKBihcoI6oPmMcX+CZF8SINfn KZhxKghkgX54IoA4b6ulV+uMu+/DBzz0/3uGVCkmTp+nDTE8PxQwW11bNsWCUZXxZ52e 24lDOJuptQmZtwwl0IMMa9mnMrf5O9in2+rO1TEFpwLP5l3bwEedB7K6rVN0Z+MrhU/n 0Xci9mi2aOj/VuR9UmYPLU4ASdEOkfT9Xfg0zXDC+YoYvX4DOe33B9bGA/81Zf6kxqNm Say2kAZ4tCpTv6Lgmxt2m/aKHlb+Fr+Op2U29UBs9dCRgUOutVr3z9HOIw+uz+JZmPNK blhg== X-Forwarded-Encrypted: i=1; AJvYcCUTBghGCC7htYqK95vU2+CeVCpTWhPmPQEAtTwURz/0XkIjJ1CYeNWoRXNjoPlXoQfm1y5rJ2UUVtmhCQ==@vger.kernel.org, AJvYcCUcx8oh9jNS/wUpVavApDV5pq37eWkTb8GMM669YS5tWatkklj/ET/XPKQw1QmAHmS5F7Bc0n/g9MJj8RrM@vger.kernel.org, AJvYcCV4C2MVhKBNn9DoocW1pAefeGbLDppcfzRu9wjNqABO13e+G9ouDZCWcmq4TL8ZWXueeNfxxmzeE+n54K0=@vger.kernel.org, AJvYcCXBF6ycnZjKwFswJ8Mqz0ip7m7LikW+zfNzr0/Wll+zyf+Z0gxxICLqM2NZBCoOMm+bZJnRD5UXPffg@vger.kernel.org X-Gm-Message-State: AOJu0YxNHNSXjOqfO5Qnfvqwr5VOTCoHaZkl0vNtU6FImAYWYQIJH8pe Kf95uMVrAo3yUNAH2L2ykVUQuEvMqD6TPHzWe3QA/IAmz+eYalfI X-Gm-Gg: ASbGnct/0cvQMRw5h1Rvkeuf+KW79e8F2cMInKQE+Alg7E9hdJtKjTIOMQWdcVMWiW9 cdvPqZZw23QYImO3K4Xv14Qu3u3PO0wzexHNJzAf62V1AbZFXak5AHHVsPU/es8qccvlI26yHVJ 1lmOIpRB50XihvNigfzJx2CBFIQHvGjpU4YOW7pkCngT55aWqCjArn4Dd/hJxcQkF/uLvHchKLQ uWInq0lltRJUPglALaqVJAIiv9HJp13gYk1HLG4GEan5xgIWwHzU+b30sgLVlkXPvB0cpgNv3YU n3JIILST6PX7kzf86+CCsJp9kAjGdrWgm76aRONFhvJjDJk4bJrM8N/eIg== X-Google-Smtp-Source: AGHT+IEYfnZZSKKwlnhzVkFTovCEetnxmc3aAYiYEW+59CxQQ6vlMjKTl8zXdIYjCmymG9n4u7FXQg== X-Received: by 2002:a17:906:f59c:b0:abf:6389:6d19 with SMTP id a640c23a62f3a-ac252a9e5demr952699666b.15.1741458887103; Sat, 08 Mar 2025 10:34:47 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:46 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 05/24] dt-bindings: media: i2c: max96717: add support for MAX9295A Date: Sat, 8 Mar 2025 20:33:34 +0200 Message-ID: <20250308183410.3013996-6-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX9295A is an older variant of the MAX96717 which does not support tunnel mode. Document the compatibility. Signed-off-by: Cosmin Tanislav --- .../devicetree/bindings/media/i2c/maxim,max96717.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml index 20114c252e01..1e5b85167d0e 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml @@ -24,11 +24,14 @@ description: The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the forward direction and 187.5Mbps in the reverse direction. + MAX96717F only supports a fixed rate of 3Gbps in the forward direction. + MAX9295A only supports pixel mode. properties: compatible: oneOf: + - const: maxim,max9295a - const: maxim,max96717f - items: - enum: From patchwork Sat Mar 8 18:33:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872058 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 23D462135DC; Sat, 8 Mar 2025 18:34:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458894; cv=none; b=u1IKxs7b/86MUykHN6iu5pqX/4poP1cHwbotCj18ZtBX/53Eux8RxyxNHVDqhC1MxrOEK2sHRY9cdAQM04IfFuhIwioaW/nB8Jm5zIyG2pz4pd2ZNyOZiLbKiYvPjbSUtbQ5kKkR+YTGb3P7qod9UWhziTKmJvmakGvFagXdu2I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458894; c=relaxed/simple; bh=BXlA8lciQJfJQ9PsocdwlLiXf5zbL4riTB1hSsRUQWY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Jbkvl92imW3Z1El+xIV4rJoqam7Eh4PdXy1Txegxn+yA2RM/Wf2yoo5klpURLVhE4csuGXwWI1VtSAJitKYLsItxia4hcBuDI8wxIrcnQw+y9tuDmM4TLHUUoaWbC9QvhBMioQ+2Kgy5VIJ32kb74ZWvzUI+R7YsKFdpvTVYF2Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=atDeo4A0; arc=none smtp.client-ip=209.85.208.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="atDeo4A0" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-5e6194e9d2cso1217572a12.2; Sat, 08 Mar 2025 10:34:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458891; x=1742063691; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aaoNQqy4aLD9/xA6TRYAtkr7klI/0e6BppeUXZTiyUI=; b=atDeo4A0HxyXZHKpHLg5e2XDzONAz6CUU/6/fME4exeC71sOAgYqMZPTNO6EIzdAFt dG7afYS6k+sdApdX0ZBdSz6Enuee8ZRGKYSdhsAxnOi623xEGfkEQrI1k7T4TCiIL+8+ /AyJRigh0ShVdJThfz6lPf8P9JqUo32bOf6ccb94knlk5vauXWBFk8H/uok6OnHd3Wth mtZRhYdbePVOBxYfhgP9KXUUi8GHvb1GusbzUEYfrzlbrOfEeXRPlk9IQm0SpIJkmLNb 9Jywm4imYUZN+ikltJD8oLWan6HDoq6gEfjACRUd+oKhkS7Kabp0iZFZKB52lZFUNl4f OkNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458891; x=1742063691; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aaoNQqy4aLD9/xA6TRYAtkr7klI/0e6BppeUXZTiyUI=; b=Q48hUf/6ISfZ4ab2IJ6YfiB/1NWCNe8CGBi0po+8n8Y76lv+ZtIltFQgdR5rI00Jrv 9JBA8CzIsnFN/OvO7gk8usXmzjWi6dTXN3DLcKQUWIvTEtFgaYTuQqcWVlvNPMti2IS+ wcsC2D7yCuCt6D1QOsX86WaMtJkK5Z/ynhEheO/MuFFIydCaEOxyEtlo6dwZoudOvWzV NLzIlVC61BvcBDtv6y2dkNviv23MJaWveWq8m0GwlNZgLZrGUNOuaYCQMNTZ2kilJ0/T 6bEao0Qr1SsJILy83UJhf/wB+3HqGqxNT6xCmYZR+iTbfGOeoAzuA4gvHEmWZMd7kKws yh3A== X-Forwarded-Encrypted: i=1; AJvYcCUX4lldk9q9ZIYDAPMnSezusHaOJ7xXh/EaTfOuA5Y2HSWNlTk27x+aF4C/z65hd7AnIfqr+Llppl6ApVU=@vger.kernel.org, AJvYcCVDJ+synmjL8tsLVWfcV8ZOE5p7WfQPXCEvbCoLpXM8y5OynXZB3ItDZYJRsrK+vH0sCMvhGmLcgBIiqvO+@vger.kernel.org, AJvYcCWsv4Hikui5yLSPruk+igLSNtJohGZuxuYekvP3n2QZ3DeIAaQvI+iRglmGPY/75IZdU87CsDdYS6CuYQ==@vger.kernel.org, AJvYcCWx8woJ/pc7Sp26EojY56WVQo7zgun9n+FF+EffaGrAP2KDJUR9K0x5c9SnOzLpzRid92l3v0ohD1Zu@vger.kernel.org X-Gm-Message-State: AOJu0YyBZQ3qbzNetjUu2k858Q4UO/iRBqkSwlwdQClKt8lIMN1BKPbf 2RAyS78H924oBXrKYoFENxdwf3mRv98rI++SKFNNMG0hXfvp8Pu4 X-Gm-Gg: ASbGncvW+67myI554MQzrweB+wD/s0kuau2ORZPEJfMcEbcmlGZT4jYEaR3njJ90CVl zKnAgIRRdAtSUo1T5UUGFQiGrsTjNCdhmEcNK5QgpCgZGSut92qfR80Q6Xz9EbTL4+yNa/lOxFZ XxTUaWPO4WHzqAiY6W6yiG9OeTwbjEi7hD++yM1Y/NXAnDQSRiu8FLecwlKF8yb08BRSWxbMT8r gH+ugNdaVgeNUBQL6m1WF6mpk5b5egSU9VXqCu+LTKihARUTN2ONau4hYSNZPdzJST82/zsUT4f nLhrH4Dr89NObny9t6A3Sdj8kSwjQS9pH45u7Jgv6s4gLrN5S3+7JQS7QA== X-Google-Smtp-Source: AGHT+IFezFam6alDx90TUfBdNmoublXmOdXfqhoT08gBkDkGLkO7nMPBmg+CdG3FyRvs8OOwhJtfsw== X-Received: by 2002:a17:907:7ba4:b0:abc:c34:4130 with SMTP id a640c23a62f3a-ac2525f958amr896455566b.18.1741458891246; Sat, 08 Mar 2025 10:34:51 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:50 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 06/24] dt-bindings: media: i2c: max96717: add support for MAX96793 Date: Sat, 8 Mar 2025 20:33:35 +0200 Message-ID: <20250308183410.3013996-7-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX96793 is a newer variant of the MAX96717 which also supports GMSL3 links. Document this compatibility. Signed-off-by: Cosmin Tanislav --- Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml index 1e5b85167d0e..2d7440049318 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml @@ -27,6 +27,7 @@ description: MAX96717F only supports a fixed rate of 3Gbps in the forward direction. MAX9295A only supports pixel mode. + MAX96793 also supports GMSL3 mode. properties: compatible: @@ -36,6 +37,7 @@ properties: - items: - enum: - maxim,max96717 + - maxim,max96793 - const: maxim,max96717f '#gpio-cells': From patchwork Sat Mar 8 18:33:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871787 Received: from mail-ej1-f54.google.com (mail-ej1-f54.google.com [209.85.218.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 97B23214214; Sat, 8 Mar 2025 18:34:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458898; cv=none; b=aYHB/POoFB4tfv3cRiPWdkZq1/tHsw1Zx8bBZzjUwc0Jm3ZY5uDyDgS24feUXUo23p5goWiNeI2aDJSQDcFLTGW83axXMTdWbV278+2gI4NRBGI1TvXhC6yqC0EPLbuPo3Eo7eIRSTN+H1sXyvcce8dJ5xSW9+uUTUcXHvz4HWY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458898; c=relaxed/simple; bh=aY2OdPtIEjCbNO8extSTSEs8Nmwq4TVYO4BTZvMhQEE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Yq9k5RaYG07wpgjDspIziKzWWhJUbhyYNKxv60NiyjnUescv+FfEhrDm1GqNpRjsyIT3bx2AWPx+LcfK+/uv8Vb1Ps2pVp2x+k6HB/sbA9lrBaxGfNLhQPa+0Y/MXKaCdlJAJgoXsc3GgK5eXve+47UFleFX7zpTBd9IKT7jSWg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IyMoFqut; arc=none smtp.client-ip=209.85.218.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IyMoFqut" Received: by mail-ej1-f54.google.com with SMTP id a640c23a62f3a-abf5f4e82caso566404866b.1; Sat, 08 Mar 2025 10:34:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458895; x=1742063695; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=a0RTV5VskyQw4SxBnUu+Jki4ojhQmudu+bw9SS3hYws=; b=IyMoFqutwo4jqSwWsvRJpjU8fAwOCEMTsadfkqxz9GDPAN4kY+sNFzTWICCLJGO8Vp oxVMcrGRJopOZNEosW1OXExd9tZ+Qe4ayb4m/YFWojT1x2CPNvnXmLElCq9Z10oh0u9r biDSACaIJL9HC4tfLcSpNJQYSBDqfUVbkfDByio2S3MSREwP58cJJrRy/xu3kBsoX/Bo cZw5OdrJqlvtd2s/VavlwZRaNKFfSpq2mryIk66Iy6y/KIK5gDoXZ4QaO7IQz/1LJRp9 mfqNGEXOifF6afq4QpnBfcoj6xOMgm8vl/Mk97yltJjGtykhjdoH55TP5unfFcTvJhcG 8b4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458895; x=1742063695; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=a0RTV5VskyQw4SxBnUu+Jki4ojhQmudu+bw9SS3hYws=; b=nY/uz0KNHtCgId+JeS8tBEdfu+GNS36n/qzgaK7F/Xnki2ExGecTlDcg48SEpX6Sf/ eVtHR9nkxUQnV9KUgp3018mInJIxBU2YME7JihIiFUbxNFc9foz2Ekt+1EKHx8mQD6Ws IHVJtnVBdZqqxX6xPi4XKir3Q6RSJDqNSSGvxhLi2QxpbJWCXbMs3CXyTOxIEQY5ykPY IdD0IeXhV3a+xx7uzfN+7EdmSLSEeVEn2TOpMAaiwr5Gcwph+2jBi3wSPgPv5hLNou5J eiJFZNcy8kMwZaf+JVFKTehBytbij4hzv5FnEHvRGDzHR1rgFe4/SQw5Oaw7CyVk93Cs XJpA== X-Forwarded-Encrypted: i=1; AJvYcCUuXPZYH7US+pr6si3eQpQ+EUz8D+ZDkAqKFT9UF4j2BGOHbHWsEDVGxBQMJVO9sbqxxXQs7YtfwoQLLkVP@vger.kernel.org, AJvYcCVJKyuPYrMFrUt3RFXfXTn3RnCB+SJkeyTAGIoWxBbYQ1U3H7jwwx0aGorawdrrB9TiF5Zu8b+KTZkRCOs=@vger.kernel.org, AJvYcCXOap/sHur6sO9jGeBMoL6qG8tW3oeuPz0DsqMnQ3myD5tr93pLeNxkLVnTcQQgrKtHeSrp4vbhvMpT@vger.kernel.org, AJvYcCXwAKZeQ45HziLalZ5nQ73ri2YwzB1ck+N24k/NGYY7QSxizs7dyiBx0kpLOP0yGr5YzgOahX5GY3eNJw==@vger.kernel.org X-Gm-Message-State: AOJu0YzHXxwxqX5U6YG190cpqDS4qJzcbC35RdhylGR++8Uq7rdZq6jh qZm1cMErdBVNri01JsA0Q/kUKWmlZpNFstMKfs3xkNXMlLdL+WZR X-Gm-Gg: ASbGncumnzAHI7LIsWG1o+Rk3j2AjYworr6E9R3scgkHWChyUtMNS4DY0ZITyf8kN1k hfJLORFiPmpW2VnQ/fpo8KMKFqg8nvlFORkHeML+P2fxV7rWIHx33Zmjwugl94uIpNOMfaJHdGQ X5nmugrTS9lCf1Io6OwupzN3tnKqMXtt/SIkc0XKxa04N2vSoHAQoN4jA7Ie5uopeRyC5PZp7di BAzq9Gf3uo7i8lQPPQwxGu/vctlNcUyryR1+vnhsZbf+BUvcL0HNTSGfOQKsoij7BP3tWKTfcnV 4yeVjPRHWBTR5Dc/mjl7ALqLtzqt+pKpuyE+VfXFp+Dva6qflZtgwGbQZw== X-Google-Smtp-Source: AGHT+IGUMLDPU+kLqQqakvTwdZEbBOPDJZa3MFxXA26YIFzmlmYTztaOBI2ZGBOinmdRJLH3zGhkDQ== X-Received: by 2002:a17:906:7303:b0:ac2:3ea:c23c with SMTP id a640c23a62f3a-ac25273a0f7mr996974166b.5.1741458894715; Sat, 08 Mar 2025 10:34:54 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:54 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 07/24] dt-bindings: media: i2c: max96714: add myself as maintainer Date: Sat, 8 Mar 2025 20:33:36 +0200 Message-ID: <20250308183410.3013996-8-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Analog Devices is taking responsability for the maintenance of the Maxim GMSL2/3 devices. Add myself to the maintainers list and to the device tree bindings. Signed-off-by: Cosmin Tanislav --- Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml | 1 + MAINTAINERS | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index 3ace50e11921..44667b74296c 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -9,6 +9,7 @@ title: Maxim MAX96714 GMSL2 to CSI-2 Deserializer maintainers: - Julien Massot + - Cosmin Tanislav description: The MAX96714 deserializer converts GMSL2 serial inputs into MIPI diff --git a/MAINTAINERS b/MAINTAINERS index f8ffb7cff9c5..7fcdcc57c8ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14191,6 +14191,7 @@ F: drivers/staging/media/max96712/max96712.c MAX96714 GMSL2 DESERIALIZER DRIVER M: Julien Massot +M: Cosmin Tanislav L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml From patchwork Sat Mar 8 18:33:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872057 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 05BE7214A9C; Sat, 8 Mar 2025 18:35:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458902; cv=none; b=Q9/0EOLKFDdSOSEds6DwlvQLw7Mrl7IS5nvtxVgTm0ytNIdBN3P7cGaYS/tQngRHlo3Beai994R1dFYzHrkldwp1inTFXzp3uED8YOoYMKdiXZvPbFHk8kX0nAZOFeBBgzRg2jEkLkBylq2/tryceSHOFjucEaX4mepBAHlAFxo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458902; c=relaxed/simple; bh=IbJ825DoJSnWvL66nJwG6v88Bdb2MBA2bKmwG3S/oCE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FtVY/6/sNrE5OyMtFllog1UkpQjKFfnNNaz1/7Ei2QGmXoQoC2RePDxHKeE5B36/iPSF1DAz32sDFIidUcD9769MdDjZz4TGodFsxjxo23b8P3GgBrr2fkS/qohYG2rMoG/YV7xR0fB9DC6C1llNdWteHR6tw0cW0VMQycHdFIo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Sbolt3CS; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Sbolt3CS" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-aaedd529ba1so361110766b.1; Sat, 08 Mar 2025 10:35:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458899; x=1742063699; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jAQhDQpxTrgqUBQBlshc++aOCj5PQ0JybfWXWmVqz2c=; b=Sbolt3CSxz4R30yp/3Oz/nXZDIMJ6m6r3bsUS/g5ekbEIBm4EvCGo/8ckjb1xF5zw7 SmEgDmtJL4k4nFi/ZriFQSmQ6ZO9Lg7x7zQ5WHaoLUAAIHFx8OQNErYoc2kQcyIEKSDB Ibfs+HG2ChycKmBUGxw+TKwp1etZz86QLDBST7HAUAPM79j9fwotqdKKHHrHHHCiKqJH WhgU5q2ER0mgxNrv8G/QyKC+1/i0mokp3UlbXgLI2CmJ06n6ThzJ7uHJaQ2jIZaavTtt Siq9U/I5KIqnRWxV/ISsiwC8xeFGGAoMrrsbGWDO+wic8DhJNgVeyWG+KkFpFJZ5Z7kB 4inA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458899; x=1742063699; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jAQhDQpxTrgqUBQBlshc++aOCj5PQ0JybfWXWmVqz2c=; b=X3Gts9hwGfpKJBDrQSUqCy0E0I7IltowzKvLBBJ9j0YjqZHkBLA2jgDo6P+p9xCYo3 JJVykNt+8BWHPa+ecevPeqkmBvAzTrb+ouPDmyBynfhBaosYT0IZ5bgDrDf+g4ZMH72k H299yCowTKzFLoI0jPCA+us1FFHYAvfv+fVjxEKI26IFSoIQIdzHj6TrC2JQ8kFdEACv eOoZGQlyaTsq9Vt1ZpxcJKhGOKhP8+7nU7PGTTWUh9n1rFoaT4+uzAQPevt0WffG1DZv TiLWZwebueUZr4xDoXWFd/zbDJA6fZZ5/fKF9Ka1/sXNFLj/A7URyktelVln9DccAS6M 6O2g== X-Forwarded-Encrypted: i=1; AJvYcCUC2884r2cWZ6+0wWAf4rIy0e+M8yN2y1uQdgBsBNAISo/xtHayvvOttocmvhXHrdGgSquPei19l99LAg==@vger.kernel.org, AJvYcCXJw6ZsV7ED3vpIL5AqVSP/a5gfBIC4L/coYJv+FyFPcEH79dZIxd5y9ZGXPnPTzQjm2ITaFhrBSpufThA=@vger.kernel.org, AJvYcCXR1uRL3S+356vACjAEdEw3BSGMXrZjJuRL2VBcwKZnv784kAlG05ZwWpv8fREnxNTo61TtPDL1oID79fvk@vger.kernel.org, AJvYcCXxDj9qpxgo7WMXsSou+Fsd7sfwrhC3+UsoDlD0329/UjtNa40mpJg1JCyjd1zkLkw5jWpZngswl3cj@vger.kernel.org X-Gm-Message-State: AOJu0YzgEUnF7cFYxtRiztlU4CkAOh1SwmHsyTK4t9NvWO9/pgewbBcv ZvyfHU2q4H4qjvRdlCCvmGiLblpTVmxDDYb4GWca2vGVe4P6j9NR X-Gm-Gg: ASbGnctbdHalwkHxD682+GVutFVh/x2pua2l/5DiUe0wG9uF1KJuBGrQ4FFqhh1NXgA SoFqtZ889/SUlIra8gk4RJ2pPRx+Dk1eKia+siQqxzrHHGKMVdtfuiNVVQxhuH61Bo1mxgFQ7DB GJOrNvEQbk+43BwU9qSYBIIUA6zW/edVFjhZMHSWwZNMTyi56b/+M8IuhDLJPm9WJGa5Mm3r8V7 GylhAFnup5ChUNcL2KOTl1yg/OVzJme28yXXyNWffaWwFVLYjd8sn3YRJFBJiNYIfg/3AW8d7fh T95zD68V6n4cb3j7nZLAXdMQvheeFQ5gcH1fJ2h5QnF4YkTde4i8SmSYWQ== X-Google-Smtp-Source: AGHT+IH2YosUhqi+STAQ/nY4ti7PQvH7nJrNeEszlj7Q84z3kvlLkPrCo3BZtLhHfeHuHBAcm4ROyg== X-Received: by 2002:a05:6402:4617:b0:5e6:17d7:9a32 with SMTP id 4fb4d7f45d1cf-5e617d7bb68mr11479433a12.18.1741458899040; Sat, 08 Mar 2025 10:34:59 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:34:58 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 08/24] dt-bindings: media: i2c: max96714: reflow text Date: Sat, 8 Mar 2025 20:33:37 +0200 Message-ID: <20250308183410.3013996-9-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This text is using weird line lengths. Fix it. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96714.yaml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index 44667b74296c..2f453189338f 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -12,14 +12,13 @@ maintainers: - Cosmin Tanislav description: - The MAX96714 deserializer converts GMSL2 serial inputs into MIPI - CSI-2 D-PHY formatted output. The device allows the GMSL2 link to - simultaneously transmit bidirectional control-channel data while forward - video transmissions are in progress. The MAX96714 can connect to one - remotely located serializer using industry-standard coax or STP - interconnects. The device cans operate in pixel or tunnel mode. In pixel mode - the MAX96714 can select individual video stream, while the tunnel mode forward all - the MIPI data received by the serializer. + The MAX96714 deserializer converts GMSL2 serial inputs into MIPI CSI-2 D-PHY + formatted output. The device allows the GMSL2 link to simultaneously transmit + bidirectional control-channel data while forward video transmissions are in + progress. The MAX96714 can connect to one remotely located serializer using + industry-standard coax or STP interconnects. The device cans operate in pixel + or tunnel mode. In pixel mode the MAX96714 can select individual video stream, + while the tunnel mode forward all the MIPI data received by the serializer. The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the forward direction and 187.5Mbps in the reverse direction. From patchwork Sat Mar 8 18:33:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871786 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A9C42202F9A; Sat, 8 Mar 2025 18:35:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458906; cv=none; b=HIpYH5YW9+Lri+wEstuijoM8286uZUIusgxZbIWxud46OMyW00ID4xyJdKG63LslO2Y+otXOcH6m/0dAueXFfRyaDEy76+Gc5xTORO88d+QGXwiwQX0bxJMu+G+K9omnzI1O1wGzjRdfU9emJsWnCI3yg4nf+8Coqtwcc6lMGnw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458906; c=relaxed/simple; bh=r1mQgC4DmlmHWnSr+8d+ANzXlBEejCjCRSN8QOb6qhU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f0Pc8nMEbpVBMSPSyEcy931d/CtzpxfvSLAL1KPreqildrD2IcIzkKmX+75c/I2c6Y8GfRE/s0+z0Q9wFQr+AYHtd5pzHXXABntfP8jh58KNJI5MBqj+dZmRZRe4rvBtRApelyeu9w96Jlj9RlaQJgi+5dnxVfnZ32PH6FRK2iA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=HCNgpVxq; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HCNgpVxq" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-ac21c5d0ea0so353161766b.2; Sat, 08 Mar 2025 10:35:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458903; x=1742063703; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=pjrbihTdUtYGfD1XjXxp/0dpy7KX01NaPnhDGGHP5+A=; b=HCNgpVxqdWSy3BSZ5YiE8fw2NrAxXeGehqzfSTC3zM6hmrCBjv4T/ShrxvrPTKT0BN XYyhNJw4UulIDtdhxwqQekRLU3drXboq9no3wSBchejc47iMCiJBpIGumBH1MQMKzVMa +oKMAIMI24OsQSHBJyNeQKdWwwzqtrzu/GYx8b9MK0ZbmiAektFOymGDs5sqR+yDS4Ek QOiKkVqjKRBAkqLyRR7ILKmHgKo7VHtFxqiOn6gTm86w35F6CXK25j58k17GIHzdkFQR 8HLhwzCgboJ/08jdSRkUDCTI4RzEXxseBuqrCEnLWKYpq/bafPL26xAMC22VnNlm9JbV dhlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458903; x=1742063703; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pjrbihTdUtYGfD1XjXxp/0dpy7KX01NaPnhDGGHP5+A=; b=physdrqBonS4nT3SGaI6UwdqbYjikK/Xva6Z4ShK0tVRbELJD/54lODvfROVWBWO8/ 0ULuKSExV1Q1KOdrCm+OHeWDIu3oLBR6LD8SI5gVLwH45jMit4wCqlRvdtLp60DFFGmG 0e//spF3N1aEcbZLgprsfzq/svjV0Uk4igbGklJY5B5EjGmSRYYSXO91ayDWZOM7VIZY V//zoa/WOyOoBdZcBkzQkYZTgecAkeZajinBYaMQ0ObA0fZr0YnmjRoGEE6S0S+9I+uM Cf5R7uuz2QDvKQ6D3kFMLKs3IVy/lcbgHZbsPPnhlwekVJHLqSweQVqltIfxqbDfcUpZ sF7A== X-Forwarded-Encrypted: i=1; AJvYcCVVCYb4xNPrQssgc4BwkhsYJ0syqD3CRaHD3wOiD2F7QzfzqZ4TyhDIYxj/TEU6/dsuEIAGJR5EePjQDA==@vger.kernel.org, AJvYcCWG/apZalVpuXQ139WjaHYqccjIY8HwOfzV951QYv3DvV1xI1d9ooBQiQPrzYYB3BwCNRlrTZAce1HYJWM=@vger.kernel.org, AJvYcCWj/EB/DUrnNPgz32qXP3R5+8UipTYsNttoNdEtOMF5hUKcTrNX1aDGJt/7OC1Ra5HSJsF9k9NsGKJu@vger.kernel.org, AJvYcCWsG/iBai1t0tGcC1DkMfD4ZW+Aqb0XFYk8rODFp2D/jDl+9XmXBhtYRblKbpgCflYNR7gy447KtyhL3PM4@vger.kernel.org X-Gm-Message-State: AOJu0YxksBKuyQ3QtzohPJydd6rferCpSqPQqTSoKZhFmMvG7V+EzH+/ ttvv7ibu6hHf63etjifAlEA5aQMiXe/UV/HL8YW9myZ7tdwFNfFn X-Gm-Gg: ASbGnctQ3f5KT8E66++UEQlAP4FTsol30xefgy/A101CvhkrkA62rRECB1me/ApyZIx 9MFV11mjN3/p83PNIvFwuLKT93L41M/lgve/4XfwAGh+W7pexhWaanosRnBmViSKmAx26hMXnPf 9WC93laiOfiTvzbFVxEltQRVFzYSJg/5jyG2mc1yAbixbekgx85mXbzspLcQZMrdwhVWrpAEi56 NVCbPy8ThjzUvFRrivf6C1lDtY6XJKcZ0Adm2153RiZCOOEEx82wV/2gxNQ+brQQfCrxwdsibrN 7eQiU8Asu5PHT/cruQUbFlV1Wgu+jDv4I7VSkULXDmPwlor34tYVdLu7gn9kYJQstgxq X-Google-Smtp-Source: AGHT+IGwUeddAVefNrp/Ox4/s1rrU1bRHiJ+ldxf/aGAE6vsUOrAaQ/XHMxMfTJtL/YGjYojnUCfRw== X-Received: by 2002:a05:6402:280d:b0:5d0:bf5e:eb8 with SMTP id 4fb4d7f45d1cf-5e5e2468800mr19735826a12.23.1741458902826; Sat, 08 Mar 2025 10:35:02 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.34.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:02 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 09/24] dt-bindings: media: i2c: max96714: make i2c-gate conditional on compatible Date: Sat, 8 Mar 2025 20:33:38 +0200 Message-ID: <20250308183410.3013996-10-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Devices to be added in following patches don't use I2C gate. Make this property conditional on the compatible strings. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96714.yaml | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index 2f453189338f..d0a2aaf7df9c 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -84,14 +84,6 @@ properties: required: - port@1 - i2c-gate: - $ref: /schemas/i2c/i2c-gate.yaml - unevaluatedProperties: false - description: - The MAX96714 will pass through and forward the I2C requests from the - incoming I2C bus over the GMSL2 link. Therefore it supports an i2c-gate - subnode to configure a serializer. - port0-poc-supply: description: Regulator providing Power over Coax for the GMSL port @@ -101,6 +93,19 @@ required: - ports additionalProperties: false +allOf: + - if: + properties: + compatible: + contains: + enum: + - maxim,max96714 + - maxim,max96714f + then: + properties: + i2c-gate: + $ref: /schemas/i2c/i2c-gate.yaml + unevaluatedProperties: false examples: - | From patchwork Sat Mar 8 18:33:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872056 Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 296042153D2; Sat, 8 Mar 2025 18:35:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458909; cv=none; b=HyaqRyi91v4m+RybSfwReqGrC9MyyuXh4NAJvh+UQl20N2V3OBkt9O0+UEei2mOakgwK7du23FW5oquv7n2MG3tJGqxho81SkehQl2E2S8UY4hFjvjNNnRm9A/YD4GU1L0fank4BaMiJ85x1qhFnfNxF5pIOaMYATr1QxEtvhW4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458909; c=relaxed/simple; bh=EOp/22V/izo5AAhRS37CwT1hkJVaRpvHoWf6KSa5yZQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FNboPlbuYFqhEd3tNy/k2rJp09jHAfQAOL5GA6+RI0el3zuItKU9sl8OsMRso7MQgGqo9uRwogddAic2QMXdgsX4COV8XIM0u2NqvEUmU9pSw8sQoB5sNfDphL3GA8YaivVhlGTIneSZYP7gwehC+5GPmILgVVZE7XsS8mzmOJM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Hmy8/yF7; arc=none smtp.client-ip=209.85.208.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Hmy8/yF7" Received: by mail-ed1-f49.google.com with SMTP id 4fb4d7f45d1cf-5e56b229d60so7332936a12.0; Sat, 08 Mar 2025 10:35:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458906; x=1742063706; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lMGBxKdxUGyFUvUDQCN+Pu7Job2ef1gvSHKYwiDKEWE=; b=Hmy8/yF7qgjFQcDhoJ9kFN5hNQ0+5x1DdJv7XpTqTJCw6Hsh4zHFmEJxdrzSeIjhAQ vHuyMaE8u+0XnNgU8IUf/2G4Jlbim8bnk1UBf/bS9gksvTMNOBOuFvEAEiGBPZFDCN9F c8kC2O1w++pJnO1YcezeBW/zxtIuB2Re3Dxfep9d1VC654A+h+zhUw9+AwFh+bGFLcEB jMRe/kXea2QiVqQ3slaAeIFHqpCyHfn76yFEpaTgpZGR06HXSkGor/+UYHlH/IPza7hb 0/Zff9sddRj/+oOAAUpKXe5oym2FFWDXpEPjbNm5NWxgmfIoY92m1sCU3hpLE3jYuW2Q 14LQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458906; x=1742063706; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lMGBxKdxUGyFUvUDQCN+Pu7Job2ef1gvSHKYwiDKEWE=; b=QZ79U/SzigBihlovFyoHw5qhEz4GHqML1omaLZaynQojTWe9u7eAYW+9YdbbOyZBVK PCbSw3HChzUs3mPSip2ktZus0RTFZY/KT94kNkGslwrCe7VRq+wdTM4ZWC8kPZIkwRY4 pvJdJOJRlulPGogDt66PQHEj/IKFxo/NVie/CWqtEUf8fu1hAE7tKptDyZ1OIHxyCVhR fO8H9yObV0SS5i9RHFvrxo7K0TCxa3U0Rs6To8U+WvL7hY7LX76wA0DKps/z12aiDei4 GKqjBbbp5F5VjXISpyKRyPYwUeWfSz1AQFGhwk/gEAnCIQ8zFi27AYTUUSU/T46zx3OL bpfw== X-Forwarded-Encrypted: i=1; AJvYcCU+uO3nB7GLFKFrECFnMqPWERR5gO/kUdz1UoqfmFzWGF8RxlGsysfM2x2vpphR0DcJojBxvBnNRlHdwiw=@vger.kernel.org, AJvYcCW+hFDKDN76nHe2r8gLxkTrT3zqbDhTePAwmaxy5elqz7DsEJH1oQIa5PLKUcZCcql7pnlba/91ctQ0mx1B@vger.kernel.org, AJvYcCWL2yqE3rHXdnlBWXZMb+L4Z/3REUtqF3oH2Abi0p40lyCfipbhqiqmi4AkKEsBySAaOCSXl8zWqNtY@vger.kernel.org, AJvYcCXOI7WUpV9cIsTeOWFXOX52dmQ+iCPW03mEE4tasSCUWgbcGIFcJrBf8D4q0d5f2VfReGOaZdmmFTXN8g==@vger.kernel.org X-Gm-Message-State: AOJu0YyFD8b7KtQz0vgIMo60638B4MWzJAajl5rgvxdoHj5lb4arFvF/ qq9RmyAfwNSSNYSjLLpLhZksTRYBKQQByYIG9fPDgidohyj+aezN X-Gm-Gg: ASbGncsfrWwgzL3tELeShRgHf641ssHN6sx67L0JKseCY87gmweHLSZH6nlR6ZG/mJf SGpzwRvGA+cqfNFU3LJrMCyC5S1yz/yAAPM7bnWnTHRjrDC8NDVAFtq/3DUulR/wZ4qm1C6VxR9 19ohj/aph31sT95F4v4jxW8hYwrsR5ORNs+TucMYYuHQQ/cczgLR6jhxtTY82BcsmrMfs464WTR FSyX0PclySXX2dmM7rpyfa/1C1B2jjMQXC/1eSzQFAq/odKVQIC/BbbybaHnsPTzLIxR5TTDrRv qkiA0XHtJTWjBuMMpPYN0HokORlAz0+oyvrZGc5TQTz5MFinaDH5xSlmgA== X-Google-Smtp-Source: AGHT+IG1X/LQ5evGM3eWPzIxwvwVI1mcEKQY/cg9Y9a4wUk6EK21LKlTc+rG43P9ZfCGFMaDANzX1g== X-Received: by 2002:a17:906:99cd:b0:abf:4a62:6e5b with SMTP id a640c23a62f3a-ac26c9d4953mr449641866b.5.1741458906347; Sat, 08 Mar 2025 10:35:06 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:05 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 10/24] dt-bindings: media: i2c: max96714: make ports conditional on compatible Date: Sat, 8 Mar 2025 20:33:39 +0200 Message-ID: <20250308183410.3013996-11-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Devices to be added in following patches have more input/output ports. Make this property conditional on the compatible strings. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96714.yaml | 90 ++++++++++--------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index d0a2aaf7df9c..f0ae069c93b5 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -41,56 +41,12 @@ properties: description: Specifier for the GPIO connected to the PWDNB pin. - ports: - $ref: /schemas/graph.yaml#/properties/ports - - properties: - port@0: - $ref: /schemas/graph.yaml#/properties/port - unevaluatedProperties: false - description: GMSL Input - properties: - endpoint: - $ref: /schemas/media/video-interfaces.yaml# - unevaluatedProperties: false - description: - Endpoint for GMSL2-Link port. - - port@1: - $ref: /schemas/graph.yaml#/$defs/port-base - unevaluatedProperties: false - description: CSI-2 Output port - - properties: - endpoint: - $ref: /schemas/media/video-interfaces.yaml# - unevaluatedProperties: false - - properties: - data-lanes: - minItems: 1 - maxItems: 4 - - lane-polarities: - minItems: 1 - maxItems: 5 - - link-frequencies: - maxItems: 1 - - required: - - data-lanes - - required: - - port@1 - port0-poc-supply: description: Regulator providing Power over Coax for the GMSL port required: - compatible - reg - - ports additionalProperties: false allOf: @@ -102,11 +58,57 @@ allOf: - maxim,max96714 - maxim,max96714f then: + required: + - ports + properties: i2c-gate: $ref: /schemas/i2c/i2c-gate.yaml unevaluatedProperties: false + ports: + $ref: /schemas/graph.yaml#/properties/ports + + properties: + port@0: + $ref: /schemas/graph.yaml#/properties/port + unevaluatedProperties: false + description: GMSL Input + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + description: + Endpoint for GMSL2-Link port. + + port@1: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: CSI-2 Output port + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + lane-polarities: + minItems: 1 + maxItems: 5 + + link-frequencies: + maxItems: 1 + + required: + - data-lanes + + required: + - port@1 + examples: - | #include From patchwork Sat Mar 8 18:33:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871785 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 005EA21577A; Sat, 8 Mar 2025 18:35:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458913; cv=none; b=gSXwXUZfcxrSvO/ZqKz2CFzOrv03GXOqZnDDF9qLUCYb+xban924MuAMy5juUhaBOtsInN1gQugjVSfWeD+sMvlQtxsqlXFQfjqDQ5nyuPyUdsRWmswMXarwtucrM/f0szc9LCuLigu0VAdTOcoyZ/5C1DuFcdTiWTikCsjHmlQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458913; c=relaxed/simple; bh=o05S0tGp3dvRdH5lVO/ozpjjZ4Bgkp1SlZ/e2LGGMnM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oBJA1nVkqQOPfsGSQIlmcDg8DycFvL0rK5u2hyWAKbD6AUEwbETQsBtj5p4p3kjT+DL13uZKk49YPhK30j92sOb0LoB5k7opyDy/BOQk19Xg2AJOkVXC7xdrl27E48YngL1BypB96Uwm/zxd5+uGYyoGyfSjoeb8IZ9QxSVE37A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hx2PqbwI; arc=none smtp.client-ip=209.85.218.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hx2PqbwI" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-aaec111762bso550656166b.2; Sat, 08 Mar 2025 10:35:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458910; x=1742063710; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=StYjAl/VAK0MYL6WYMTcRj5E6kmKjD+sp6An2vGqQtw=; b=hx2PqbwIwtuehseHUPlzj90raV+XLIhFxiEMywXwSzQkGA8xsUipezTueqC5oipvtN FtQfpna+nrtxFV+EPlGvgBHP33TDQ2kTXQ6bbMYbNj0KJYmSvCJSAJuwodcVkNNgJ6n2 SkHz7bcGlrN7tDg7JSHQ512SffG5VK40X9FBs8YKvsTLlrZ3yEWDZClScZe2SkHXUUnD MijZo1evraRBAjgdZjJyXKu4t8H9HBSb8qIXAuXexhqB24OPaVTOrfEgoVMx4B8YDJK8 /VzCgNcV+Q9Cg36xcqFMFKYdTLi3e3bUfvozEqYvkGad68oztfMOnLECBq2wy2ZY92ut UCag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458910; x=1742063710; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=StYjAl/VAK0MYL6WYMTcRj5E6kmKjD+sp6An2vGqQtw=; b=Qp5l/BJidnUsmcJPqWPrvKKtan3nw6++sSMWffMMauljBOT3jiMDZgH5eXzhFw0OXh SYTTlvliDlwPc+MouYKoZrq2zTwMoCVPaoQIAcCFnxAzhX+PCv8XpJWQiD+V5WnIlzDW FUuFs0J2C5IlaeKwG6crR56UjHhzTfFwLhO5YdsWqYc6LujHKere/JqxlHeCGzGyoldc TLtuJ9WeM/x08BARCOjd0WX4qD3xOXeQF7B6zrthlAElxJ/zg1PUAgGbCIUEjXuLd1cP NkAom5yM3ZDr7F9C9KV17ajcZ61tPgn0RCkFQ/1XBbXEN0t3Uvyh9cTEYytDctasjv0O qXqA== X-Forwarded-Encrypted: i=1; AJvYcCVMI+oJHdmXxmzmWUjtg0UTyc9mLQzYAYN1zz1UjUuCltN3dr5kHjWhXjMCTqy8s4WbxAqPy7Fj31ZddGLC@vger.kernel.org, AJvYcCWdcyZf5eBn8Lwc9cE7LMLM36kxFU1F5Ju14SYuETLklZZlVgwrzA1DMZiYyAogK+BbI0vgnTXcI2gk3w==@vger.kernel.org, AJvYcCWeDh5h7j4Ni4EOM13+pWvRhw5rtrlknKeBLh5dYdu+vt5hdzmoHXnH5TllPFnSHJOSp1JxlJ+y6wFFtuo=@vger.kernel.org, AJvYcCX+QhFuVZkkwUzbdYK/2PJvtaZqhHYCuxeiKyAWVw9hVj1PStWNZR4WMPX5nhXZAzJeC/OGbWE4SIUk@vger.kernel.org X-Gm-Message-State: AOJu0Yy5imau+3o86rSHzUytFbIjKz6sdvLgCvHqMWPnwk0yYa56JPB0 zxRVHwzCCwfkRWmARvKMayCdVxHvctDivKNrm1/k97hNdZkIl7KF X-Gm-Gg: ASbGncstMJKmWoVAtMQXR09sgX18tcYQkV/JHBXmk7txYrvty4X5jkirhiqK/pUKfTx WXoDNmjSKzz8o21CpDqFQF4uNB5i8UnjDbJo3cVg4pgIvz5owJTPlCoFFIMD4+EH59o9Pg5gNl2 lS4ZzSkbUd2iarT8Rvs5sHuCl2sqluw+e3F0Y6w/w+kEAcHDBQ489wzLyfm5WZi8jxqf9PxNGcO xO9K1iheVzCGg/cC0pa2Sa/tqBXRDMh26ocIPTQpK2J+f5epv20s06+VTGvpWH6DxQZ1g9FK90o T4s2NDnCu7tG87dQwaZZjo1ziqiUiwwG9kzgrvmk0DzcVbJW0MU4hVkJow== X-Google-Smtp-Source: AGHT+IFkml8eKK0tt9HJFaDP4zPVB3vHkGahRibCFcb1VL1+aECeQ55QqNbdYqCYjZhicTjwIyr4zA== X-Received: by 2002:a17:907:1b16:b0:abf:742e:1fca with SMTP id a640c23a62f3a-ac252a9e1e0mr879939566b.18.1741458910140; Sat, 08 Mar 2025 10:35:10 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:09 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 11/24] dt-bindings: media: i2c: max96714: make supply conditional on compatible Date: Sat, 8 Mar 2025 20:33:40 +0200 Message-ID: <20250308183410.3013996-12-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Devices to be added in following patches have more input ports, and, implicitly, more POC supplies. Make this property conditional on the compatible strings. Signed-off-by: Cosmin Tanislav --- .../devicetree/bindings/media/i2c/maxim,max96714.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index f0ae069c93b5..5bbd36c55ab4 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -41,9 +41,6 @@ properties: description: Specifier for the GPIO connected to the PWDNB pin. - port0-poc-supply: - description: Regulator providing Power over Coax for the GMSL port - required: - compatible - reg @@ -62,6 +59,9 @@ allOf: - ports properties: + port0-poc-supply: + description: Regulator providing Power over Coax for the GMSL port + i2c-gate: $ref: /schemas/i2c/i2c-gate.yaml unevaluatedProperties: false From patchwork Sat Mar 8 18:33:41 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872055 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D446215F6A; Sat, 8 Mar 2025 18:35:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458917; cv=none; b=D/JEpdJ0ue+2cQptgfbbuiOL+CpYhnTeAj2l+LPlB+CReMAZEysrNuW4HtLp0XUJvsB2UdbC/qeRWB9gs5BJRDNaxAkIN28+R/HnGQyDlUBzsftRQxZGRwsvMgJY8/kcaUIOZU2FBMq1Dba/PWDM8THV5I9w7/uiFu0y7WlSfd8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458917; c=relaxed/simple; bh=BJzpD4gfPGejKywhP8UPgiRX4+wHEm1Y8kRS4kT9oec=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KRKnBN+j4GneeI3pSkLjTVyC9ILSuI7tKPDZ9kWJR8g3892pdaHj9ATBioUL4QzwqwzpEqshmGWymzYxMAWRnPK/+4CHvy/S3MVjno/Jr2mQVennksJZx46a498RWBQqXOcIccdBYnEE8niNfmIsNwtZw6WhuhlSBLLgLfUOjcM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=S657sRJh; arc=none smtp.client-ip=209.85.218.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="S657sRJh" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-ac25520a289so299913566b.3; Sat, 08 Mar 2025 10:35:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458914; x=1742063714; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=J6+z5mwvOpLxFkXjmRmdjGwPnNX9qEV+1prpbhSFJtE=; b=S657sRJhQjHyCN3jHwVBrxYflLgIhYCizROulfRCLp7g/pADBJ4msIDchnrbb3n1Ao GTwmlAivF7oEb54tqkvQ1w3H/chXOFAHcBJsQc9gWHd/TNTErBwQBFUgEo6kewLk/ufJ Oa0gRyU3gZPgzk+HuQUci1MVMEA9oyYjPdzadIMn1CKZAs7uKzOQxkuvpEvz5nN10b1S ltffdnjqWj8lmu4IJfrRsWp6yIX18tu0xXTHYI5d1ip+RWFnmAJd2AesT90lQNRUXarD 13IzJXfGPfbeApmefid6IbMHF0A+FvsbYrc9f/In3CdyaPm+jLyxotiCLmgSdoZJHnFR AMYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458914; x=1742063714; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=J6+z5mwvOpLxFkXjmRmdjGwPnNX9qEV+1prpbhSFJtE=; b=ISo8cx26gzKvYV4mrw9gPt0kmkaWsmt2sJxQBhBQSLWyOUU+8SAAfhVoG94BFpiO/N ztumRv22mzPn632stU9tZ1elJBn8NYhXie78uBQnpdnElJzK8XFS0V72cHW8BKFhWfrB uwXXckIZAuSThxhPWDqwdSnOjqjKYXdNxBfVkqC9G79McU7udEtgaR1AqR+ADyEJ/uZy Za7UP9Y/AsZRxj+nVhpGX8lwC3vMSqtFykW98L0szKfFKfi6QI+T8WBOGZ8r6H9jW1yL 5tvt79xOEe3fLBFCgjVZ6wM9nXM1Z+KMRtjfQg0mGaxQ5sIdSc4dANJ5oSfqLg7AJIKC NlEA== X-Forwarded-Encrypted: i=1; AJvYcCUsAAUzrlHcTQ1/e202RS2kWgLE/G9lydapQz2TkOOmuAVMFacVW/racSenZFZC44bQkHnu7e5QLzPP@vger.kernel.org, AJvYcCV+LThbZqHv4dZEJjODZZyMnoQ/oKcxBtc0dqYNdpfjbzzROqKlxOEhJPYBbrxnE9q8ck0L2WM1CdpaNQ==@vger.kernel.org, AJvYcCVeQNuWUOHLIkjTuhu52bX1aH4Fex2753Ik0Oq4eDrdxtMcR306ALpOGKYgH3KDOwNfrsn12ZatHdLU2K3g@vger.kernel.org, AJvYcCWaXle//hx/ByEB0KJhsVnbjHp5gJzO2Uo4ZtCh9NMwjuwIQhIswhOZBIJGACuAphpK2A8cUXRoiHsiB4Q=@vger.kernel.org X-Gm-Message-State: AOJu0YwrsjfWYZaSsompQfP7onil6uQcFUALHyoYam7/3bXMeKS9x+Tj 68vhEno4VZ2JAci6oQZb36OVNqR6s+XXEeK05eTBlyV1/sQFVU4T X-Gm-Gg: ASbGncuogULmsEzYNoKPMOXoR3z5Q2Roqp+cSOleyp1lirptCGhCBBGmxjSel7lkE03 q2w6Xo5Klag5oHsmonG9ANltax8TB1ekB95YmvW3FAfm0uoznliTPvIligcjhlbCbJjLUypwhjv lbGi4fuigmgWZnwLBwLysCdjXo80v08uEi1DA9thG44+YupmycqUZD3eRCD7jQ0fFIRt52IL+cU +RTu5yxJc3R5dCtdAnJfRHGNrAnVtciUtnQeAB6Q32pgSTIShP+XIkPCGhyHWUvQkZAQbByNReA clZgtrlDZMUS7t7xh1C6PsXqY1m0MVdjeaZ5Z6s7Gx9zRwLuyf/CN3yI8A== X-Google-Smtp-Source: AGHT+IFh4qSdAc0ziZwtQFqR3gB3PLHeMZTKtpDvQwy/JOvsAtBLR6l0SztItz/m5ITqfugVt1AvgQ== X-Received: by 2002:a17:907:3f9b:b0:abf:c20d:501a with SMTP id a640c23a62f3a-ac25264ca27mr967872266b.16.1741458913731; Sat, 08 Mar 2025 10:35:13 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:13 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 12/24] dt-bindings: media: i2c: max96714: add support for MAX9296A Date: Sat, 8 Mar 2025 20:33:41 +0200 Message-ID: <20250308183410.3013996-13-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX9296A is an older variant of the MAX96714 which doesn't support tunnel mode, but has two GMSL2 links. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96714.yaml | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index 5bbd36c55ab4..9c6c79a770ed 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -22,11 +22,14 @@ description: The GMSL2 serial link operates at a fixed rate of 3Gbps or 6Gbps in the forward direction and 187.5Mbps in the reverse direction. + MAX96714F only supports a fixed rate of 3Gbps in the forward direction. + MAX9296A only supports pixel mode, and has two GMSL2 links. properties: compatible: oneOf: + - const: maxim,max9296a - const: maxim,max96714f - items: - enum: @@ -109,6 +112,90 @@ allOf: required: - port@1 + - if: + properties: + compatible: + contains: + enum: + - maxim,max9296a + then: + allOf: + - $ref: /schemas/i2c/i2c-atr.yaml# + + properties: + i2c-alias-pool: + maxItems: 2 + + i2c-atr: + patternProperties: + '^i2c@[0-1]$': + $ref: /schemas/i2c/i2c-controller.yaml# + properties: + reg: + items: + min: 0 + max: 1 + + - if: + properties: + compatible: + contains: + enum: + - maxim,max9296a + then: + properties: + port0-poc-supply: + description: Regulator providing Power over Coax for GMSL port 0 + + port1-poc-supply: + description: Regulator providing Power over Coax for GMSL port 1 + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + patternProperties: + port@[0-1]: + $ref: /schemas/graph.yaml#/properties/port + unevaluatedProperties: false + description: GMSL Input + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + description: + Endpoint for GMSL2-Link port. + + port@[2-3]: + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: CSI-2 Output port + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + lane-polarities: + minItems: 1 + maxItems: 5 + + link-frequencies: + maxItems: 1 + + required: + - data-lanes + + anyOf: + - required: + - port@2 + - required: + - port@3 + examples: - | #include From patchwork Sat Mar 8 18:33:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871784 Received: from mail-ej1-f54.google.com (mail-ej1-f54.google.com [209.85.218.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26D482163B3; Sat, 8 Mar 2025 18:35:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458922; cv=none; b=GqUXA4NsVIdjQaXu5zM7M02rhv3UjNwSwRbH/cKqchaa2QX9y2r2cH1tv+DPG/71l8Y6Jep3/r1RtVeE2LJ4NWSjqn3XeYVkhS1Ap7tSAGUdbCX9QnXOvHs+65OXPSujarEJMVpnPuiQayefR+4GRDpowl0Xkz2U1aKIP0fnOv4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458922; c=relaxed/simple; bh=8ZE9rC+k0ylA9+L3TmlcZKYr0Wjz0Tht4eUfO+AkCjA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WGz9sOarVsj4elJhGXKkycxvRmEOdRVytWO2d+tnjrZ89n2sY3wny01L/cKw+1QBcGvxTkQqUzeFh7K79JmUn2oXEkLXJZiJU4gZ0Z0TujmH8JV1JmXzA8cjYs6w6Mbm5mOJXM/A7mlkyLyQjaYVW0UUm6fW+FgLStO/fBPBscA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=R4wHhwks; arc=none smtp.client-ip=209.85.218.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="R4wHhwks" Received: by mail-ej1-f54.google.com with SMTP id a640c23a62f3a-ac25d2b2354so253093066b.1; Sat, 08 Mar 2025 10:35:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458917; x=1742063717; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=lH0nLPR7+Nln01PT5ZZw1hoLmM980Fwy2kz6sbBJysY=; b=R4wHhwksWUzhH6DqcOkY7QgJdwQG4txMLotYnVDRBriGxaZNz63bca75/QwRTbsC2l fxlTNXBp656MBJSWbE89aDlz8YJSs/ErQHHA9i2saSahIkgXFccAZ9kTlTsjOvyvN/s+ mzgpqnCIuebgJD3OFdJG3jrkgWrviz+0iaGnNN4yTZjZ2VYu54YXd8HFPK2ZUtZjtx6m NyaHioPykhrUSIDMpypiyHGDWUu5IDTKpUxsxPCijd8EjCVCNqx/TwAhdL7Xhl/SVwiz lac7M1UuUNvKy57Ye6uDynKZe8rbXVGjQ9LNgLxHNpJ9QeXmWYV1Tw+U0BQJynFUJL3k l4xA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458917; x=1742063717; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=lH0nLPR7+Nln01PT5ZZw1hoLmM980Fwy2kz6sbBJysY=; b=BeKzKBx+Hi+KZxiXQ/KbKEKWBWfpCg3RQiVTkiVf9sWiqvLrgLRxjRahIovwEUiT3U SRl3nB+iNk/emaA7pIy36/K9wnMjKoIePog+0qmDBP9DGbTr8zL7gTmnyfdw5An5471F Pt738UuEmazchkVw9AN02UHZYb7b9f2LKr8MJ510sGKaRJXcBWUl+y2BoTevE6ztuUEW Q/1m6qeSjaDcaeyzEneycdThiiwimU8qoQp1H6O1EWWMWQMfxCQHUzBDIoGxP+l6bjy1 YLAYZkTCT4WHDFFzemxlxPHY4H52C4bUeazREfW74dGNVeY9GHQPczyQWYpw0RsPY80e Fadw== X-Forwarded-Encrypted: i=1; AJvYcCU66ZNNHWAChGin2rm2kefzT7Eu6TENZeNYFrX+OT/lNThPzU6VcAlRgthWekqYS/jZ/hIYkl2zDQoeeWzp@vger.kernel.org, AJvYcCUCo8dRc17rfFSORHsENHwF1BX8zeCCspZofj6WTycu9J0LwCBGoYTrSTEyLaeOa85T+fU5DevJ2eMf3w==@vger.kernel.org, AJvYcCUJurkbmoP9fMINDYJOA88JOKv88U3ZSxDCKBWx2Q/uOr/PG5NzW1kgda4M62v1HczxXEHXqUSBZX4K@vger.kernel.org, AJvYcCUKZ1H7s3Yrm3OIior01Vw31yPXxXotMixmKSFIAadD03OiWaoF7udTCzzZOYhzgKW/mD5orZQPX6Fe47c=@vger.kernel.org X-Gm-Message-State: AOJu0YwLO6X/p5P5WuH+7kRdyJ2xlWrZoZ1XEsvHmdsSJbtw/xUUjmV9 07RsnE5EoWtO64tb/HynGvo8fWEIr+p1l4srnsQgFEVk9gzQ9s7t X-Gm-Gg: ASbGncun7NcYbzMyPMoh/omKoGYvDf7qW6OGeHVcJ7bkAqO7rI2b7nVk7CApb2CrG/2 gE0MaEY99NnkruKjHUzVzprfOlNFsEvlhtcHddRdVn2FwpEfcBSpAYKzAjD0sWX9Z+PRQK7TNXa 4uIk3RZN7QFRJWJ/01dAA6wJ56RcgO7UPydVpKbXrfQ8jl+ViqDb06gxY20G9tbDBxs4TlHkHh6 oosMcZEf7MxONx6NWrJBbaLXhhdR6E+JFmHoBUdL+Pw+enXMTL7hgNHNuJHRt3X5vT6TzuGKHtH SKdf7U3AWBDZHV/FfrVnm3zi0EpV5H8pjLYJJKywlHduzW5Ig0lwMKoHe/3dC0u8cLW+ X-Google-Smtp-Source: AGHT+IFxa4QmBw7Ig6TbMkCdhDiwKrrIoEA173KNNedZZ1zvVFLBlc4GfcP9AWrjoYPa9kZijnAFSw== X-Received: by 2002:a17:907:15d4:b0:ac1:fb27:d3b7 with SMTP id a640c23a62f3a-ac2527048a6mr603962566b.21.1741458917335; Sat, 08 Mar 2025 10:35:17 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:16 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 13/24] dt-bindings: media: i2c: max96714: add support for MAX96716A Date: Sat, 8 Mar 2025 20:33:42 +0200 Message-ID: <20250308183410.3013996-14-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX96716A is a newer variant of the MAX9296A which supports both pixel and tunnel mode. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96714.yaml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index 9c6c79a770ed..d4055ecf673f 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -25,12 +25,14 @@ description: MAX96714F only supports a fixed rate of 3Gbps in the forward direction. MAX9296A only supports pixel mode, and has two GMSL2 links. + MAX96716A supports both tunnel and pixel mode, and has two GMSL2 links. properties: compatible: oneOf: - const: maxim,max9296a - const: maxim,max96714f + - const: maxim,max96716a - items: - enum: - maxim,max96714 @@ -136,12 +138,31 @@ allOf: min: 0 max: 1 + - if: + properties: + compatible: + contains: + const: maxim,max96716a + then: + properties: + i2c-mux: + $ref: /schemas/i2c/i2c-mux.yaml# + patternProperties: + '^i2c@[0-1]$': + $ref: /schemas/i2c/i2c-controller.yaml# + properties: + reg: + items: + min: 0 + max: 1 + - if: properties: compatible: contains: enum: - maxim,max9296a + - maxim,max96716a then: properties: port0-poc-supply: From patchwork Sat Mar 8 18:33:43 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872054 Received: from mail-ed1-f45.google.com (mail-ed1-f45.google.com [209.85.208.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E7CB72163B7; Sat, 8 Mar 2025 18:35:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458924; cv=none; b=TRKfY/hmMNVs+Dk/3Rqu4qe5xf2rxD4q5O95L7sFdhWU/PjFhaRBPsjS1fS+YuxSj2Z8ihkkj34prnAN4Y7M6aiUtok5AgiPO5Q7OobfnLsZfz6/ZE4iUosY9ARgqJFxhaMDN021gie4QKmjg8+/OugeCsjsAgLAMuzZsJrGlno= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458924; c=relaxed/simple; bh=ECI+YYqiSDocPmZgoGfiqNbqVHbdsHypglZK4S7zrnU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QDev2QXUwWdprAJZbzE7jv7DI/LwM3yaOj3HYM5kUVCIRlAgo0QFZGxjBv2FsW+bcHqFgIOyisdXdoO9S/6RG1JQfoEo63IEV0yOLraRrF6F8A19M5S5+yGdokL2HNyHC8OZBo+OPNRodETeWRS70YxEAD/cPwiVOnkOsRACDb4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=LPSAfbsM; arc=none smtp.client-ip=209.85.208.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="LPSAfbsM" Received: by mail-ed1-f45.google.com with SMTP id 4fb4d7f45d1cf-5e673822f76so4716a12.2; Sat, 08 Mar 2025 10:35:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458921; x=1742063721; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=baE3FlbyAib1Dal/N03f+Lej7yknyKf0UFF4oZGMBs4=; b=LPSAfbsMyQQWCYwtNFmQvDRTRgm19YGmEB2ERR1Ppq+jkwi79zsc3O6JxuyVObqEhL grjjro1qTL4ECEjIEQSSExjQmZoq85Kp6tBBun5l4jx75TGm8xURsLdYDay+8CS0SVzS kcKjhYzzzMQ6xvXQlYehEDfDXUJrzvFLfoAi1DKkB/F4CG45tCog7YzN+CmhMGsnI4gw mGbpvx9cREA0ut4j2O0pWi8bK0F8z/1PHVAE4+aRC5a4jV0z6kLOtRvgGXJGfi04xZfI UVmfTr+AVTNarhvhVw6R1hmPl7Sg+mgwSK3orTsp3wYbFftWjhuuPOrKSWF+ZZI1pY1i zI6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458921; x=1742063721; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=baE3FlbyAib1Dal/N03f+Lej7yknyKf0UFF4oZGMBs4=; b=Lii6xjO0P+jXaW//YCTs+xoPStqzjSrB1zxWikufW2jXj13tttYwuzCeaqWJ36Cw96 MgUE33feuKaAosRuQBE2FXYDpkY/fmFD+Q3v+sC0vzwFFlMYsbmojUbQBKvj3UYeeivY 5VogGFdGndHSx0VxzMu4bYetFgHoOHYs7pDaIa2u/ZqHR/Och4KdFE4ohZdCuc2YDJQn v1xoVU83+4dqGSIr2ESjy+cqpQB0cvTTe4CDhxy8h5P345caIP693UWxQ3VS6tW/e3v6 eCTy8XRvpZCn8FVsraJXYqurzrHyzVj83F+SL8EQqWqAcn5ztxVWNLGJZl+21CC7BTMj FEcQ== X-Forwarded-Encrypted: i=1; AJvYcCUgi0okQPszjLhdd8nyFrmasTayhfwjY9h14Dsk7e1Mx0c3c43AZCY0SjcPxExNo6S0WUvsZhKc0ouS@vger.kernel.org, AJvYcCVkuej5CLZrGsuprZWEa0SXNPclbslwSc75LefkEtHGQ514DavprOnkJ6o9HUZLhOJSDyInNZtnfIbf+g==@vger.kernel.org, AJvYcCVoQNDqks3SkG+Yn/RFPX9S7T4mIoJieV1vWOEnGe6vjBQ3ki0+DsQAJtECnztCH/vKwfGGJXHqBb+bUY8e@vger.kernel.org, AJvYcCWkvz4CjAczz+UnEy2FOTJDtCRGoqt0zEYsmGYKsyy5OyODXxsMfbOdewwHlQmQBudcxxaT+n0OODxqJZc=@vger.kernel.org X-Gm-Message-State: AOJu0Yyzl3l2nJTvE++3SH3aOTehnMG+Joj08sh6mViLPhzniJJPljNE D/sghUz76/dEXx2X/zgK8tS4FL1isKEUNQfMZAlNUQRNWpzIU4so X-Gm-Gg: ASbGncuJLXqAI91NOzDU7OV9XF3grcEvn42jvcOFSx1SkSx2xA6OdDHOV+ExxVMZv/g y3L1lH5TuAO59vQC2CLo3pR8xX3FgHrCvCqxTEHcg34DGsc8CkUm7zbum0pL8tfRUXdEKrJRDXi wBXRbclljSmYo/1pGHE8+zIXSSFHnmIRW5wzatkN+PS829b5JiJYPWl4dFZaXQzTgin3EW4lKkH 0YDkQndWtK8dgL/K9DOM3XfZJSc0knTxb+aEuRE8SzvP70Plwh3GyXjw4fYYlo8qfft9CQE8B3m ki7K0P8Gzjvwh3H9WZzbYdM6m6k2VHgiUDTkfAhKJkBDnX4huF3NdDDT1A== X-Google-Smtp-Source: AGHT+IFeoNQFzdeGQAk7Bpgr0BvM/R3lxDF9QM900UyUvrHBnqHPA0/fWbTTYKQNUdbDVHoVSrFw+g== X-Received: by 2002:a17:907:3f2a:b0:abf:77f3:d1d8 with SMTP id a640c23a62f3a-ac252a9e1c5mr850948766b.19.1741458921149; Sat, 08 Mar 2025 10:35:21 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:20 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 14/24] dt-bindings: media: i2c: max96714: add support for MAX96792A Date: Sat, 8 Mar 2025 20:33:43 +0200 Message-ID: <20250308183410.3013996-15-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX96792A is a newer variant of the MAX96716A, which supports GMSL3 links. Signed-off-by: Cosmin Tanislav --- .../devicetree/bindings/media/i2c/maxim,max96714.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml index d4055ecf673f..a392da39c154 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml @@ -26,6 +26,7 @@ description: MAX96714F only supports a fixed rate of 3Gbps in the forward direction. MAX9296A only supports pixel mode, and has two GMSL2 links. MAX96716A supports both tunnel and pixel mode, and has two GMSL2 links. + MAX96792A supports both tunnel and pixel mode, and has two GMSL3 links. properties: compatible: @@ -33,6 +34,7 @@ properties: - const: maxim,max9296a - const: maxim,max96714f - const: maxim,max96716a + - const: maxim,max96792a - items: - enum: - maxim,max96714 @@ -120,6 +122,7 @@ allOf: contains: enum: - maxim,max9296a + - maxim,max96792a then: allOf: - $ref: /schemas/i2c/i2c-atr.yaml# @@ -163,6 +166,7 @@ allOf: enum: - maxim,max9296a - maxim,max96716a + - maxim,max96792a then: properties: port0-poc-supply: From patchwork Sat Mar 8 18:33:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871783 Received: from mail-ej1-f52.google.com (mail-ej1-f52.google.com [209.85.218.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8CE4120C029; Sat, 8 Mar 2025 18:35:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458939; cv=none; b=Rn5BhTmywQ+KnFZADZnVpB29Kx5qEkG/cp98Wcn1r5IzrcvYg/qg/ujKGxbqkvB+zzAMBBrzTsuDRpnM00TnQ7tEcy1amF8Lc1tcVJGY76gFi3ixI5E8kMDc1M5LNVQ9r83gNqYyOIFbtVU9hAwdTkiSqvUwjSKrzgezIpfNAJo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458939; c=relaxed/simple; bh=C3puY2gKJR/vIUjpUr7LiUyw0554VXVmNsc0xT2yhyQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Aun2JeUuMzTsmsTpmVKz72v1W6GUqVj7fdzNuNgk4f+hc+ggfF0faEL82I4p2vpTCohykol6wLSlGB3Inhip68td769K5Huh9HHSCqyAH0vlvuqEojzvO2G97tinSNMbkJ0Q/ucj4huoZIQfwgzai0Xw9mmoV38fBnP9jn7bwy4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MI6djEWy; arc=none smtp.client-ip=209.85.218.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MI6djEWy" Received: by mail-ej1-f52.google.com with SMTP id a640c23a62f3a-abf48293ad0so469545966b.0; Sat, 08 Mar 2025 10:35:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458936; x=1742063736; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DCsk/rfL/dXjGmxlvAv4Wmgs717Q0qsPD356Vdw2nxQ=; b=MI6djEWyQuAxy+D0xXpNyNQE8AgcvLXgnEr2W9GLN2ucDebSex/m3+VpftAs2ZPY3f E+NHzB3JLrWyhpRJaGdudWLZPmtw+V6Qp6Cu5NazxkeR7wZwGmc+VAjsQWVSQosRpORj C0rzmEBdlepMoOGp/s/Hl1IQ0FmoD3tCmcQ53UnLY+SKiYz3hLzIGXJwi6swGozPoKt2 pZjjQ2Mtk6sla2OIxh+chsyEBUtDVt6InvpCH2pXM8MshI7Cm8WW4VeNNzc73CuNgFvP rXvd3UhiLaxWZeehQ/VNKhIIQQBhoVqMB9gDbn6XDmvGy1VmgwQibDrSQkqsJPin/YSG 7uhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458936; x=1742063736; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DCsk/rfL/dXjGmxlvAv4Wmgs717Q0qsPD356Vdw2nxQ=; b=nCmPo+Kh1T9BnjEsvT1bq8iFLtkoAEattiJj7oeSRJrAFa4CY2Mfu8dtWro4GCVyDt zeghdymq0FEJ6yFA8b9Oe6lYUVlAuvoAXu57ZXvrKqsgn6MA92f7CICYwlohKhZTJXe7 GVIKWzWvsMkmvL89g/IPe3ySX7nX1iTew/Z2ihNCghwfk/ZhmNJ+gtoVkdMuPTcWHhHK 0/Dl5/ctlH8prBvBqfHhO2w7kCUwJpgKo75TDuFwcH6vPpRHc3VSan2QzjRyrfXYbG/2 XBAm5U0YrJpOz78BVmLLkCJXRzH6dJNjCFbChVneiMFeswUKw/auQe8q5vQpLWUIhNZZ RNhQ== X-Forwarded-Encrypted: i=1; AJvYcCV06byEyEu8WKQJ9mHuBva5KFTVvwGKYhLdIVZ8IPmFEal82+W3YCYrGmL+Vyo44314U5JCeWSmV5CU8wg=@vger.kernel.org, AJvYcCWk7Ly8RsoQ4QOwZhqn74jgQXze1Yx4oZe7rcRfC1rwfSoXTKaZf9cTWVrmr7H7oQM5btdlsw2WwX16p5Su@vger.kernel.org, AJvYcCXey4kslP5hNsqVHp4OpfD2Hxasbdmk7ro69ZWJmeZoXTDx4rOn44li+Q19QHjDZbRpceG8AgQw0bv/@vger.kernel.org, AJvYcCXsFWh8oLLGxDggB2oEKkIM0pb2gsErdU6yk6EAB94M1SbqnX1vcwEmw18FSoD2QpgYuEz9y94Kpqwk6Q==@vger.kernel.org X-Gm-Message-State: AOJu0YyHLvhXmg2XlB/FchliCgcdAKpARdk1HWuWsR99NrOC9z7uouMo 1ii7tUE+hHdRglwNBE3G9p774GrSQ77YRp7deT0pZsqOBt+R8B0L X-Gm-Gg: ASbGncts2kY0VLW0bE8Rmv0vT0UeOF5v/PGyoht/qKRKhFEhhxHuMRVim5deavEh7os hkd/S6ezVxn3mwQ+1f7kdhUUbFzb3GkzuARt9F7Nmf9TVWdYkOwsNILYj+k3Aeb3PXFGBILwRWm IlYk9FxlkwNgX9UP216bggaS/FJ2T1fG+/f6ZkKq1HnUlIlwhdxRff1TJw7s//RZje0qpcEvmx4 mz7TLARj6dPNRbAYMX02x0LlpX9vVUjeu0cuMqf4tlBcVeCyNbqd5nO6Q+ED3Tzr+l9LZHQulXC hw1ZhudA3ED/zm6icNXycbPR/4SH+J7inA33OJoRI7Oep3ytJSIRDlj4wg== X-Google-Smtp-Source: AGHT+IGuZkxoe/YU55gAOydwcd3lXHtaguNyV0TNC5ENcmXJiPj/O25J37irkr3OZx/XpOJhzTPfZQ== X-Received: by 2002:a17:907:1c9c:b0:abf:69e6:438b with SMTP id a640c23a62f3a-ac2525e040bmr1055808066b.9.1741458935572; Sat, 08 Mar 2025 10:35:35 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:35 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 15/24] dt-bindings: media: i2c: max96712: add myself as maintainer Date: Sat, 8 Mar 2025 20:33:44 +0200 Message-ID: <20250308183410.3013996-16-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Analog Devices is taking responsability for the maintenance of the Maxim GMSL2/3 devices. Add myself to the maintainers list and to the device tree bindings. Signed-off-by: Cosmin Tanislav --- Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml | 1 + MAINTAINERS | 1 + 2 files changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml index 26f85151afbd..efdece2b33b9 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml @@ -9,6 +9,7 @@ title: Quad GMSL2 to CSI-2 Deserializer with GMSL1 Compatibility maintainers: - Niklas Söderlund + - Cosmin Tanislav description: | The MAX96712 deserializer converts GMSL2 or GMSL1 serial inputs into MIPI diff --git a/MAINTAINERS b/MAINTAINERS index 7fcdcc57c8ba..84078626ed5a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14184,6 +14184,7 @@ F: drivers/media/i2c/max9286.c MAX96712 QUAD GMSL2 DESERIALIZER DRIVER M: Niklas Söderlund +M: Cosmin Tanislav L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml From patchwork Sat Mar 8 18:33:45 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872053 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1460C216618; Sat, 8 Mar 2025 18:35:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458944; cv=none; b=eRtY1DeayXrZ1lcNb8E92cWLAep9UX9lM69Zfltq0u38kI+jFWjy6Kl98s+tVAaivWLs3qqq5R6oCRRVNXaEznGF2lIl12FJE4YnQsMCsWs0sMzLCFIOSZoNaCJktfYEzPV/zKF0WZ6I1PlURSAAEho8xEsqOkBolS4gwuTGjsk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458944; c=relaxed/simple; bh=PSA5fazrZYGh2STXG+59g+TiLDvJm5XnM9PxyZImEvM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ik/n7ODSRuzPLjBAGcY9znvn3qniK+4zcUozJvA+I92PoowEZ2sER3SSDzV1Po9aeYjoXguyTfz8Np+dB8jIps/B7M/6NarP8VavFLqmoKFaR6g/MkBGVeAVwMZyNx2ZeRnK1JIjXgo9TAautDdFLMlPJktBWJfsA1boE7WZDs4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TLSxRFH3; arc=none smtp.client-ip=209.85.218.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TLSxRFH3" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-ac289147833so20665066b.2; Sat, 08 Mar 2025 10:35:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458939; x=1742063739; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2cOgPHAoL12m9EBozXzMPJw28vDXvvK81+CTquR3Aqw=; b=TLSxRFH3CjZcpJe1ypT8NIzR6hnlr4nZCaXwcW6MghKOdHwNDT2H3LZfXyPEAIyqQi fv4554xtrsQ1qkgGGK5Rxp+lUYO15ayhEujEFlgPSPfx6P/g8aNoMbk3fu5u/gFoAk5P c0R1lwSTT44ofY7YQuDZlmLP6CRMT1f8IqJK7D5cf0iVDXUfDjSgVmKoxh2AVYca9uhT xmP5OwL/beaQ2hrQOyDJqLk2Fp3gagiav6Bpj2p/EAbuQb6Bn7U3hV4dpV2vTBy4e8DT aK0iVZHOpcL4PcwjJk/ww5hZPLYRa1tEtwx8gkAVkx7JQ3MdIxSlepU1VM2kvRRa/RYT cbIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458939; x=1742063739; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2cOgPHAoL12m9EBozXzMPJw28vDXvvK81+CTquR3Aqw=; b=V/8JW9Ym6uz/5Xw8VU30UkBcZ25rRSxTtfqDdkiIGJXOwZQKePvHxW187kLma5XJ8u DIuDpKr61ixOUYoi9wiSHB6ydFSh2GW6rzCeXVN+j64zXBx8jiPPY3F5ApdDfFEUqZtU 3NcdA6oZH7yq8UQWBD++cUh+Oumiwr4oqOIGjsE4dfW130KQlGiprPtw/zfmia2ixYIG ieL8xN0pzsjRyVlOrrWIYdN45qf7t6hKPOGSKynoL6Xa0HaNR1DY9ojBOxav85Pf9xMU o9H316OXVXPL6qllgbimVs3dVeqeoJQuY8LnOnBdCbaV2p64IbG4UQangsPGz9A9bZq5 72NA== X-Forwarded-Encrypted: i=1; AJvYcCWXZXrbEByfD1U6EJuSe4N86hkUE/KvAJGoKIS+tqrKEwEgGNz0P6qgHvsnM2nr9kS0U0nbT3XV8ixdWw==@vger.kernel.org, AJvYcCXhnOVqyU8lc0L/9l0iePcXIkiwIYW8Bv4lRmXgKEg+uEQtvI1mnRPoFSS9Ojqgu940a0LCYL93+HtSgdg=@vger.kernel.org, AJvYcCXr6+z3+H1SgA2dSEHpbP5Rbrwz+2Ly/CyWG0b8Q5fya6XqcZa/c54C3VdE/XBBmfzfZ5oeoNyRmbAblyzq@vger.kernel.org, AJvYcCXu2TKhkD4ZVSfilNvypvdkt7Wne/TSMJPDyPHDGSV2+gg2MDQkPneb9xjdZH6oqlZN6TZFT3fs+iRr@vger.kernel.org X-Gm-Message-State: AOJu0YxhGCHFkL9GexqiH2YSMgbkGOm6Dsb+vXgwXFBBK8id63WLok6x +tK9dY8HbSLbyv+mrSVGn89yF2mefPnB3bwMH62+bXZakrHFHuCs X-Gm-Gg: ASbGnct7eAzdMxYcg1rwDBiqcRShCqrT+rPYZLilbxhKxiXzFAnX3TS/RoR1S6MdijM F1wspuGy9DpoXHsqOcsoLPN0ESSs2Ojla/reLQtlnm30R3gAWbbmUOnzlCNkHwPfM4okGWEVXYx GBdE02gcByAFEG+s2uu+euRDB/3z959OJ0vvB91rZs4N+o+szc77kKpVHo2acB4yBGpw0qP6cJv 1ptHDEaiikTb0ahcVCrs8z+forYDXrxDcYubXz8N0cBTWYXhD0pTKjsW8P+EmBrXkyo5rW2rXjO r2zi7dt2JHeh+m97NseTU24jNQ4n63mkQYx2qhx10IcoxFL9rjY6kVRCUQ== X-Google-Smtp-Source: AGHT+IHcPwKF5eB7VgOS8H61Ng0ywU+slTryB/Bsve8lxLP4Zc7Uc+Ntz4kGcsZJIup2zLzGgH7gHw== X-Received: by 2002:a17:906:5ac8:b0:ac2:7a6d:c918 with SMTP id a640c23a62f3a-ac27a6dd696mr229761566b.57.1741458939203; Sat, 08 Mar 2025 10:35:39 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:38 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 16/24] dt-bindings: media: i2c: max96712: use pattern properties for input ports Date: Sat, 8 Mar 2025 20:33:45 +0200 Message-ID: <20250308183410.3013996-17-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The input ports are all the same, use patternProperties for them. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96712.yaml | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml index efdece2b33b9..148d196b9acc 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml @@ -40,22 +40,10 @@ properties: ports: $ref: /schemas/graph.yaml#/properties/ports - properties: - port@0: + patternProperties: + port@[0-3]: $ref: /schemas/graph.yaml#/properties/port - description: GMSL Input 0 - - port@1: - $ref: /schemas/graph.yaml#/properties/port - description: GMSL Input 1 - - port@2: - $ref: /schemas/graph.yaml#/properties/port - description: GMSL Input 2 - - port@3: - $ref: /schemas/graph.yaml#/properties/port - description: GMSL Input 3 + description: GMSL Input port port@4: $ref: /schemas/graph.yaml#/$defs/port-base From patchwork Sat Mar 8 18:33:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871782 Received: from mail-ed1-f41.google.com (mail-ed1-f41.google.com [209.85.208.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD79020F073; Sat, 8 Mar 2025 18:35:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458946; cv=none; b=j2/tVvqVSBCWDIDJFbOyHBk3w1TbgiGSRqEjoL/fw8x7Px91o/btMy2Mtp6x6E1Xl4BhaX8CKTNMFz7eSCtTaChp5M3toC2qFV+v7Ikg1YaRalOonO0gHMB/RRUi/rlybHrRFUMNeLIsyyMNty44HXQMOaPxpar7x8lI3YMKT/4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458946; c=relaxed/simple; bh=ht5ypYiEkwHxwMKy5bQfucXh4XtSV3csZ6nPeORtxLE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RUW2cM4UW1dm8noxGvdA9BXrJFbnNV1yGqBilkbxWGHUldCeV/g3l1tqwiw+1K9watX1GQEcMtoo8ETDnvobIjqAzPc8ZcQ2l2JTcyJW0rzB8DsMTzHaEpKJfyoJ57A2yzzSQPRGVWjbdS0toFJ7Vx3NdVmN8YXa1/a5HcttUPI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RYf8NqtP; arc=none smtp.client-ip=209.85.208.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RYf8NqtP" Received: by mail-ed1-f41.google.com with SMTP id 4fb4d7f45d1cf-5e5e8274a74so2385927a12.1; Sat, 08 Mar 2025 10:35:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458943; x=1742063743; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZAHmn6rG6ETfCx5uG55oa9NiQsZ2fVF1iLru44ItkPk=; b=RYf8NqtPOq4dpM9xfiq0s80hk4elUFooYEfeody6cUorzBPatau222D26V7gZrK6b8 01lqRQ5eSLN0F9wT0YKmzsPfW/4QseIK+X/0rY7xyl3i7+oGuWOBfTcsZyj2vP2jJw+C 046tf+KXoWNjdFk64vcQ3m+cFwJ5ZdEawK5pzc/XLlEW9YSCw+LFLJYU+xeo7fm9qdlH ZP7C/dz4clHVdhPJz/rlgm94OGtInSjtwLk7vz+FsiN+Kb0WraazB8MNoTbzW1azpVD8 dQH74W+Yy0L0cMOBJgE2w9NUVtItasPfvfIqHBTYC9rqr+/xPaC2nDBvrlm36ZI4K7/q AAqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458943; x=1742063743; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZAHmn6rG6ETfCx5uG55oa9NiQsZ2fVF1iLru44ItkPk=; b=sk7tzFGU4NK6+/Vs4Vnn6vxehiUwGmJOWEc7/mABtYRtJPmCsaebwiXQPFKUUyo82A NfBgGPdT6xHm/QPSzJ6nQ7id/ftsZ2oB6l84rI3fjNHv6UJrgNC3eoN8mLVPX3svHo/4 XnkQjnfWBe0Hr/zZOraDvt2bXw5vH0WCdj4WpqAmvb6/PO9bsrQs4Zsf4GPeihl0cUwA 87h4ivfwIsMObuaR8rA/y7LJlhZt40ruGr9D0iYwltdzu4rYxKLNcTHnX+Mmqdm/ltIi /QDytEDJ9wnhiimsncT0PtOxAAUKKuaQB54cT0oiCqgrGtK+G47ZIr4rC29golB1YLT2 h7Vw== X-Forwarded-Encrypted: i=1; AJvYcCUYn+Me+3Rz0dekqzgZ24K/QkLTuKzYSRDchgQFe2Y9CFpp1+MdaEoUBBHHdsZS81irhG3KPmoYDvPKaETt@vger.kernel.org, AJvYcCVy/2ZhGC9nFhfs9VqlfaPDmuz8rpLpZjz6zedAz7MrNY89EX8l0WqKQ+GhmRfjVRvfzb8wZMeLyLagoQ==@vger.kernel.org, AJvYcCWxmZYm/EjYjnQRRY6BCAxCshNOHGA5t6mGG1j1Bb/qNqFr+msExcrvkolbojdoPvZ2xDkzR3MvDGnL@vger.kernel.org, AJvYcCX0HnSWN2yBol25lSLjaYihnbVRcCBScllgiHDbD4RI4t8P3Onj1Hr/5UOljW+gw3CmQUu/mxhzmZw2aIw=@vger.kernel.org X-Gm-Message-State: AOJu0YywHQpsVV1PsD0HeNJWwYI8uGQyvzJkQdFd1v2ciFI1gB/FKarO f9KOFN3EwzNb2f4E+YoaRaO6xfyNi0Br9+uKaNWr1/B/GkC81jW4 X-Gm-Gg: ASbGnctOAG6huOXWgPKg+bClqiHPIQWZfCxtPmua0wvQ6obaRt6gL42NO6g/7LlbGwP Jwge/ST5VlSkwn1VfAfzPNP/UsUKBTENyxuCUjfipC5musb+K1iImXqjoLe6tDrylctX1hTCKM7 KYV6IpEEEX40+7l35glufJRrVHsaVN8m9cvdXf051SjnNQy//Ru7EQggFeIKRCp4IsKYpmQ8+Pv XE909SRG1KSvZr0E8eOO5Pi/IU6Syhh9+9dDQVGoyAJqU8Q+uDaZG1GKec9HETDX6J8yHDIC2++ wUd9neXqABgSmB9IEQqBUMGlKngWblAINsqHmMieflQ4zUwpI03VV1Lrhw== X-Google-Smtp-Source: AGHT+IGrMwcZh0pY9ViCetXCuLx6l8flR98nHFGVJmFE5NhrBR9RFuGiHgNwfMO7DQSkLgJr5+3lrA== X-Received: by 2002:a05:6402:845:b0:5e5:c76f:c019 with SMTP id 4fb4d7f45d1cf-5e5e22d8d92mr22199896a12.17.1741458942777; Sat, 08 Mar 2025 10:35:42 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:42 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 17/24] dt-bindings: media: i2c: max96712: increase number of output ports Date: Sat, 8 Mar 2025 20:33:46 +0200 Message-ID: <20250308183410.3013996-18-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The MAX96712 and MAX96724 support up to 4 separate PHYs, depending on the selected PHY configuration. Document this possibility by increasing the number of output ports. Signed-off-by: Cosmin Tanislav --- .../bindings/media/i2c/maxim,max96712.yaml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml index 148d196b9acc..52b5603c2f53 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml @@ -45,10 +45,10 @@ properties: $ref: /schemas/graph.yaml#/properties/port description: GMSL Input port - port@4: + port@[4-7]: $ref: /schemas/graph.yaml#/$defs/port-base unevaluatedProperties: false - description: CSI-2 Output + description: CSI-2 Output port properties: endpoint: @@ -66,8 +66,15 @@ properties: - data-lanes - bus-type - required: - - port@4 + anyOf: + - required: + - port@4 + - required: + - port@5 + - required: + - port@6 + - required: + - port@7 required: - compatible From patchwork Sat Mar 8 18:33:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872052 Received: from mail-ed1-f48.google.com (mail-ed1-f48.google.com [209.85.208.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E5EA5218AB7; Sat, 8 Mar 2025 18:35:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458950; cv=none; b=k7r20A7NLoqEhtK2fzUnnefBUNpx+iwQ3+jZEI7T+6QYlkO4Y5R8GEkRY3JxbyhqWdwTmyAppCbBmnY1iDh2sNf36ePhNRZoVLzDyRG864f+cx2O8Hu15JS83b8uoAGwG7Fm17m+PtAZEziMfgVaZYjUfZw9F1bDsfaUj9QWgpw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458950; c=relaxed/simple; bh=NYzMuVB3B9usgVKCiwjaVacmFf7hMikuoDeAMpRnNcc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hN5BoQtWlHPTDqy4VA2ZF08dqq7oYeotIzX1QSUdLtsKms+TAozTwkchMUfhE1KESA1p+wCcHtcKcOq1Wnz3/7/qtNhJ+Zq7FoWdRBsxb6ULk8Jb9OdfRl34BjlyabfsK1oIluXHlekL8duFAIrIaml8D7MS1OMwIaT0oVE+/2o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ABvEsHfG; arc=none smtp.client-ip=209.85.208.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ABvEsHfG" Received: by mail-ed1-f48.google.com with SMTP id 4fb4d7f45d1cf-5e5deb6482cso4249130a12.1; Sat, 08 Mar 2025 10:35:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458947; x=1742063747; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CK5bDbReHG6fPNd1fjSjzJA7YFApuP2BjpPfIh5cqv4=; b=ABvEsHfGc/0NElZ5yFStmfuO467VxeTwzqqZYhWrKZQe34+TxzwIkeZLWygT18KznU tyJL8vtfZShNw5d0aCvKX7KbKtuSF+nmOJ1y0cRD0tb3G5DM2NmiLC4PLdNn8aFn43Kn kxPHz7UROPqnHN4ONV/SziJAqQwEW5zzaOq4kBCDeAHF5ClqpfZErBd2WCDBfRys/Wy7 sZx7qlzYFr5IYw5KqtZuvLOtzToTBtququvEo9CRAnJF1imm7fwyYwbnnauLUGmp3c3U UpTtibPY8zZ5VwelNUW+zAGzG9nwxaj06uJqmTvD0O66F/gkJLRR9/UGm6oi/oQxABwh Yh+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458947; x=1742063747; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CK5bDbReHG6fPNd1fjSjzJA7YFApuP2BjpPfIh5cqv4=; b=sMKZh2JU+r20F009jvMrz0X6Y9+T6ncL52HOQwzayY9vvqks17iO7P+CJciuXNwGbQ Hc9kCJBjEIdkuSwF6JNMrfUejNWvtHwW4uN0XeBKKyymgwmeOyaqpYk//wKWtWmxkiGB V0S/0+oaVrzk9iJzB4u/3tp0MGKyAB9FXU7h3IIJVmSNfe0AWS92wiEM3l2I05jcEAsO yshDIQAfuWOk0h8qHMEiBbJgcHNpuM43tUq5W4zqnPAN8YMUZYZRL8eMzPek/VOUHk0P JUiIpcOVp2il/wb8kUPUY5PVsolHOlT0e9gUcfGRVjwaa3AYpLHZ/5Lvt8TA5M5vMNcP MaFQ== X-Forwarded-Encrypted: i=1; AJvYcCUgWXH5KjWzv5Gq1pmmF1RTBFrtZuwVaFyXsUWX5lCRb5QNjf2uUb87Zt2oqsLPw8XyEI1iGKFiZcZh8w==@vger.kernel.org, AJvYcCW5GITBaPqpfQvJNvmuXvPkktdI7Nsie0jqKTJqllghgxTH1qr+BuvVhZsZacOTDjbx07SjgrYKPMw2@vger.kernel.org, AJvYcCWR3Q7PIbcykVYno2e586GtDy5WwvUMAa+57qe7gUht/hv7wqKiVP0kOy6cpMUmvf8kzLdkKjTdKdlfYlxQ@vger.kernel.org, AJvYcCWv3glNR1wc0SSMPMWhBvryjYJ8uWGWWOa2w9+Vw2SOGRJl8waBO+uzawHACNTW4+0V7yU+dV5pWADkbpI=@vger.kernel.org X-Gm-Message-State: AOJu0YyTvTU72XI5BrKW3dHglTmgMi6OmSQpoqGcFNyrhd+Rhje1kmCR 9yr/oSpM2naCN5A6YqOJeGtl6zUszUwpTK7cc4JqqNl/J3IX/DD+ X-Gm-Gg: ASbGncvMpQ8CkvvLSt9b0l/cfoEHrexLXWnrieHEPrXXaC8sF8M4R01u7wuUb5wY16f U5k4njnq6FxmwBWVCd0v26JE8Vhh/PNePjGn0qiTWJ7uSmqq54PnFX8//0weLZwK/8gGBSudMLo 5JBau1VXzE+Bgb42y6EnyeXixpSwlskBNZTiSgmMCD23Pf7+NlsqOIW4LlkBB1r++YnTdiLYRFo Wl5RpnKHgV6w4C5a2GjrLQmnJnAPYBoCKH+upYsfBs7uJp6G+IfQIUPgqjQeB2EzTPX+SBwkvRc yGSt0qKfi2q18y6udmKKBbwzwnG9cF2KidYkQS9YUbcqN5aQlPl3qfgYIQ== X-Google-Smtp-Source: AGHT+IGYYdE8ygjHkGbwYFxdRuN7/SMwMWgaOvxuGGIjcdc5JQxB3kxCPC7VbHX7VMiCBnhZf/DQyA== X-Received: by 2002:a17:907:c313:b0:abf:27ac:2cf8 with SMTP id a640c23a62f3a-ac26cbc5b28mr427259166b.21.1741458946975; Sat, 08 Mar 2025 10:35:46 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:46 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 18/24] dt-bindings: media: i2c: max96712: add support for I2C MUX Date: Sat, 8 Mar 2025 20:33:47 +0200 Message-ID: <20250308183410.3013996-19-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 MAX96712 and MAX96724 have more than one GMSL2 link, and each link is capable of connecting to a separate serializer. If these serializers have the same CFG pins configuration, they will also have the same I2C address, causing conflicts unless the deserializer muxes the I2C channels. Moreover, the serializers can have the same hardware attached to their respective I2C bus. The MAX96712 and MAX96724 suppot I2C channel muxing via the GMSL2 link to facilitate communication to each of the connected serializers. Document this capability. Signed-off-by: Cosmin Tanislav --- .../devicetree/bindings/media/i2c/maxim,max96712.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml index 52b5603c2f53..4c4542d041cd 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml @@ -37,6 +37,17 @@ properties: enable-gpios: true + i2c-mux: + $ref: /schemas/i2c/i2c-mux.yaml# + patternProperties: + '^i2c@[0-3]$': + $ref: /schemas/i2c/i2c-controller.yaml# + properties: + reg: + items: + min: 0 + max: 3 + ports: $ref: /schemas/graph.yaml#/properties/ports From patchwork Sat Mar 8 18:33:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871781 Received: from mail-ed1-f43.google.com (mail-ed1-f43.google.com [209.85.208.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C098219308; Sat, 8 Mar 2025 18:35:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458954; cv=none; b=OEYCQ7jSWuLTl1qojBYxqpowoO/8Tby2dbe4xoLnRridqShBxmZZ1D8PbN60+7gbHsHHlKunH8ZAqrrFjhGLmXUdck6mQQVpswBrJUOV5BPZES/7KxYUIXia12obY/tlI4SQXg/2DHFeRI7Xye+UBPJoQN8My18BUdHEOlHq+Nc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458954; c=relaxed/simple; bh=FznTDNtKWojR9Ye+Jrb2h3xMj/oOzdqTZQIRY2kpr2g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ttpLbixeAdRRG7EdYR3m6sqcX3NkcdXJPN0UfKgtzXRcrgii7D3f34UsfCQTVESV5EhRbFhIGd7ze1C3OS7UjrERxTYXzzcgURKwmdqzhmKoTNlkAIdstd7wPEPxxhR6YPaPeKgkUCLbNaDg6l8dtoBr4NchPAxSBZ3pRKAlpa0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=J8XRsgKM; arc=none smtp.client-ip=209.85.208.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="J8XRsgKM" Received: by mail-ed1-f43.google.com with SMTP id 4fb4d7f45d1cf-5dca468c5e4so5411461a12.1; Sat, 08 Mar 2025 10:35:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458951; x=1742063751; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Xre/RsxIANW+aBbofEjpmFCtWlH5fWozQWnveyUbcrg=; b=J8XRsgKMOHu2TBg4z5a0qtt2Vd45kaocrsCnDkXfs14wJDtgrLQ2RVLBFeCzuJMnJE 0+ptHgTsMg5qJmqtU+DU97wssHQzGIjqxBwixRmzgkkhq89CO6HbidUGjh4Pk58vWdBL jE+AIwvfCTV8rZT8z3v9/IG2+3TMrfiCV9HrTNWpaD1Tr/MmZdoFCrSHAzCbg9BwdyXt 36lNC1TTsy7Kyk9U5unuip1XZlLM5MI7So+S76F4kjhT3voKmxJafv1cx72sZhMvZ85T bjo/p9c681OtTysE+YG6S97A70HNVA7Drb7Qk9QV/EdfbMCCAsaMK7jBZFU//99QOATP 2ObQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458951; x=1742063751; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Xre/RsxIANW+aBbofEjpmFCtWlH5fWozQWnveyUbcrg=; b=tHVpQsmEzCnREU7cpz2tB9ngPSQb/W/E7Kj10TpcyG6e4QU4kXMNvLkkaqH1HwKtva ORG3zqNqeDPfgzo7azoJA8LWZOC+cpJ7GnoPMCMM3o5X90k8DmaBgDm9kKt8BaDxqowb ZrhBJAOe42ZZivz/wtA5mVFcA+z/6nhoIUEH3pMadepzr2RJncFvRA/79DlJqY9ONrof haQDmliC6q6yAyjkwmZu+muoBzSY7odINs3RQyN5cNJRVkWknIO86oJ5XuKJB9R4tn9j dlf3V+shTE/p+I0AXqKVfowkG8b++NFZMZv0yN0Bc2WP5siIAd2dtFAJSGthD5vPhZVH WaoA== X-Forwarded-Encrypted: i=1; AJvYcCU/zt10ENGanLOBQplZ8GemsI95KdgHY4Byru+ESNrkPcvf2xTC5LRY0zmeIO2EEJq+H9NeEvV/DhrMZe0=@vger.kernel.org, AJvYcCUfdoDbZqx9ha12cEcVQRqak8be5DTFlZStMV8IgWAVxwX1Y0OV9cZY7ItTg6jttsTrvsBjTvDDtM+oaA==@vger.kernel.org, AJvYcCVonjNrv899RzAoUv9JjxeRVoVbJCw8SQAfGX1V+Wosawyj3KjiK+OLeaFix430s1Rj6AxIYfGvuLRH@vger.kernel.org, AJvYcCXg2pNf9+7g3OwzwmbDhCRXGQmsyQFQeL+EpjrZ87lyTwzA6MFSVTHQcZIfEASKj76IsHmpKi9U1u2xUlTe@vger.kernel.org X-Gm-Message-State: AOJu0YyNRaOvqRFLSLwNo7rrPTUnozCBv0iRVNHQ27x3PGnZUTFTlIYw Aj4z8+Gl7G+OhLz+Sd/8X313SYf6GkBOhrVknzP87U0mFjEUC4HW X-Gm-Gg: ASbGncs8k7gOe6YaNdVvd7MTQ1bmustJfwuUKAWBH7nfJkw7ya8ZHR1JuhQE0pUBAza nEQVilCZ/slJZEWF4ZzBmhyzUN2Rdt3E3/Ycyy1f4Jcd91ntSt23ituZx8YmmaC1FmBkGlGDBQ3 r23rAb8Z7ChNKCtQv+wn4sC7txgaFgsAKSqRmQXyZtup5FHeCfqx1WvXoRPWD9qriVOFshkMleG kQAqNSolNUPOmaNp4uCUlTA0NBcB4s/5Q92LbEvcDhlxd+pL2LNtw7U3WQW6OtyXf00ct6tWzfb jCNgQsuYvgDkKhTXTEMdHaX1V8snyD4TCmvlT1i5UorK6txXhEfUHqWvHQ== X-Google-Smtp-Source: AGHT+IE7HcMcv8UGE2u8zJcS8GFDxgYSucRdRKjubTzY1De4Hv/qmaFr8IpaN1Nvc57DsiT+CQcqYA== X-Received: by 2002:a17:907:94d4:b0:ac1:df33:25b9 with SMTP id a640c23a62f3a-ac252ba291fmr945250566b.40.1741458950505; Sat, 08 Mar 2025 10:35:50 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:50 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 19/24] dt-bindings: media: i2c: max96712: add support for POC supplies Date: Sat, 8 Mar 2025 20:33:48 +0200 Message-ID: <20250308183410.3013996-20-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The GMSL links can carry power to the serializer when using coaxial cables. Document this capability. Signed-off-by: Cosmin Tanislav --- .../devicetree/bindings/media/i2c/maxim,max96712.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml index 4c4542d041cd..1680d99b1f36 100644 --- a/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml +++ b/Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml @@ -87,6 +87,10 @@ properties: - required: - port@7 +patternProperties: + port[0-3]-poc-supply: + description: Regulator providing Power over Coax for GMSL ports + required: - compatible - reg From patchwork Sat Mar 8 18:33:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872050 Received: from mail-ej1-f52.google.com (mail-ej1-f52.google.com [209.85.218.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72376212B0D; Sat, 8 Mar 2025 18:35:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458967; cv=none; b=SxlVo/C7f+dmeIMTunnk4qrLAkNpaJewDFZ6HrHHcv9d78TM3YkL5MGVjbMAZrDyhme4LV92kiojF7ZgCRCgpnVVxr5ioYXXFyhn+T0UqEoKtFo+XetANaDauT9uO96IbrWD29CCZSCEx/WJEV310S7GBHOefJ0zBTUpzVcG0Vs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458967; c=relaxed/simple; bh=y4whjALQZg+P/OLcsWb766X/V1MhXqrmOTCYTpQOOPY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ny6G6r0RqiKx7Nac9XAyZ6ag75Yo5T+sAgmVeUn88rPHwKxe83DfgQ7oVVHLZZKzWujD9UmBw4jDAgtkd8E7Iih/EF/fVt24jRKia8I9p7jNhKqe/Epa8skmVEW19JqJPf1oQW5YS/rk6gorR1e9C/XmDZlB7lgbNKETCaMlC3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=RUqvGHx3; arc=none smtp.client-ip=209.85.218.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="RUqvGHx3" Received: by mail-ej1-f52.google.com with SMTP id a640c23a62f3a-abf42913e95so422743266b.2; Sat, 08 Mar 2025 10:35:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458956; x=1742063756; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5N/DEI53LWLGMEcSR2vbQPhx1cD+OxD0OXwViKV1oMM=; b=RUqvGHx3AwOaneEy1oS+02k3CdZZWbRVwJRXwc9+inDyl+sOz5PcWIR2Xu2bN00vwa xuMb/y0FV5n4oF/wRnh2iPyAHwmbXPgmmXmc+K3U1jdK9gX4uEbxoq3jaZsYkHzS+tSr FWOuKmmvKTAUB/FjZQdjlwu8yd4ehqx4QCWrauvbhlkx+r/+d6EUea728yVL+XYC3cj+ nHfrBQ4Tl1YZePLB7loi/tuvbS27mJbrUsKP1M8PAw+vK29Fn3Pu3SMQY/qO9pkdpjue 3qJv4u1mFOBT3FcIAGofsFCkEXp/yXltR/K3hNH9xxSXRLe0JTlq9ilBtOgNYBWD6K5E HgJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458956; x=1742063756; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5N/DEI53LWLGMEcSR2vbQPhx1cD+OxD0OXwViKV1oMM=; b=HT3UIwLIm99IvBC/ZjpH+rDiUyS43ME+c0QYTuPFfO4J7VYQmzmK8rekUgegZ6Mld4 2iAvB/f4DaaJcdL87VUS3OQ1P795qL4glvfE8pOxgU8K5ZH2ALAGhfpfSZvpNT6YGGbR zLbYx+FRpbeD2blTRQ87bvKJKtwrJ6rioI3XnFvujb47DENvPDIk5bfpVHRfV7pkCxNb vDOpH1Z0CjHlZNNiVUVP7q7fS7PSiQAeC8eGEaZRiIcNvdjBM+V4EVDOLbwO8dQ1hGiv DrNqgoApNrWkBltf3JsOmnIHcuo071891zTrbGYzTYO87VXZHuIJuYfmOlDLgwL/+EVK qTKw== X-Forwarded-Encrypted: i=1; AJvYcCVV7Oc7S52rVbj9onSZOBb4wlZw+QlgVuF4WvZg94DTWKNrfX4Brtj6lfc/FWjIJK4IvzQ+LlQRPQW9@vger.kernel.org, AJvYcCVx9cefxJNvCC40gTR+no8AK2tmw9cgeG1Dmpdwj7JwqZv31MN7ZsrOGjDHiM/AxeWE+C0jataAfx+V77A=@vger.kernel.org, AJvYcCWKMU7V9EJ4Fp2Hi7v2UZobUo9KYcLlU61/YWHbLmvpF5Blh8CzmKuInQG5Rcorhjj6l0AogcOxgo6qew==@vger.kernel.org, AJvYcCXGj3SUXJItfYT/Do7Wo6ktdwpoE42WPgsUj3Lu1vS62pKBGIq9b4YIBA7ZlmsadOWArSc3W9hCtLOFT3KP@vger.kernel.org X-Gm-Message-State: AOJu0YziszdLxc3yv1o+S52R/bfO9iZXileLzeUElKfNg8u2p+Lj2jQj FqLnOFjs7z+ZTcppBv28DTZKEEQecqrGrHatPtv7vKFJNZs9ovoM X-Gm-Gg: ASbGnctVEhPBincoUu7Mp/f0R+cMzjhuZIu991+wCU3ERovMAEXVwcW5BbgzL8fKQ2I gjGJQyhKVlnc9SITLivZWp9o1VW/MqhevVZamVGB7xGnM6jqkwkKjEv8LD4SieIoHpIUVAMNTC1 YhGtsiupHnAC/cNaF5OVieee1zGaulStGuIdvmAupGss3321c5FPjZLEOnkY2zWGEAbWJziMmpD wkavyndxt0NKmjXXNURpeHhtYc4ddeWI1ZYCuRH/lGlu0AumI57ALnDVFGDvJJ5jVD+knGlkROm tmgsJQsiJR7muEeMmEyrKRF/eMfPEJBy7u3nowNLaC9vjR0SzW+ASm+jgw== X-Google-Smtp-Source: AGHT+IECSkcBwy3TykdhLvVWbUATd43tp1oy68VROJYCT8ZlylBZ87PLWKaQedxpG4aVf7lrY0+kBQ== X-Received: by 2002:a17:906:7303:b0:ac1:ff43:82ae with SMTP id a640c23a62f3a-ac252747c77mr886358366b.2.1741458954783; Sat, 08 Mar 2025 10:35:54 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:53 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 20/24] media: i2c: add Maxim GMSL2/3 serializer and deserializer drivers Date: Sat, 8 Mar 2025 20:33:49 +0200 Message-ID: <20250308183410.3013996-21-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add drivers for some of the broad-market Maxim GMSL2 / GMSL3 serializers and deserializers. These drivers are meant to replace the existing MAX96712 / MAX96714 / MAX96717 drivers, while integrating them in a common framework, keeping compatibility with existing usecases, and avoiding code duplication, while also enabling more features across the whole range. These drivers also add support for the following new chips: * MAX96716 (GMSL2) * MAX9296A (GMSL2) * MAX96792A (GMSL3) * MAX9295A (GMSL2) * MAX96793 (GMSL3) These drivers enable support for the following new features: * Full Streams API support * .get_frame_desc() * .get_mbus_config() * I2C ATR, I2C MUX * automatic VC remapping * automatic pixel mode / tunnel mode selection * automatic double mode selection * logging of internal state and chip status registers via .log_status() * PHY modes * serializer pinctrl Signed-off-by: Cosmin Tanislav --- MAINTAINERS | 6 + drivers/media/i2c/Kconfig | 2 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/maxim-serdes/Kconfig | 53 + drivers/media/i2c/maxim-serdes/Makefile | 6 + drivers/media/i2c/maxim-serdes/max9296a.c | 1146 +++++++++ drivers/media/i2c/maxim-serdes/max96717.c | 1500 ++++++++++++ drivers/media/i2c/maxim-serdes/max96724.c | 905 ++++++++ drivers/media/i2c/maxim-serdes/max_des.c | 2321 +++++++++++++++++++ drivers/media/i2c/maxim-serdes/max_des.h | 135 ++ drivers/media/i2c/maxim-serdes/max_ser.c | 1584 +++++++++++++ drivers/media/i2c/maxim-serdes/max_ser.h | 132 ++ drivers/media/i2c/maxim-serdes/max_serdes.c | 302 +++ drivers/media/i2c/maxim-serdes/max_serdes.h | 88 + 14 files changed, 8181 insertions(+) create mode 100644 drivers/media/i2c/maxim-serdes/Kconfig create mode 100644 drivers/media/i2c/maxim-serdes/Makefile create mode 100644 drivers/media/i2c/maxim-serdes/max9296a.c create mode 100644 drivers/media/i2c/maxim-serdes/max96717.c create mode 100644 drivers/media/i2c/maxim-serdes/max96724.c create mode 100644 drivers/media/i2c/maxim-serdes/max_des.c create mode 100644 drivers/media/i2c/maxim-serdes/max_des.h create mode 100644 drivers/media/i2c/maxim-serdes/max_ser.c create mode 100644 drivers/media/i2c/maxim-serdes/max_ser.h create mode 100644 drivers/media/i2c/maxim-serdes/max_serdes.c create mode 100644 drivers/media/i2c/maxim-serdes/max_serdes.h diff --git a/MAINTAINERS b/MAINTAINERS index 84078626ed5a..1bc0ef81a1f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14221,6 +14221,12 @@ S: Maintained F: Documentation/devicetree/bindings/iio/proximity/maxbotix,mb1232.yaml F: drivers/iio/proximity/mb1232.c +MAXIM GMSL2 SERIALIZERS AND DESERIALIZERS +M: Cosmin Tanislav +L: linux-media@vger.kernel.org +S: Maintained +F: drivers/media/i2c/maxim-serdes/ + MAXIM MAX11205 DRIVER M: Ramona Bolboaca L: linux-iio@vger.kernel.org diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index e576b213084d..e24c84962c92 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1653,6 +1653,8 @@ config VIDEO_MAX96717 To compile this driver as a module, choose M here: the module will be called max96717. +source "drivers/media/i2c/maxim-serdes/Kconfig" + endmenu endif # VIDEO_DEV diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index 6c23a4463527..b24e7cf7bb2f 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o obj-$(CONFIG_VIDEO_MAX9286) += max9286.o obj-$(CONFIG_VIDEO_MAX96714) += max96714.o obj-$(CONFIG_VIDEO_MAX96717) += max96717.o +obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim-serdes/ obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o obj-$(CONFIG_VIDEO_MT9M001) += mt9m001.o diff --git a/drivers/media/i2c/maxim-serdes/Kconfig b/drivers/media/i2c/maxim-serdes/Kconfig new file mode 100644 index 000000000000..fafa6a47d5eb --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/Kconfig @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 + +config VIDEO_MAXIM_SERDES + tristate "Maxim GMSL2 Serializer and Deserializer support" + depends on VIDEO_DEV + select I2C_ATR + select I2C_MUX + select MEDIA_CONTROLLER + select V4L2_FWNODE + select VIDEO_V4L2_SUBDEV_API + help + This driver supports the Maxim GMSL2 common Serializer and Deserializer + framework. + + To compile this driver as a module, choose M here: the + module will be called max_serdes. + +config VIDEO_MAX96717 + tristate "Maxim MAX96717 GMSL2 Serializer support" + depends on OF && COMMON_CLK + select VIDEO_MAXIM_SERDES + select GENERIC_PINCONF + select GENERIC_PINCTRL_GROUPS + select GENERIC_PINMUX_FUNCTIONS + select GPIOLIB + help + This driver supports the Maxim MAX96717 GMSL2 Serializer, + which receives video on a MIPI CSI-2 interface and outputs it + on a GMSL2 link. + + To compile this driver as a module, choose M here: the + module will be called max96717. + +config VIDEO_MAX96724 + tristate "Maxim MAX96724 Quad GMSL2 Deserializer support" + select VIDEO_MAXIM_SERDES + help + This driver supports the Maxim MAX96724 Quad GMSL2 Deserializer, + which converts from four GMSL2/1 to 1, 2 or 4 MIPI D-PHY or + C-PHY outputs. + + To compile this driver as a module, choose M here: the + module will be called max96724. + +config VIDEO_MAX9296A + tristate "Maxim MAX9296A Dual GMSL2 Deserializer support" + select VIDEO_MAXIM_SERDES + help + This driver supports the Maxim MAX9296A Dual GMSL2 Deserializer, + which converts from two GMSL2/1 to 1 or 2 MIPI D-PHY outputs. + + To compile this driver as a module, choose M here: the + module will be called max9296a. diff --git a/drivers/media/i2c/maxim-serdes/Makefile b/drivers/media/i2c/maxim-serdes/Makefile new file mode 100644 index 000000000000..ae306bc33bfb --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +max-serdes-objs := max_serdes.o max_ser.o max_des.o +obj-$(CONFIG_VIDEO_MAXIM_SERDES) += max-serdes.o +obj-$(CONFIG_VIDEO_MAX96717) += max96717.o +obj-$(CONFIG_VIDEO_MAX96724) += max96724.o +obj-$(CONFIG_VIDEO_MAX9296A) += max9296a.o diff --git a/drivers/media/i2c/maxim-serdes/max9296a.c b/drivers/media/i2c/maxim-serdes/max9296a.c new file mode 100644 index 000000000000..d2ee4cccb633 --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max9296a.c @@ -0,0 +1,1146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Maxim MAX9296A Quad GMSL2 Deserializer Driver + * + * Copyright (C) 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include + +#include "max_des.h" + +#define MAX9296A_REG0 0x0 + +#define MAX9296A_REG1 0x1 +#define MAX9296A_REG1_DIS_REM_CC_A BIT(4) +#define MAX9296A_REG1_RX_RATE_A GENMASK(1, 0) +#define MAX9296A_REG1_RX_RATE_6Gbps 0b10 +#define MAX9296A_REG1_RX_RATE_12Gbps 0b11 + +#define MAX9296A_REG2 0x2 +#define MAX9296A_REG2_VID_EN(p) BIT((p) + 4) + +#define MAX9296A_REG3 0x3 +#define MAX9296A_REG3_DIS_REM_CC_B BIT(2) + +#define MAX9296A_REG4 0x4 +#define MAX9296A_REG4_GMSL3_X(x) BIT((x) + 6) +#define MAX9296A_REG4_RX_RATE_B GENMASK(1, 0) + +#define MAX9296A_REG6 0x6 +#define MAX9296A_REG6_GMSL2_X(x) BIT((x) + 6) + +#define MAX9296A_CTRL0 0x10 +#define MAX9296A_CTRL0_LINK_CFG GENMASK(1, 0) +#define MAX9296A_CTRL0_AUTO_LINK BIT(4) +#define MAX9296A_CTRL0_RESET_ONESHOT BIT(5) +#define MAX9296A_CTRL0_RESET_ALL BIT(7) + +#define MAX9296A_CTRL2 0x12 +#define MAX9296A_CTRL2_RESET_ONESHOT_B BIT(5) + +#define MAX9296A_MIPI_TX0(x) (0x28 + (x) * 0x5000) +#define MAX9296A_MIPI_TX0_RX_FEC_EN BIT(1) + +#define MAX9296A_RX50(p) (0x50 + (p)) +#define MAX9296A_RX50_STR_SEL GENMASK(1, 0) + +#define MAX9296A_VIDEO_PIPE_EN 0x160 +#define MAX9296A_VIDEO_PIPE_EN_MASK(p) BIT(p) + +#define MAX9296A_VIDEO_PIPE_SEL 0x161 +#define MAX9296A_VIDEO_PIPE_SEL_STREAM(p) (GENMASK(1, 0) << ((p) * 3)) + +#define MAX9296A_VPRBS(p) (0x1dc + (p) * 0x20) +#define MAX9296A_VPRBS_VIDEO_LOCK BIT(0) + +#define MAX9296A_BACKTOP12 0x313 +#define MAX9296A_BACKTOP12_CSI_OUT_EN BIT(1) + +#define MAX9296A_BACKTOP21 0x31c +#define MAX9296A_BACKTOP21_BPP8DBL(p) BIT(4 + (p)) + +#define MAX9296A_BACKTOP22(x) (0x31d * (x) * 0x3) +#define MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL GENMASK(4, 0) +#define MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL_EN BIT(5) + +#define MAX9296A_BACKTOP24 0x31f +#define MAX9296A_BACKTOP24_BPP8DBL_MODE(p) BIT(4 + (p)) + +#define MAX9296A_BACKTOP32 0x327 +#define MAX9296A_BACKTOP32_BPP10DBL(p) BIT(p) +#define MAX9296A_BACKTOP32_BPP10DBL_MODE(p) BIT(4 + (p)) + +#define MAX9296A_BACKTOP33 0x328 +#define MAX9296A_BACKTOP32_BPP12DBL(p) BIT(p) + +#define MAX9296A_MIPI_PHY2 0x332 +#define MAX9296A_MIPI_PHY2_PHY_STDBY_N(x) (GENMASK(5, 4) << ((x) * 2)) + +#define MAX9296A_MIPI_PHY3(x) (0x333 + (x)) +#define MAX9296A_MIPI_PHY3_PHY_LANE_MAP_4 GENMASK(7, 0) + +#define MAX9296A_MIPI_PHY5(x) (0x335 + (x)) +#define MAX9296A_MIPI_PHY5_PHY_POL_MAP_0_1 GENMASK(1, 0) +#define MAX9296A_MIPI_PHY5_PHY_POL_MAP_2_3 GENMASK(4, 3) +#define MAX9296A_MIPI_PHY5_PHY_POL_MAP_CLK(x) ((x) == 0 ? BIT(5) : BIT(2)) + +#define MAX9296A_MIPI_PHY18 (0x342) +#define MAX9296A_MIPI_PHY18_CSI2_TX_PKT_CNT(x) (GENMASK(3, 0) << (4 * (x))) + +#define MAX9296A_MIPI_PHY20 (0x342) +#define MAX9296A_MIPI_PHY20_PHY_PKT_CNT(x) (GENMASK(3, 0) << (4 * (x))) + +#define MAX9296A_MIPI_TX3(x) (0x403 + (x) * 0x40) +#define MAX9296A_MIPI_TX3_DESKEW_INIT_8X32K FIELD_PREP(GENMASK(2, 0), 0b001) +#define MAX9296A_MIPI_TX3_DESKEW_INIT_AUTO BIT(7) + +#define MAX9296A_MIPI_TX4(x) (0x404 + (x) * 0x40) +#define MAX9296A_MIPI_TX4_DESKEW_PER_2K FIELD_PREP(GENMASK(2, 0), 0b001) +#define MAX9296A_MIPI_TX4_DESKEW_PER_AUTO BIT(7) + +#define MAX9296A_MIPI_TX10(x) (0x40a + 0x40 * (x)) +#define MAX9296A_MIPI_TX10_CSI2_LANE_CNT GENMASK(7, 6) +#define MAX9296A_MIPI_TX10_CSI2_CPHY_EN BIT(5) + +#define MAX9296A_MIPI_TX11(p) (0x40b + (p) * 0x40) +#define MAX9296A_MIPI_TX12(p) (0x40c + (p) * 0x40) + +#define MAX9296A_MIPI_TX13(p, x) (0x40d + (p) * 0x40 + (x) * 0x2) +#define MAX9296A_MIPI_TX13_MAP_SRC_DT GENMASK(5, 0) +#define MAX9296A_MIPI_TX13_MAP_SRC_VC GENMASK(7, 6) + +#define MAX9296A_MIPI_TX14(p, x) (0x40e + (p) * 0x40 + (x) * 0x2) +#define MAX9296A_MIPI_TX14_MAP_DST_DT GENMASK(5, 0) +#define MAX9296A_MIPI_TX14_MAP_DST_VC GENMASK(7, 6) + +#define MAX9296A_MIPI_TX45(p, x) (0x42d + (p) * 0x40 + (x) / 4) +#define MAX9296A_MIPI_TX45_MAP_DPHY_DEST(x) (GENMASK(1, 0) << (2 * ((x) % 4))) + +#define MAX9296A_MIPI_TX51(x) (0x433 + (x) * 0x40) +#define MAX9296A_MIPI_TX51_ALT_MEM_MAP_12 BIT(0) +#define MAX9296A_MIPI_TX51_ALT_MEM_MAP_8 BIT(1) +#define MAX9296A_MIPI_TX51_ALT_MEM_MAP_10 BIT(2) +#define MAX9296A_MIPI_TX51_ALT2_MEM_MAP_8 BIT(4) + +#define MAX9296A_MIPI_TX52(x) (0x434 + 0x40 * (x)) +#define MAX9296A_MIPI_TX52_TUN_DEST BIT(1) +#define MAX9296A_MIPI_TX52_TUN_EN BIT(0) + +#define MAX9296A_GMSL1_EN 0xf00 +#define MAX9296A_GMSL1_EN_LINK_EN GENMASK(1, 0) + +#define MAX9296A_RLMS3E(x) (0x143e + 0x100 * (x)) +#define MAX9296A_RLMS3F(x) (0x143f + 0x100 * (x)) +#define MAX9296A_RLMS49(x) (0x1449 + 0x100 * (x)) +#define MAX9296A_RLMS7E(x) (0x147e + 0x100 * (x)) +#define MAX9296A_RLMS7F(x) (0x147f + 0x100 * (x)) +#define MAX9296A_RLMSA3(x) (0x14a3 + 0x100 * (x)) +#define MAX9296A_RLMSA5(x) (0x14a5 + 0x100 * (x)) +#define MAX9296A_RLMSD8(x) (0x14d8 + 0x100 * (x)) + +#define MAX9296A_DPLL_0(x) (0x1c00 + ((x) == 0 ? 1 : 2) * 0x100) +#define MAX9296A_DPLL_0_CONFIG_SOFT_RST_N BIT(0) + +#define field_get(mask, val) (((val) & (mask)) >> __ffs(mask)) +#define field_prep(mask, val) (((val) << __ffs(mask)) & (mask)) + +#define MAX9296A_PIPES_NUM 4 +#define MAX9296A_PHYS_NUM 2 + +static const struct regmap_config max9296a_i2c_regmap = { + .reg_bits = 16, + .val_bits = 8, +}; + +struct max9296a_priv { + struct max_des des; + const struct max9296a_chip_info *info; + + struct device *dev; + struct i2c_client *client; + struct regmap *regmap; + + struct gpio_desc *gpiod_pwdn; +}; + +struct max9296a_chip_info { + unsigned int max_register; + enum max_gmsl_version versions; + unsigned int num_pipes; + unsigned int pipe_hw_ids[MAX9296A_PIPES_NUM]; + unsigned int phy_hw_ids[MAX9296A_PIPES_NUM]; + unsigned int num_phys; + unsigned int num_links; + struct max_phys_configs phys_configs; + bool select_resets_link; + bool has_per_link_reset; + bool phy0_lanes_0_1_on_second_phy; + bool polarity_on_physical_lanes; + bool supports_cphy; + bool supports_phy_log; + bool adjust_rlms; + bool fix_tx_ids; + + int (*set_pipe_stream_id)(struct max_des *des, struct max_des_pipe *pipe, + unsigned int stream_id); + int (*set_pipe_enable)(struct max_des *des, struct max_des_pipe *pipe, + bool enable); + int (*set_pipe_phy)(struct max_des *des, struct max_des_pipe *pipe, + struct max_des_phy *phy); + int (*set_pipe_tunnel_enable)(struct max_des *des, struct max_des_pipe *pipe, + bool enable); + int (*select_links)(struct max_des *des, unsigned int mask); + int (*select_link_version)(struct max_des *des, struct max_des_link *link, + enum max_gmsl_version version); +}; + +#define des_to_priv(_des) \ + container_of(_des, struct max9296a_priv, des) + +static int max9296a_wait_for_device(struct max9296a_priv *priv) +{ + unsigned int i; + int ret; + + for (i = 0; i < 10; i++) { + unsigned int val; + + ret = regmap_read(priv->regmap, MAX9296A_REG0, &val); + if (!ret && val) + return 0; + + msleep(100); + + dev_err(priv->dev, "Retry %u waiting for deserializer: %d\n", i, ret); + } + + return ret; +} + +static int max9296a_reset(struct max9296a_priv *priv) +{ + int ret; + + ret = max9296a_wait_for_device(priv); + if (ret) + return ret; + + ret = regmap_set_bits(priv->regmap, MAX9296A_CTRL0, + MAX9296A_CTRL0_RESET_ALL); + if (ret) + return ret; + + msleep(100); + + ret = max9296a_wait_for_device(priv); + if (ret) + return ret; + + return 0; +} + +static unsigned int max9296a_pipe_id(struct max9296a_priv *priv, + struct max_des_pipe *pipe) +{ + return priv->info->pipe_hw_ids[pipe->index]; +} + +static unsigned int max9296a_phy_id(struct max9296a_priv *priv, + struct max_des_phy *phy) +{ + return priv->info->phy_hw_ids[phy->index]; +} + +static int max9296a_reg_read(struct max_des *des, unsigned int reg, + unsigned int *val) +{ + struct max9296a_priv *priv = des_to_priv(des); + + return regmap_read(priv->regmap, reg, val); +} + +static int max9296a_reg_write(struct max_des *des, unsigned int reg, + unsigned int val) +{ + struct max9296a_priv *priv = des_to_priv(des); + + return regmap_write(priv->regmap, reg, val); +} + +static int max9626a_log_pipe_status(struct max_des *des, + struct max_des_pipe *pipe, const char *name) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + unsigned int val; + int ret; + + ret = regmap_read(priv->regmap, MAX9296A_VPRBS(index), &val); + if (ret) + return ret; + + pr_info("%s: \tvideo_lock: %u\n", name, + !!(val & MAX9296A_VPRBS_VIDEO_LOCK)); + + return 0; +} + +static int max9296a_log_phy_status(struct max_des *des, + struct max_des_phy *phy, const char *name) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = phy->index; + unsigned int val; + int ret; + + if (!priv->info->supports_phy_log) + return 0; + + ret = regmap_read(priv->regmap, MAX9296A_MIPI_PHY18, &val); + if (ret) + return ret; + + pr_info("%s: \tcsi2_pkt_cnt: %lu\n", name, + field_get(MAX9296A_MIPI_PHY18_CSI2_TX_PKT_CNT(index), val)); + + ret = regmap_read(priv->regmap, MAX9296A_MIPI_PHY20, &val); + if (ret) + return ret; + + pr_info("%s: \tphy_pkt_cnt: %lu\n", name, + field_get(MAX9296A_MIPI_PHY20_PHY_PKT_CNT(index), val)); + + return 0; +} + +static int max9296a_set_enable(struct max_des *des, bool enable) +{ + struct max9296a_priv *priv = des_to_priv(des); + + return regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP12, + MAX9296A_BACKTOP12_CSI_OUT_EN, enable); +} + +static int max9296a_init(struct max_des *des) +{ + struct max9296a_priv *priv = des_to_priv(des); + int ret; + + /* Disable link auto-select. */ + ret = regmap_clear_bits(priv->regmap, MAX9296A_CTRL0, + MAX9296A_CTRL0_AUTO_LINK); + if (ret) + return ret; + + return 0; +} + +static int max9296a_init_phy(struct max_des *des, struct max_des_phy *phy) +{ + struct max9296a_priv *priv = des_to_priv(des); + bool is_cphy = phy->bus_type == V4L2_MBUS_CSI2_CPHY; + unsigned int num_data_lanes = phy->mipi.num_data_lanes; + unsigned int dpll_freq = phy->link_frequency * 2; + unsigned int num_hw_data_lanes; + unsigned int hw_index = max9296a_phy_id(priv, phy); + unsigned int index = phy->index; + unsigned int used_data_lanes = 0; + unsigned int val; + unsigned int i; + int ret; + + if (is_cphy && !priv->info->supports_cphy) { + dev_err(priv->dev, "CPHY not supported\n"); + return -EINVAL; + } + + num_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy); + + /* + * MAX9296A has four PHYs, but does not support single-PHY configurations, + * only double-PHY configurations, even when only using two lanes. + * For PHY 0 + PHY 1, PHY 1 is the master PHY. + * For PHY 2 + PHY 3, PHY 2 is the master PHY. + * Clock is always on the master PHY. + * For first pair of PHYs, first lanes are on the master PHY. + * For second pair of PHYs, first lanes are on the master PHY too. + * + * PHY 0 + 1 + * CLK = PHY 1 + * PHY1 Lane 0 = D0 + * PHY1 Lane 1 = D1 + * PHY0 Lane 0 = D2 + * PHY0 Lane 1 = D3 + * + * PHY 2 + 3 + * CLK = PHY 2 + * PHY2 Lane 0 = D0 + * PHY2 Lane 1 = D1 + * PHY3 Lane 0 = D2 + * PHY3 Lane 1 = D3 + * + * MAX96714 only has two PHYs which cannot support single-PHY configurations. + * Clock is always on the master PHY, first lanes are on PHY 0, even if + * PHY 1 is the master PHY. + * + * PHY 0 + 1 + * CLK = PHY 1 + * PHY0 Lane 0 = D0 + * PHY0 Lane 1 = D1 + * PHY1 Lane 0 = D2 + * PHY1 Lane 1 = D3 + */ + + /* Configure a lane count. */ + ret = regmap_update_bits(priv->regmap, MAX9296A_MIPI_TX10(hw_index), + MAX9296A_MIPI_TX10_CSI2_LANE_CNT, + FIELD_PREP(MAX9296A_MIPI_TX10_CSI2_LANE_CNT, + num_data_lanes - 1)); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX10(hw_index), + MAX9296A_MIPI_TX10_CSI2_CPHY_EN, is_cphy); + if (ret) + return ret; + + /* Configure lane mapping. */ + /* + * The lane of each PHY can be mapped to physical lanes 0, 1, 2, and 3. + * This mapping is exclusive, multiple lanes, even if unused cannot be + * mapped to the same physical lane. + * Each lane mapping is represented as two bits. + */ + val = 0; + for (i = 0; i < num_hw_data_lanes ; i++) { + unsigned int map; + + if (i < num_data_lanes) + map = phy->mipi.data_lanes[i] - 1; + else + map = ffz(used_data_lanes); + + val |= map << (i * 2); + used_data_lanes |= BIT(map); + } + + if (phy->index == 0 && priv->info->phy0_lanes_0_1_on_second_phy) + val = ((val & 0xf) << 4) | ((val >> 4) & 0xf); + + ret = regmap_update_bits(priv->regmap, MAX9296A_MIPI_PHY3(index), + MAX9296A_MIPI_PHY3_PHY_LANE_MAP_4, + FIELD_PREP(MAX9296A_MIPI_PHY3_PHY_LANE_MAP_4, val)); + if (ret) + return ret; + + /* + * Configure lane polarity. + * + * PHY 0 and 1 are on register 0x335. + * PHY 2 and 3 are on register 0x336. + * + * Each PHY has 3 bits of polarity configuration. + * + * On MAX9296A, each bit represents the lane polarity of logical lanes. + * Each of these lanes can be mapped to any physical lane. + * 0th bit is for lane 0. + * 1st bit is for lane 1. + * 2nd bit is for clock lane. + * + * On MAX96714, each bit represents the lane polarity of physical lanes. + * 0th bit for physical lane 0. + * 1st bit for physical lane 1. + * 2nd bit for clock lane of PHY 0, the slave PHY, which is unused. + * + * 3rd bit for physical lane 2. + * 4th bit for physical lane 3. + * 5th bit for clock lane of PHY 1, the master PHY. + */ + + val = 0; + for (i = 0; i < num_data_lanes; i++) { + unsigned int map; + + if (!phy->mipi.lane_polarities[i + 1]) + continue; + + /* + * The numbers inside the data_lanes array specify the hardware + * lane each logical lane maps to. + * If polarity is set for the physical lanes, retrieve the + * physical lane matching the logical lane from data_lanes. + * Otherwise, when polarity is set for the logical lanes + * the index of the polarity can be used. + */ + + if (priv->info->polarity_on_physical_lanes) + map = phy->mipi.data_lanes[i]; + else + map = i; + + val |= BIT(map); + } + + if (phy->index == 0 && priv->info->phy0_lanes_0_1_on_second_phy) + val = ((val & 0x3) << 2) | ((val >> 2) & 0x3); + + ret = regmap_update_bits(priv->regmap, MAX9296A_MIPI_PHY5(index), + MAX9296A_MIPI_PHY5_PHY_POL_MAP_0_1 | + MAX9296A_MIPI_PHY5_PHY_POL_MAP_2_3, + FIELD_PREP(MAX9296A_MIPI_PHY5_PHY_POL_MAP_0_1, val) | + FIELD_PREP(MAX9296A_MIPI_PHY5_PHY_POL_MAP_2_3, val >> 2)); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_PHY5(index), + MAX9296A_MIPI_PHY5_PHY_POL_MAP_CLK(index), + phy->mipi.lane_polarities[0]); + if (ret) + return ret; + + /* Put DPLL block into reset. */ + ret = regmap_clear_bits(priv->regmap, MAX9296A_DPLL_0(index), + MAX9296A_DPLL_0_CONFIG_SOFT_RST_N); + if (ret) + return ret; + + /* Set DPLL frequency. */ + ret = regmap_update_bits(priv->regmap, MAX9296A_BACKTOP22(index), + MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL, + FIELD_PREP(MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL, + div_u64(dpll_freq, 100000000))); + if (ret) + return ret; + + /* Enable DPLL frequency. */ + ret = regmap_set_bits(priv->regmap, MAX9296A_BACKTOP22(index), + MAX9296A_BACKTOP22_PHY_CSI_TX_DPLL_EN); + if (ret) + return ret; + + /* Pull DPLL block out of reset. */ + ret = regmap_set_bits(priv->regmap, MAX9296A_DPLL_0(index), + MAX9296A_DPLL_0_CONFIG_SOFT_RST_N); + if (ret) + return ret; + + if (dpll_freq > 1500000000ull) { + /* Enable initial deskew with 2 x 32k UI. */ + ret = regmap_write(priv->regmap, MAX9296A_MIPI_TX3(hw_index), + MAX9296A_MIPI_TX3_DESKEW_INIT_AUTO | + MAX9296A_MIPI_TX3_DESKEW_INIT_8X32K); + if (ret) + return ret; + + /* Enable periodic deskew with 2 x 1k UI.. */ + ret = regmap_write(priv->regmap, MAX9296A_MIPI_TX4(hw_index), + MAX9296A_MIPI_TX4_DESKEW_PER_AUTO | + MAX9296A_MIPI_TX4_DESKEW_PER_2K); + if (ret) + return ret; + } else { + /* Disable initial deskew. */ + ret = regmap_write(priv->regmap, MAX9296A_MIPI_TX3(hw_index), 0x0); + if (ret) + return ret; + + /* Disable periodic deskew. */ + ret = regmap_write(priv->regmap, MAX9296A_MIPI_TX4(hw_index), 0x0); + if (ret) + return ret; + } + + return 0; +} + +static int max9296a_set_phy_mode(struct max_des *des, struct max_des_phy *phy, + struct max_des_phy_mode *mode) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = phy->index; + unsigned int phy_id = index == 0 ? 1 : 2; + int ret; + + /* Set alternate memory map modes. */ + ret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX51(phy_id), + MAX9296A_MIPI_TX51_ALT_MEM_MAP_12, + mode->alt_mem_map12); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX51(phy_id), + MAX9296A_MIPI_TX51_ALT_MEM_MAP_8, + mode->alt_mem_map8); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX51(phy_id), + MAX9296A_MIPI_TX51_ALT_MEM_MAP_10, + mode->alt_mem_map10); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX51(phy_id), + MAX9296A_MIPI_TX51_ALT2_MEM_MAP_8, + mode->alt2_mem_map8); + if (ret) + return ret; + + return 0; +} + +static int max9296a_set_phy_active(struct max_des *des, struct max_des_phy *phy, + bool enable) +{ + struct max9296a_priv *priv = des_to_priv(des); + + return regmap_assign_bits(priv->regmap, MAX9296A_MIPI_PHY2, + MAX9296A_MIPI_PHY2_PHY_STDBY_N(phy->index), enable); +} + +static int max9296a_set_pipe_remap(struct max_des *des, + struct max_des_pipe *pipe, + unsigned int i, + struct max_des_remap *remap) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + unsigned int phy_id = remap->phy == 0 ? 1 : 2; + int ret; + + /* Set source Data Type and Virtual Channel. */ + /* TODO: implement extended Virtual Channel. */ + ret = regmap_write(priv->regmap, MAX9296A_MIPI_TX13(index, i), + FIELD_PREP(MAX9296A_MIPI_TX13_MAP_SRC_DT, + remap->from_dt) | + FIELD_PREP(MAX9296A_MIPI_TX13_MAP_SRC_VC, + remap->from_vc)); + if (ret) + return ret; + + /* Set destination Data Type and Virtual Channel. */ + /* TODO: implement extended Virtual Channel. */ + ret = regmap_write(priv->regmap, MAX9296A_MIPI_TX14(index, i), + FIELD_PREP(MAX9296A_MIPI_TX14_MAP_DST_DT, + remap->to_dt) | + FIELD_PREP(MAX9296A_MIPI_TX14_MAP_DST_VC, + remap->to_vc)); + if (ret) + return ret; + + /* Set destination PHY. */ + return regmap_update_bits(priv->regmap, MAX9296A_MIPI_TX45(index, i), + MAX9296A_MIPI_TX45_MAP_DPHY_DEST(i), + field_prep(MAX9296A_MIPI_TX45_MAP_DPHY_DEST(i), + phy_id)); +} + +static int max9296a_set_pipe_remaps_enable(struct max_des *des, + struct max_des_pipe *pipe, + unsigned int mask) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + int ret; + + ret = regmap_write(priv->regmap, MAX9296A_MIPI_TX11(index), mask); + if (ret) + return ret; + + return regmap_write(priv->regmap, MAX9296A_MIPI_TX12(index), mask >> 8); +} + +static int max9296a_set_pipe_enable(struct max_des *des, struct max_des_pipe *pipe, + bool enable) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + + return regmap_assign_bits(priv->regmap, MAX9296A_REG2, + MAX9296A_REG2_VID_EN(index), enable); +} + +static int max96714_set_pipe_enable(struct max_des *des, struct max_des_pipe *pipe, + bool enable) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + + return regmap_assign_bits(priv->regmap, MAX9296A_VIDEO_PIPE_EN, + MAX9296A_VIDEO_PIPE_EN_MASK(index - 1), enable); +} + +static int max96714_set_pipe_tunnel_enable(struct max_des *des, + struct max_des_pipe *pipe, bool enable) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + + return regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX52(index), + MAX9296A_MIPI_TX52_TUN_EN, enable); +} + +static int max9296a_set_pipe_stream_id(struct max_des *des, struct max_des_pipe *pipe, + unsigned int stream_id) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + + return regmap_update_bits(priv->regmap, MAX9296A_RX50(index), MAX9296A_RX50_STR_SEL, + FIELD_PREP(MAX9296A_RX50_STR_SEL, pipe->stream_id)); +} + +static int max96714_set_pipe_stream_id(struct max_des *des, struct max_des_pipe *pipe, + unsigned int stream_id) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + + return regmap_update_bits(priv->regmap, MAX9296A_VIDEO_PIPE_SEL, + MAX9296A_VIDEO_PIPE_SEL_STREAM(index - 1), + field_prep(MAX9296A_VIDEO_PIPE_SEL_STREAM(index - 1), + stream_id)); +} + +static int max96716_set_pipe_phy(struct max_des *des, + struct max_des_pipe *pipe, + struct max_des_phy *phy) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + + return regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX52(index), + MAX9296A_MIPI_TX52_TUN_DEST, phy->index); +} + +static int max9296a_set_pipe_mode(struct max_des *des, + struct max_des_pipe *pipe, + struct max_des_pipe_mode *mode) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = max9296a_pipe_id(priv, pipe); + int ret; + + /* Set 8bit double mode. */ + ret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP21, + MAX9296A_BACKTOP21_BPP8DBL(index), mode->dbl8); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP24, + MAX9296A_BACKTOP24_BPP8DBL_MODE(index), + mode->dbl8mode); + if (ret) + return ret; + + /* Set 10bit double mode. */ + ret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP32, + MAX9296A_BACKTOP32_BPP10DBL(index), mode->dbl10); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP32, + MAX9296A_BACKTOP32_BPP10DBL_MODE(index), + mode->dbl10mode); + if (ret) + return ret; + + /* Set 12bit double mode. */ + /* TODO: check support for double mode on MAX96714. */ + return regmap_assign_bits(priv->regmap, MAX9296A_BACKTOP33, + MAX9296A_BACKTOP32_BPP12DBL(index), mode->dbl12); +} + +static int max9296a_reset_link(struct max9296a_priv *priv, unsigned int index) +{ + unsigned int reg, mask; + + if (index == 0) { + reg = MAX9296A_CTRL0; + mask = MAX9296A_CTRL0_RESET_ONESHOT; + } else { + reg = MAX9296A_CTRL2; + mask = MAX9296A_CTRL2_RESET_ONESHOT_B; + } + + return regmap_set_bits(priv->regmap, reg, mask); +} + +static int max9296a_init_link_rlms(struct max9296a_priv *priv, + struct max_des_link *link) +{ + unsigned int index = link->index; + int ret; + + /* + * These settings are described as required on datasheet page 53 + * for MAX96714. + */ + + ret = regmap_write(priv->regmap, MAX9296A_RLMS3E(index), 0xfd); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX9296A_RLMS3F(index), 0x3d); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX9296A_RLMS49(index), 0xf5); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX9296A_RLMS7E(index), 0xa8); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX9296A_RLMS7F(index), 0x68); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX9296A_RLMSA3(index), 0x30); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX9296A_RLMSA5(index), 0x70); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX9296A_RLMSD8(index), 0x07); + if (ret) + return ret; + + return max9296a_reset_link(priv, link->index); +} + +static int max9296a_init_link(struct max_des *des, struct max_des_link *link) +{ + struct max9296a_priv *priv = des_to_priv(des); + int ret; + + if (priv->info->adjust_rlms) { + ret = max9296a_init_link_rlms(priv, link); + if (ret) + return ret; + } + + return 0; +} + +static int max9296a_select_links(struct max_des *des, unsigned int mask) +{ + struct max9296a_priv *priv = des_to_priv(des); + int ret; + + if (priv->info->num_links == 1) + return 0; + + if (!mask) { + dev_err(priv->dev, "Disable all links unsupported\n"); + return -EINVAL; + } + + ret = regmap_update_bits(priv->regmap, MAX9296A_GMSL1_EN, + MAX9296A_GMSL1_EN_LINK_EN, + FIELD_PREP(MAX9296A_GMSL1_EN_LINK_EN, mask)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MAX9296A_CTRL0, + MAX9296A_CTRL0_LINK_CFG | + MAX9296A_CTRL0_RESET_ONESHOT, + FIELD_PREP(MAX9296A_CTRL0_LINK_CFG, mask) | + FIELD_PREP(MAX9296A_CTRL0_RESET_ONESHOT, 1)); + if (ret) + return ret; + + if (priv->info->has_per_link_reset) { + ret = max9296a_reset_link(priv, 1); + if (ret) + return ret; + } + + msleep(200); + + return 0; +} + +static int max96716_select_links(struct max_des *des, unsigned int mask) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int i; + int ret; + + for (i = 0; i < des->ops->num_links; i++) { + bool dis = !(mask & BIT(i)); + unsigned int reg, mask; + + if (i == 0) { + reg = MAX9296A_REG1; + mask = MAX9296A_REG1_DIS_REM_CC_A; + } else { + reg = MAX9296A_REG3; + mask = MAX9296A_REG3_DIS_REM_CC_B; + } + + ret = regmap_assign_bits(priv->regmap, reg, mask, dis); + if (ret) + return ret; + } + + return 0; +} + +static int max96792a_select_link_version(struct max_des *des, + struct max_des_link *link, + enum max_gmsl_version version) +{ + struct max9296a_priv *priv = des_to_priv(des); + unsigned int index = link->index; + bool en = version == MAX_GMSL_3; + unsigned int reg, mask, val; + int ret; + + if (index == 0) { + reg = MAX9296A_REG1; + mask = MAX9296A_REG1_RX_RATE_A; + } else { + reg = MAX9296A_REG4; + mask = MAX9296A_REG4_RX_RATE_B; + } + + val = en ? MAX9296A_REG1_RX_RATE_12Gbps + : MAX9296A_REG1_RX_RATE_6Gbps; + ret = regmap_update_bits(priv->regmap, reg, mask, val); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_MIPI_TX0(index), + MAX9296A_MIPI_TX0_RX_FEC_EN, en); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX9296A_REG6, + MAX9296A_REG6_GMSL2_X(index), !en); + if (ret) + return ret; + + return regmap_assign_bits(priv->regmap, MAX9296A_REG4, + MAX9296A_REG4_GMSL3_X(index), en); +} + +static const struct max_des_ops max9296a_ops = { + .num_remaps_per_pipe = 16, + .reg_read = max9296a_reg_read, + .reg_write = max9296a_reg_write, + .log_pipe_status = max9626a_log_pipe_status, + .log_phy_status = max9296a_log_phy_status, + .set_enable = max9296a_set_enable, + .init = max9296a_init, + .init_phy = max9296a_init_phy, + .set_phy_mode = max9296a_set_phy_mode, + .set_phy_active = max9296a_set_phy_active, + .set_pipe_remap = max9296a_set_pipe_remap, + .set_pipe_remaps_enable = max9296a_set_pipe_remaps_enable, + .set_pipe_mode = max9296a_set_pipe_mode, + .init_link = max9296a_init_link, +}; + +static int max9296a_probe(struct i2c_client *client) +{ + struct regmap_config i2c_regmap = max9296a_i2c_regmap; + struct device *dev = &client->dev; + struct max9296a_priv *priv; + struct max_des_ops *ops; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL); + if (!ops) + return -ENOMEM; + + priv->info = device_get_match_data(dev); + if (!priv->info) { + dev_err(dev, "Failed to get match data\n"); + return -ENODEV; + } + + priv->dev = dev; + priv->client = client; + i2c_set_clientdata(client, priv); + + i2c_regmap.max_register = priv->info->max_register; + priv->regmap = devm_regmap_init_i2c(client, &i2c_regmap); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "powerdown", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_pwdn)) + return PTR_ERR(priv->gpiod_pwdn); + + if (priv->gpiod_pwdn) { + /* PWDN must be held for 1us for reset */ + udelay(1); + + gpiod_set_value_cansleep(priv->gpiod_pwdn, 0); + /* Maximum power-up time (tLOCK) 4ms */ + usleep_range(4000, 5000); + } + + *ops = max9296a_ops; + + ops->versions = priv->info->versions; + ops->fix_tx_ids = priv->info->fix_tx_ids; + ops->num_phys = priv->info->num_phys; + ops->num_pipes = priv->info->num_pipes; + ops->num_links = priv->info->num_links; + ops->phys_configs = priv->info->phys_configs; + ops->set_pipe_enable = priv->info->set_pipe_enable; + ops->set_pipe_stream_id = priv->info->set_pipe_stream_id; + ops->set_pipe_phy = priv->info->set_pipe_phy; + ops->set_pipe_tunnel_enable = priv->info->set_pipe_tunnel_enable; + ops->select_links = priv->info->select_links; + ops->select_link_version = priv->info->select_link_version; + ops->select_resets_link = priv->info->select_resets_link; + priv->des.ops = ops; + + ret = max9296a_reset(priv); + if (ret) + return ret; + + return max_des_probe(client, &priv->des); +} + +static void max9296a_remove(struct i2c_client *client) +{ + struct max9296a_priv *priv = i2c_get_clientdata(client); + + max_des_remove(&priv->des); + + gpiod_set_value_cansleep(priv->gpiod_pwdn, 1); +} + +static const struct max_phys_config max9296a_phys_configs[] = { + { { 4, 4 } }, +}; + +static const struct max_phys_config max96714_phys_configs[] = { + { { 4 } }, +}; + +static const struct max9296a_chip_info max9296a_info = { + .max_register = 0x1f00, + .set_pipe_stream_id = max9296a_set_pipe_stream_id, + .set_pipe_enable = max9296a_set_pipe_enable, + .select_links = max9296a_select_links, + .select_resets_link = true, + .phys_configs = { + .num_configs = ARRAY_SIZE(max9296a_phys_configs), + .configs = max9296a_phys_configs, + }, + .phy0_lanes_0_1_on_second_phy = true, + .fix_tx_ids = true, + .num_pipes = 4, + .pipe_hw_ids = { 0, 1, 2, 3 }, + .num_phys = 2, + .phy_hw_ids = { 1, 2 }, + .num_links = 2, +}; + +static const struct max9296a_chip_info max96714_info = { + .max_register = 0x5011, + .set_pipe_stream_id = max96714_set_pipe_stream_id, + .set_pipe_enable = max96714_set_pipe_enable, + .set_pipe_tunnel_enable = max96714_set_pipe_tunnel_enable, + .phys_configs = { + .num_configs = ARRAY_SIZE(max96714_phys_configs), + .configs = max96714_phys_configs, + }, + .polarity_on_physical_lanes = true, + .supports_phy_log = true, + .adjust_rlms = true, + .num_pipes = 1, + .pipe_hw_ids = { 1 }, + .num_phys = 1, + .phy_hw_ids = { 1 }, + .num_links = 1, +}; + +static const struct max9296a_chip_info max96716a_info = { + .max_register = 0x52d6, + .set_pipe_stream_id = max96714_set_pipe_stream_id, + .set_pipe_enable = max96714_set_pipe_enable, + .set_pipe_phy = max96716_set_pipe_phy, + .set_pipe_tunnel_enable = max96714_set_pipe_tunnel_enable, + .select_links = max96716_select_links, + .phys_configs = { + .num_configs = ARRAY_SIZE(max9296a_phys_configs), + .configs = max9296a_phys_configs, + }, + .has_per_link_reset = true, + .phy0_lanes_0_1_on_second_phy = true, + .supports_cphy = true, + .supports_phy_log = true, + .num_pipes = 2, + .pipe_hw_ids = { 1, 2 }, + .num_phys = 2, + .phy_hw_ids = { 1, 2 }, + .num_links = 2, +}; + +static const struct max9296a_chip_info max96792a_info = { + .max_register = 0x52d6, + .versions = BIT(MAX_GMSL_2) | BIT(MAX_GMSL_3), + .set_pipe_stream_id = max96714_set_pipe_stream_id, + .set_pipe_phy = max96716_set_pipe_phy, + .set_pipe_enable = max96714_set_pipe_enable, + .set_pipe_tunnel_enable = max96714_set_pipe_tunnel_enable, + .select_links = max9296a_select_links, + .select_link_version = max96792a_select_link_version, + .select_resets_link = true, + .phys_configs = { + .num_configs = ARRAY_SIZE(max9296a_phys_configs), + .configs = max9296a_phys_configs, + }, + .has_per_link_reset = true, + .phy0_lanes_0_1_on_second_phy = true, + .supports_cphy = true, + .supports_phy_log = true, + .num_pipes = 2, + .pipe_hw_ids = { 1, 2 }, + .num_phys = 2, + .phy_hw_ids = { 1, 2 }, + .num_links = 2, +}; + +static const struct of_device_id max9296a_of_table[] = { + { .compatible = "maxim,max9296a", .data = &max9296a_info }, + { .compatible = "maxim,max96714", .data = &max96714_info }, + { .compatible = "maxim,max96714f", .data = &max96714_info }, + { .compatible = "maxim,max96716a", .data = &max96716a_info }, + { .compatible = "maxim,max96792a", .data = &max96792a_info }, + { }, +}; +MODULE_DEVICE_TABLE(of, max9296a_of_table); + +static struct i2c_driver max9296a_i2c_driver = { + .driver = { + .name = "max9296a", + .of_match_table = of_match_ptr(max9296a_of_table), + }, + .probe = max9296a_probe, + .remove = max9296a_remove, +}; + +module_i2c_driver(max9296a_i2c_driver); + +MODULE_DESCRIPTION("Maxim MAX9296A Quad GMSL2 Deserializer Driver"); +MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/maxim-serdes/max96717.c b/drivers/media/i2c/maxim-serdes/max96717.c new file mode 100644 index 000000000000..bf05a8055099 --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max96717.c @@ -0,0 +1,1500 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Maxim MAX96717 GMSL2 Serializer Driver + * + * Copyright (C) 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "max_ser.h" + +#define MAX96717_REG0 0x0 + +#define MAX96717_REG2 0x2 +#define MAX96717_REG2_VID_TX_EN_P(p) BIT(4 + (p)) + +#define MAX96717_REG3 0x3 +#define MAX96717_REG3_RCLKSEL GENMASK(1, 0) +#define MAX96717_REG3_RCLKSEL_REFERENCE_PLL 0b11 + +#define MAX96717_REG6 0x6 +#define MAX96717_REG6_RCLKEN BIT(5) + +#define MAX96717_I2C_2(x) (0x42 + (x) * 0x2) +#define MAX96717_I2C_2_SRC GENMASK(7, 1) + +#define MAX96717_I2C_3(x) (0x43 + (x) * 0x2) +#define MAX96717_I2C_3_DST GENMASK(7, 1) + +#define MAX96717_TX3(p) (0x53 + (p) * 0x4) +#define MAX96717_TX3_TX_STR_SEL GENMASK(1, 0) + +#define MAX96717_VIDEO_TX0(p) (0x100 + (p) * 0x8) +#define MAX96717_VIDEO_TX0_AUTO_BPP BIT(3) + +#define MAX96717_VIDEO_TX1(p) (0x101 + (p) * 0x8) +#define MAX96717_VIDEO_TX1_BPP GENMASK(5, 0) + +#define MAX96717_VIDEO_TX2(p) (0x102 + (p) * 0x8) +#define MAX96717_VIDEO_TX2_PCLKDET BIT(7) +#define MAX96717_VIDEO_TX2_DRIFT_DET_EN BIT(1) + +#define MAX96717_GPIO_A(x) (0x2be + (x) * 0x3) +#define MAX96717_GPIO_A_GPIO_OUT_DIS BIT(0) +#define MAX96717_GPIO_A_GPIO_TX_EN BIT(1) +#define MAX96717_GPIO_A_GPIO_RX_EN BIT(2) +#define MAX96717_GPIO_A_GPIO_IN BIT(3) +#define MAX96717_GPIO_A_GPIO_OUT BIT(4) +#define MAX96717_GPIO_A_TX_COMP_EN BIT(5) +#define MAX96717_GPIO_A_RES_CFG BIT(7) + +#define MAX96717_GPIO_B(x) (0x2bf + (x) * 0x3) +#define MAX96717_GPIO_B_GPIO_TX_ID GENMASK(4, 0) +#define MAX96717_GPIO_B_OUT_TYPE BIT(5) +#define MAX96717_GPIO_B_PULL_UPDN_SEL GENMASK(7, 6) +#define MAX96717_GPIO_B_PULL_UPDN_SEL_NONE 0b00 +#define MAX96717_GPIO_B_PULL_UPDN_SEL_PU 0b01 +#define MAX96717_GPIO_B_PULL_UPDN_SEL_PD 0b10 + +#define MAX96717_GPIO_C(x) (0x2c0 + (x) * 0x3) +#define MAX96717_GPIO_C_GPIO_RX_ID GENMASK(4, 0) + +#define MAX96717_CMU2 0x302 +#define MAX96717_CMU2_PFDDIV_RSHORT GENMASK(6, 4) +#define MAX96717_CMU2_PFDDIV_RSHORT_1_1V 0b001 + +#define MAX96717_FRONTTOP_0 0x308 +#define MAX96717_FRONTTOP_0_CLK_SEL_P(x) BIT(x) +#define MAX96717_FRONTTOP_0_START_PORT(x) BIT((x) + 4) + +#define MAX96717_FRONTTOP_1(p) (0x309 + (p) * 0x2) +#define MAX96717_FRONTTOP_2(p) (0x30a + (p) * 0x2) + +#define MAX96717_FRONTTOP_9 0x311 +#define MAX96717_FRONTTOP_9_START_PORT(p, x) BIT((p) + (x) * 4) + +#define MAX96717_FRONTTOP_10 0x312 +#define MAX96717_FRONTTOP_10_BPP8DBL(p) BIT(p) + +#define MAX96717_FRONTTOP_11 0x313 +#define MAX96717_FRONTTOP_11_BPP10DBL(p) BIT(p) +#define MAX96717_FRONTTOP_11_BPP12DBL(p) BIT((p) + 4) + +#define MAX96717_FRONTTOP_12(p, x) (0x314 + (p) * 0x2 + (x)) +#define MAX96717_MEM_DT_SEL GENMASK(5, 0) +#define MAX96717_MEM_DT_EN BIT(6) + +#define MAX96717_FRONTTOP_20(p) (0x31c + (p) * 0x1) +#define MAX96717_FRONTTOP_20_SOFT_BPP_EN BIT(5) +#define MAX96717_FRONTTOP_20_SOFT_BPP GENMASK(4, 0) + +#define MAX96717_MIPI_RX0 0x330 +#define MAX96717_MIPI_RX0_NONCONTCLK_EN BIT(6) + +#define MAX96717_MIPI_RX1 0x331 +#define MAX96717_MIPI_RX1_CTRL_NUM_LANES GENMASK(5, 4) + +#define MAX96717_MIPI_RX2 0x332 +#define MAX96717_MIPI_RX2_PHY1_LANE_MAP GENMASK(7, 4) + +#define MAX96717_MIPI_RX3 0x333 +#define MAX96717_MIPI_RX3_PHY2_LANE_MAP GENMASK(3, 0) + +#define MAX96717_MIPI_RX4 0x334 +#define MAX96717_MIPI_RX4_PHY1_POL_MAP GENMASK(5, 4) + +#define MAX96717_MIPI_RX5 0x335 +#define MAX96717_MIPI_RX5_PHY2_POL_MAP GENMASK(1, 0) +#define MAX96717_MIPI_RX5_PHY2_POL_MAP_CLK BIT(2) + +#define MAX96717_EXTA(x) (0x3dc + (x)) + +#define MAX96717_EXT11 0x383 +#define MAX96717_EXT11_TUN_MODE BIT(7) + +#define MAX96717_EXT21 0x38d +#define MAX96717_EXT22 0x38e +#define MAX96717_EXT23 0x38f +#define MAX96717_EXT24 0x390 + +#define MAX96717_REF_VTG0 0x3f0 +#define MAX96717_REF_VTG0_REFGEN_EN BIT(0) +#define MAX96717_REF_VTG0_REFGEN_RST BIT(1) +#define MAX96717_REF_VTG0_REFGEN_PREDEF_FREQ_ALT\ + BIT(3) +#define MAX96717_REF_VTG0_REFGEN_PREDEF_FREQ GENMASK(5, 4) +#define MAX96717_REF_VTG0_REFGEN_PREDEF_EN BIT(6) + +#define MAX96717_REF_VTG1 0x3f1 +#define MAX96717_REF_VTG1_PCLKEN BIT(0) +#define MAX96717_REF_VTG1_PCLK_GPIO GENMASK(5, 1) +#define MAX96717_REF_VTG1_RCLKEN_Y BIT(7) + +#define MAX96717_PIO_SLEW_0 0x56f +#define MAX96717_PIO_SLEW_0_PIO00_SLEW GENMASK(1, 0) +#define MAX96717_PIO_SLEW_0_PIO01_SLEW GENMASK(3, 2) +#define MAX96717_PIO_SLEW_0_PIO02_SLEW GENMASK(5, 4) + +#define MAX96717_PIO_SLEW_1 0x570 +#define MAX96717_PIO_SLEW_1_PIO05_SLEW GENMASK(3, 2) +#define MAX96717_PIO_SLEW_1_PIO06_SLEW GENMASK(5, 4) + +#define MAX96717_PIO_SLEW_2 0x571 +#define MAX96717_PIO_SLEW_2_PIO010_SLEW GENMASK(5, 4) +#define MAX96717_PIO_SLEW_2_PIO011_SLEW GENMASK(7, 6) + +#define MAX96717_PIO_SLEW_FASTEST 0b00 + +#define MAX96717_BIAS_PULL_STRENGTH_1000000_OHM 1000000U +#define MAX96717_BIAS_PULL_STRENGTH_40000_OHM 40000U + +#define MAX96717_DEFAULT_CLKOUT_RATE 24000000UL + +#define MAX96717_NAME "max96717" +#define MAX96717_PINCTRL_NAME MAX96717_NAME "-pinctrl" +#define MAX96717_GPIOCHIP_NAME MAX96717_NAME "-gpiochip" +#define MAX96717_GPIO_NUM 11 +#define MAX96717_PIPES_NUM 4 +#define MAX96717_PHYS_NUM 2 + +#define field_get(mask, val) (((val) & (mask)) >> __ffs(mask)) +#define field_prep(mask, val) (((val) << __ffs(mask)) & (mask)) + +struct max96717_priv { + struct max_ser ser; + struct pinctrl_desc pctldesc; + struct gpio_chip gc; + const struct max96717_chip_info *info; + + struct device *dev; + struct i2c_client *client; + struct regmap *regmap; + struct pinctrl_dev *pctldev; + + struct clk_hw clk_hw; + u8 pll_predef_index; +}; + +struct max96717_chip_info { + bool supports_3_data_lanes; + bool supports_tunnel_mode; + bool supports_noncontinuous_clock; + bool supports_pkt_cnt; + unsigned int num_pipes; + unsigned int num_dts_per_pipe; + unsigned int pipe_hw_ids[MAX96717_PIPES_NUM]; + unsigned int num_phys; + unsigned int phy_hw_ids[MAX96717_PHYS_NUM]; +}; + +#define ser_to_priv(_ser) \ + container_of(_ser, struct max96717_priv, ser) + +static inline struct max96717_priv *clk_hw_to_priv(struct clk_hw *hw) +{ + return container_of(hw, struct max96717_priv, clk_hw); +} + +static const struct regmap_config max96717_i2c_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = 0x1f00, +}; + +static int max96717_wait_for_device(struct max96717_priv *priv) +{ + unsigned int i; + int ret; + + for (i = 0; i < 10; i++) { + unsigned int val; + + ret = regmap_read(priv->regmap, MAX96717_REG0, &val); + if (!ret && val) + return 0; + + msleep(100); + + dev_err(priv->dev, "Retry %u waiting for serializer: %d\n", i, ret); + } + + return ret; +} + +#define MAX96717_PIN(n) \ + PINCTRL_PIN(n, "mfp" __stringify(n)) + +static const struct pinctrl_pin_desc max96717_pins[] = { + MAX96717_PIN(0), + MAX96717_PIN(1), + MAX96717_PIN(2), + MAX96717_PIN(3), + MAX96717_PIN(4), + MAX96717_PIN(5), + MAX96717_PIN(6), + MAX96717_PIN(7), + MAX96717_PIN(8), + MAX96717_PIN(9), + MAX96717_PIN(10), +}; + +#define MAX96717_GROUP_PINS(name, ...) \ + static const unsigned int name ## _pins[] = { __VA_ARGS__ } + +MAX96717_GROUP_PINS(mfp0, 0); +MAX96717_GROUP_PINS(mfp1, 1); +MAX96717_GROUP_PINS(mfp2, 2); +MAX96717_GROUP_PINS(mfp3, 3); +MAX96717_GROUP_PINS(mfp4, 4); +MAX96717_GROUP_PINS(mfp5, 5); +MAX96717_GROUP_PINS(mfp6, 6); +MAX96717_GROUP_PINS(mfp7, 7); +MAX96717_GROUP_PINS(mfp8, 8); +MAX96717_GROUP_PINS(mfp9, 9); +MAX96717_GROUP_PINS(mfp10, 10); + +#define MAX96717_GROUP(name) \ + PINCTRL_PINGROUP(__stringify(name), name ## _pins, ARRAY_SIZE(name ## _pins)) + +static const struct pingroup max96717_ctrl_groups[] = { + MAX96717_GROUP(mfp0), + MAX96717_GROUP(mfp1), + MAX96717_GROUP(mfp2), + MAX96717_GROUP(mfp3), + MAX96717_GROUP(mfp4), + MAX96717_GROUP(mfp5), + MAX96717_GROUP(mfp6), + MAX96717_GROUP(mfp7), + MAX96717_GROUP(mfp8), + MAX96717_GROUP(mfp9), + MAX96717_GROUP(mfp10), +}; + +#define MAX96717_FUNC_GROUPS(name, ...) \ + static const char * const name ## _groups[] = { __VA_ARGS__ } + +MAX96717_FUNC_GROUPS(gpio, "mfp0", "mfp1", "mfp2", "mfp3", "mfp4", "mfp5", + "mfp6", "mfp7", "mfp8", "mfp9", "mfp10"); +MAX96717_FUNC_GROUPS(rclkout, "mfp0", "mfp1", "mfp2", "mfp3", "mfp4", + "mfp7", "mfp8"); + +enum max96717_func { + max96717_func_gpio, + max96717_func_rclkout, +}; + +#define MAX96717_FUNC(name) \ + [max96717_func_ ## name] = \ + PINCTRL_PINFUNCTION(__stringify(name), name ## _groups, \ + ARRAY_SIZE(name ## _groups)) + +static const struct pinfunction max96717_functions[] = { + MAX96717_FUNC(gpio), + MAX96717_FUNC(rclkout), +}; + +#define MAX96717_PINCTRL_X(x) (PIN_CONFIG_END + (x)) +#define MAX96717_PINCTRL_PULL_STRENGTH_HIGH MAX96717_PINCTRL_X(1) +#define MAX96717_PINCTRL_JITTER_COMPENSATION_EN MAX96717_PINCTRL_X(2) +#define MAX96717_PINCTRL_GMSL_TX_EN MAX96717_PINCTRL_X(3) +#define MAX96717_PINCTRL_GMSL_RX_EN MAX96717_PINCTRL_X(4) +#define MAX96717_PINCTRL_GMSL_TX_ID MAX96717_PINCTRL_X(5) +#define MAX96717_PINCTRL_GMSL_RX_ID MAX96717_PINCTRL_X(6) +#define MAX96717_PINCTRL_RCLKOUT_CLK MAX96717_PINCTRL_X(7) +#define MAX96717_PINCTRL_INPUT_VALUE MAX96717_PINCTRL_X(8) + +static const struct pinconf_generic_params max96717_cfg_params[] = { + { "maxim,jitter-compensation", MAX96717_PINCTRL_JITTER_COMPENSATION_EN, 0 }, + { "maxim,gmsl-tx", MAX96717_PINCTRL_GMSL_TX_EN, 0 }, + { "maxim,gmsl-rx", MAX96717_PINCTRL_GMSL_RX_EN, 0 }, + { "maxim,gmsl-tx-id", MAX96717_PINCTRL_GMSL_TX_ID, 0 }, + { "maxim,gmsl-rx-id", MAX96717_PINCTRL_GMSL_RX_ID, 0 }, + { "maxim,rclkout-clock", MAX96717_PINCTRL_RCLKOUT_CLK, 0 }, +}; + +static int max96717_ctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(max96717_ctrl_groups); +} + +static const char *max96717_ctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return max96717_ctrl_groups[selector].name; +} + +static int max96717_ctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + *pins = (unsigned int *)max96717_ctrl_groups[selector].pins; + *num_pins = max96717_ctrl_groups[selector].npins; + + return 0; +} + +static int max96717_get_pin_config_reg(unsigned int offset, u32 param, + unsigned int *reg, unsigned int *mask, + unsigned int *val) +{ + *reg = MAX96717_GPIO_A(offset); + + switch (param) { + case PIN_CONFIG_OUTPUT_ENABLE: + *mask = MAX96717_GPIO_A_GPIO_OUT_DIS; + *val = 0b0; + return 0; + case PIN_CONFIG_INPUT_ENABLE: + *mask = MAX96717_GPIO_A_GPIO_OUT_DIS; + *val = 0b1; + return 0; + case MAX96717_PINCTRL_GMSL_TX_EN: + *mask = MAX96717_GPIO_A_GPIO_TX_EN; + *val = 0b1; + return 0; + case MAX96717_PINCTRL_GMSL_RX_EN: + *mask = MAX96717_GPIO_A_GPIO_RX_EN; + *val = 0b1; + return 0; + case MAX96717_PINCTRL_INPUT_VALUE: + *mask = MAX96717_GPIO_A_GPIO_IN; + *val = 0b1; + return 0; + case PIN_CONFIG_OUTPUT: + *mask = MAX96717_GPIO_A_GPIO_OUT; + *val = 0b1; + return 0; + case MAX96717_PINCTRL_JITTER_COMPENSATION_EN: + *mask = MAX96717_GPIO_A_TX_COMP_EN; + *val = 0b1; + return 0; + case MAX96717_PINCTRL_PULL_STRENGTH_HIGH: + *mask = MAX96717_GPIO_A_RES_CFG; + *val = 0b1; + return 0; + } + + *reg = MAX96717_GPIO_B(offset); + + switch (param) { + case MAX96717_PINCTRL_GMSL_TX_ID: + *mask = MAX96717_GPIO_B_GPIO_TX_ID; + return 0; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + *mask = MAX96717_GPIO_B_OUT_TYPE; + *val = 0b0; + return 0; + case PIN_CONFIG_DRIVE_PUSH_PULL: + *mask = MAX96717_GPIO_B_OUT_TYPE; + *val = 0b1; + return 0; + case PIN_CONFIG_BIAS_DISABLE: + *mask = MAX96717_GPIO_B_PULL_UPDN_SEL; + *val = MAX96717_GPIO_B_PULL_UPDN_SEL_NONE; + return 0; + case PIN_CONFIG_BIAS_PULL_DOWN: + *mask = MAX96717_GPIO_B_PULL_UPDN_SEL; + *val = MAX96717_GPIO_B_PULL_UPDN_SEL_PD; + return 0; + case PIN_CONFIG_BIAS_PULL_UP: + *mask = MAX96717_GPIO_B_PULL_UPDN_SEL; + *val = MAX96717_GPIO_B_PULL_UPDN_SEL_PU; + return 0; + } + + switch (param) { + case PIN_CONFIG_SLEW_RATE: + if (offset < 3) { + *reg = MAX96717_PIO_SLEW_0; + if (offset == 0) + *mask = MAX96717_PIO_SLEW_0_PIO00_SLEW; + else if (offset == 1) + *mask = MAX96717_PIO_SLEW_0_PIO01_SLEW; + else + *mask = MAX96717_PIO_SLEW_0_PIO02_SLEW; + } else if (offset < 5) { + *reg = MAX96717_PIO_SLEW_1; + if (offset == 3) + *mask = MAX96717_PIO_SLEW_1_PIO05_SLEW; + else + *mask = MAX96717_PIO_SLEW_1_PIO06_SLEW; + } else if (offset < 7) { + return -EINVAL; + } else if (offset < 9) { + *reg = MAX96717_PIO_SLEW_2; + if (offset == 7) + *mask = MAX96717_PIO_SLEW_2_PIO010_SLEW; + else + *mask = MAX96717_PIO_SLEW_2_PIO011_SLEW; + } else { + return -EINVAL; + } + return 0; + case MAX96717_PINCTRL_GMSL_RX_ID: + *reg = MAX96717_GPIO_C(offset); + *mask = MAX96717_GPIO_C_GPIO_RX_ID; + return 0; + case MAX96717_PINCTRL_RCLKOUT_CLK: + if (offset != 2 && offset != 4) + return -EINVAL; + + *reg = MAX96717_REG3; + *mask = MAX96717_REG3_RCLKSEL; + return 0; + default: + return -ENOTSUPP; + } +} + +static int max96717_conf_pin_config_get(struct pinctrl_dev *pctldev, + unsigned int offset, + unsigned long *config) +{ + struct max96717_priv *priv = pinctrl_dev_get_drvdata(pctldev); + u32 param = pinconf_to_config_param(*config); + unsigned int reg, mask, val, en_val; + int ret; + + ret = max96717_get_pin_config_reg(offset, param, ®, &mask, &en_val); + if (ret) + return ret; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + case PIN_CONFIG_DRIVE_PUSH_PULL: + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + case MAX96717_PINCTRL_JITTER_COMPENSATION_EN: + case MAX96717_PINCTRL_GMSL_TX_EN: + case MAX96717_PINCTRL_GMSL_RX_EN: + case PIN_CONFIG_OUTPUT_ENABLE: + case PIN_CONFIG_INPUT_ENABLE: + ret = regmap_read(priv->regmap, reg, &val); + if (ret) + return ret; + + val = field_get(mask, val) == en_val; + if (!val) + return -EINVAL; + + break; + case MAX96717_PINCTRL_PULL_STRENGTH_HIGH: + case MAX96717_PINCTRL_INPUT_VALUE: + case PIN_CONFIG_OUTPUT: + ret = regmap_read(priv->regmap, reg, &val); + if (ret) + return ret; + + val = field_get(mask, val) == en_val; + break; + case MAX96717_PINCTRL_GMSL_TX_ID: + case MAX96717_PINCTRL_GMSL_RX_ID: + case MAX96717_PINCTRL_RCLKOUT_CLK: + case PIN_CONFIG_SLEW_RATE: + ret = regmap_read(priv->regmap, reg, &val); + if (ret) + return ret; + + val = field_get(mask, val); + break; + default: + return -ENOTSUPP; + } + + switch (param) { + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + *config = pinconf_to_config_packed(MAX96717_PINCTRL_PULL_STRENGTH_HIGH, 0); + + ret = max96717_conf_pin_config_get(pctldev, offset, config); + if (ret) + return ret; + + val = pinconf_to_config_argument(*config); + if (val) + val = MAX96717_BIAS_PULL_STRENGTH_1000000_OHM; + else + val = MAX96717_BIAS_PULL_STRENGTH_40000_OHM; + + break; + default: + break; + } + + *config = pinconf_to_config_packed(param, val); + + return 0; +} + +static int max96717_conf_pin_config_set_one(struct max96717_priv *priv, + unsigned int offset, + unsigned long config) +{ + u32 param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); + unsigned int reg, mask, val, en_val; + int ret; + + ret = max96717_get_pin_config_reg(offset, param, ®, &mask, &en_val); + if (ret) + return ret; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + case PIN_CONFIG_DRIVE_PUSH_PULL: + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + val = field_prep(mask, en_val); + + ret = regmap_update_bits(priv->regmap, reg, mask, val); + break; + case MAX96717_PINCTRL_JITTER_COMPENSATION_EN: + case MAX96717_PINCTRL_PULL_STRENGTH_HIGH: + case MAX96717_PINCTRL_GMSL_TX_EN: + case MAX96717_PINCTRL_GMSL_RX_EN: + case PIN_CONFIG_OUTPUT_ENABLE: + case PIN_CONFIG_INPUT_ENABLE: + case PIN_CONFIG_OUTPUT: + val = field_prep(mask, arg ? en_val : ~en_val); + + ret = regmap_update_bits(priv->regmap, reg, mask, val); + break; + case MAX96717_PINCTRL_GMSL_TX_ID: + case MAX96717_PINCTRL_GMSL_RX_ID: + case MAX96717_PINCTRL_RCLKOUT_CLK: + case PIN_CONFIG_SLEW_RATE: + val = field_prep(mask, arg); + + ret = regmap_update_bits(priv->regmap, reg, mask, val); + break; + default: + return -ENOTSUPP; + } + + if (ret) + return ret; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + arg = arg >= MAX96717_BIAS_PULL_STRENGTH_1000000_OHM; + config = pinconf_to_config_packed(MAX96717_PINCTRL_PULL_STRENGTH_HIGH, arg); + return max96717_conf_pin_config_set_one(priv, offset, config); + case PIN_CONFIG_OUTPUT: + config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT_ENABLE, 1); + return max96717_conf_pin_config_set_one(priv, offset, config); + case PIN_CONFIG_OUTPUT_ENABLE: + config = pinconf_to_config_packed(MAX96717_PINCTRL_GMSL_RX_EN, 0); + return max96717_conf_pin_config_set_one(priv, offset, config); + default: + break; + } + + return 0; +} + +static int max96717_conf_pin_config_set(struct pinctrl_dev *pctldev, + unsigned int offset, + unsigned long *configs, + unsigned int num_configs) +{ + struct max96717_priv *priv = pinctrl_dev_get_drvdata(pctldev); + int ret; + + while (num_configs--) { + unsigned long config = *configs; + + ret = max96717_conf_pin_config_set_one(priv, offset, config); + if (ret) + return ret; + + configs++; + } + + return 0; +} + +static int max96717_mux_get_functions_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(max96717_functions); +} + +static const char *max96717_mux_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return max96717_functions[selector].name; +} + +static int max96717_mux_get_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + *groups = max96717_functions[selector].groups; + *num_groups = max96717_functions[selector].ngroups; + + return 0; +} + +static int max96717_mux_set_rclkout(struct max96717_priv *priv, unsigned int group) +{ + int ret; + + /* Enable PCLK output. */ + ret = regmap_set_bits(priv->regmap, MAX96717_REF_VTG1, + MAX96717_REF_VTG1_PCLKEN); + if (ret) + return ret; + + /* Set PCLK output to the RCLK pin. */ + ret = regmap_update_bits(priv->regmap, MAX96717_REF_VTG1, + MAX96717_REF_VTG1_PCLK_GPIO, + FIELD_PREP(MAX96717_REF_VTG1_PCLK_GPIO, group)); + if (ret) + return ret; + + /* Enable RCLK output on PCLK. */ + ret = regmap_set_bits(priv->regmap, MAX96717_REF_VTG1, + MAX96717_REF_VTG1_RCLKEN_Y); + if (ret) + return ret; + + return 0; +} + +static int max96717_mux_set(struct pinctrl_dev *pctldev, unsigned int selector, + unsigned int group) +{ + struct max96717_priv *priv = pinctrl_dev_get_drvdata(pctldev); + + switch (selector) { + case max96717_func_rclkout: + return max96717_mux_set_rclkout(priv, group); + } + + return 0; +} + +static int max96717_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT_ENABLE, 0); + struct max96717_priv *priv = gpiochip_get_data(gc); + int ret; + + ret = max96717_conf_pin_config_get(priv->pctldev, offset, &config); + if (ret) + return ret; + + return pinconf_to_config_argument(config) ? GPIO_LINE_DIRECTION_OUT + : GPIO_LINE_DIRECTION_IN; +} + +static int max96717_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long config = pinconf_to_config_packed(PIN_CONFIG_INPUT_ENABLE, 1); + struct max96717_priv *priv = gpiochip_get_data(gc); + + return max96717_conf_pin_config_set_one(priv, offset, config); +} + +static int max96717_gpio_direction_output(struct gpio_chip *gc, unsigned int offset, + int value) +{ + unsigned long config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value); + struct max96717_priv *priv = gpiochip_get_data(gc); + + return max96717_conf_pin_config_set_one(priv, offset, config); +} + +static int max96717_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + unsigned long config = pinconf_to_config_packed(MAX96717_PINCTRL_INPUT_VALUE, 0); + struct max96717_priv *priv = gpiochip_get_data(gc); + int ret; + + ret = max96717_conf_pin_config_get(priv->pctldev, offset, &config); + if (ret) + return ret; + + return pinconf_to_config_argument(config); +} + +static void max96717_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) +{ + unsigned long config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT, value); + struct max96717_priv *priv = gpiochip_get_data(gc); + int ret; + + ret = max96717_conf_pin_config_set_one(priv, offset, config); + if (ret) + dev_err(priv->dev, "Failed to set GPIO %u output value, err: %d\n", + offset, ret); +} + +static unsigned int max96717_pipe_id(struct max96717_priv *priv, + struct max_ser_pipe *pipe) +{ + return priv->info->pipe_hw_ids[pipe->index]; +} + +static unsigned int max96717_phy_id(struct max96717_priv *priv, + struct max_ser_phy *phy) +{ + return priv->info->phy_hw_ids[phy->index]; +} + +static int max96717_set_pipe_enable(struct max_ser *ser, + struct max_ser_pipe *pipe, bool enable) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + unsigned int mask = MAX96717_REG2_VID_TX_EN_P(index); + + return regmap_assign_bits(priv->regmap, MAX96717_REG2, mask, enable); +} + +static int max96717_reg_read(struct max_ser *ser, unsigned int reg, + unsigned int *val) +{ + struct max96717_priv *priv = ser_to_priv(ser); + + return regmap_read(priv->regmap, reg, val); +} + +static int max96717_reg_write(struct max_ser *ser, unsigned int reg, + unsigned int val) +{ + struct max96717_priv *priv = ser_to_priv(ser); + + return regmap_write(priv->regmap, reg, val); +} + +static int max96717_set_pipe_dt_en(struct max_ser *ser, struct max_ser_pipe *pipe, + unsigned int i, bool enable) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + unsigned int reg; + + if (i < 2) + reg = MAX96717_FRONTTOP_12(index, i); + else + /* + * DT 7 and 8 are only supported on MAX96717, no need for pipe + * index to be taken into account. + */ + reg = MAX96717_EXTA(i - 2); + + return regmap_assign_bits(priv->regmap, reg, MAX96717_MEM_DT_EN, enable); +} + +static int max96717_set_pipe_dt(struct max_ser *ser, struct max_ser_pipe *pipe, + unsigned int i, unsigned int dt) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + unsigned int reg; + + if (i < 2) + reg = MAX96717_FRONTTOP_12(index, i); + else + reg = MAX96717_EXTA(i - 2); + + return regmap_update_bits(priv->regmap, reg, MAX96717_MEM_DT_SEL, + FIELD_PREP(MAX96717_MEM_DT_SEL, dt)); +} + +static int max96717_set_pipe_vcs(struct max_ser *ser, + struct max_ser_pipe *pipe, + unsigned int vcs) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + int ret; + + ret = regmap_write(priv->regmap, MAX96717_FRONTTOP_1(index), + (vcs >> 0) & 0xff); + if (ret) + return ret; + + return regmap_write(priv->regmap, MAX96717_FRONTTOP_2(index), + (vcs >> 8) & 0xff); +} + +static int max96717_log_status(struct max_ser *ser, const char *name) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int val; + int ret; + + if (!priv->info->supports_tunnel_mode) + return 0; + + ret = regmap_read(priv->regmap, MAX96717_EXT23, &val); + if (ret) + return ret; + + pr_info("%s: tun_pkt_cnt: %u\n", name, val); + + return 0; +} + +static int max96717_log_pipe_status(struct max_ser *ser, + struct max_ser_pipe *pipe, + const char *name) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + unsigned int val; + int ret; + + ret = regmap_read(priv->regmap, MAX96717_VIDEO_TX2(index), &val); + if (ret) + return ret; + + pr_info("%s: \tpclkdet: %u\n", name, !!(val & MAX96717_VIDEO_TX2_PCLKDET)); + + return 0; +} + +static int max96717_log_phy_status(struct max_ser *ser, + struct max_ser_phy *phy, + const char *name) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int val; + int ret; + + if (!priv->info->supports_pkt_cnt) + return 0; + + ret = regmap_read(priv->regmap, MAX96717_EXT21, &val); + if (ret) + return ret; + + pr_info("%s: \tphy_pkt_cnt: %u\n", name, val); + + ret = regmap_read(priv->regmap, MAX96717_EXT22, &val); + if (ret) + return ret; + + pr_info("%s: \tcsi_pkt_cnt: %u\n", name, val); + + ret = regmap_read(priv->regmap, MAX96717_EXT24, &val); + if (ret) + return ret; + + pr_info("%s: \tphy_clk_cnt: %u\n", name, val); + + return 0; +} + +static int max96717_init_phy(struct max_ser *ser, + struct max_ser_phy *phy) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int num_data_lanes = phy->mipi.num_data_lanes; + unsigned int used_data_lanes = 0; + unsigned int val; + unsigned int i; + int ret; + + if (num_data_lanes == 3 && !priv->info->supports_3_data_lanes) { + dev_err(priv->dev, "Unsupported 3 data lane mode\n"); + return -EINVAL; + } + + /* Configure a lane count. */ + ret = regmap_update_bits(priv->regmap, MAX96717_MIPI_RX1, + MAX96717_MIPI_RX1_CTRL_NUM_LANES, + FIELD_PREP(MAX96717_MIPI_RX1_CTRL_NUM_LANES, + num_data_lanes - 1)); + if (ret) + return ret; + + /* Configure lane mapping. */ + val = 0; + for (i = 0; i < 4; i++) { + unsigned int map; + + if (i < num_data_lanes) + map = phy->mipi.data_lanes[i] - 1; + else + map = ffz(used_data_lanes); + + val |= map << (i * 2); + used_data_lanes |= BIT(map); + } + + ret = regmap_update_bits(priv->regmap, MAX96717_MIPI_RX3, + MAX96717_MIPI_RX3_PHY2_LANE_MAP, + FIELD_PREP(MAX96717_MIPI_RX3_PHY2_LANE_MAP, val)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MAX96717_MIPI_RX2, + MAX96717_MIPI_RX2_PHY1_LANE_MAP, + FIELD_PREP(MAX96717_MIPI_RX2_PHY1_LANE_MAP, val >> 4)); + if (ret) + return ret; + + /* Configure lane polarity. */ + val = 0; + for (i = 0; i < num_data_lanes; i++) + if (phy->mipi.lane_polarities[i + 1]) + val |= BIT(i); + + ret = regmap_update_bits(priv->regmap, MAX96717_MIPI_RX5, + MAX96717_MIPI_RX5_PHY2_POL_MAP, + FIELD_PREP(MAX96717_MIPI_RX5_PHY2_POL_MAP, val)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MAX96717_MIPI_RX4, + MAX96717_MIPI_RX4_PHY1_POL_MAP, + FIELD_PREP(MAX96717_MIPI_RX4_PHY1_POL_MAP, val >> 2)); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_MIPI_RX5, + MAX96717_MIPI_RX5_PHY2_POL_MAP_CLK, + phy->mipi.lane_polarities[0]); + if (ret) + return ret; + + if (priv->info->supports_noncontinuous_clock) { + ret = regmap_assign_bits(priv->regmap, MAX96717_MIPI_RX0, + MAX96717_MIPI_RX0_NONCONTCLK_EN, + phy->mipi.flags & + V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK); + if (ret) + return ret; + } + + return 0; +} + +static int max96717_set_phy_active(struct max_ser *ser, struct max_ser_phy *phy, + bool enable) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_phy_id(priv, phy); + + return regmap_assign_bits(priv->regmap, MAX96717_FRONTTOP_0, + MAX96717_FRONTTOP_0_START_PORT(index), enable); +} + +static int max96717_set_pipe_stream_id(struct max_ser *ser, + struct max_ser_pipe *pipe, + unsigned int stream_id) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + + return regmap_update_bits(priv->regmap, MAX96717_TX3(index), + MAX96717_TX3_TX_STR_SEL, + FIELD_PREP(MAX96717_TX3_TX_STR_SEL, stream_id)); +} + +static int max96717_set_pipe_phy(struct max_ser *ser, struct max_ser_pipe *pipe, + struct max_ser_phy *phy) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + unsigned int phy_id = max96717_phy_id(priv, phy); + int ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_FRONTTOP_0, + MAX96717_FRONTTOP_0_CLK_SEL_P(index), + phy_id == 1); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_FRONTTOP_9, + MAX96717_FRONTTOP_9_START_PORT(index, 0), + phy_id == 0); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_FRONTTOP_9, + MAX96717_FRONTTOP_9_START_PORT(index, 1), + phy_id == 1); + if (ret) + return ret; + + return 0; +} + +static int max96717_set_pipe_mode(struct max_ser *ser, + struct max_ser_pipe *pipe, + struct max_ser_pipe_mode *mode) +{ + struct max96717_priv *priv = ser_to_priv(ser); + unsigned int index = max96717_pipe_id(priv, pipe); + int ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_VIDEO_TX0(index), + MAX96717_VIDEO_TX0_AUTO_BPP, !mode->bpp); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MAX96717_VIDEO_TX1(index), + MAX96717_VIDEO_TX1_BPP, + FIELD_PREP(MAX96717_VIDEO_TX1_BPP, mode->bpp)); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_VIDEO_TX2(index), + MAX96717_VIDEO_TX2_DRIFT_DET_EN, !mode->bpp); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_FRONTTOP_10, + MAX96717_FRONTTOP_10_BPP8DBL(index), + mode->dbl8); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_FRONTTOP_11, + MAX96717_FRONTTOP_11_BPP10DBL(index), + mode->dbl10); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96717_FRONTTOP_11, + MAX96717_FRONTTOP_11_BPP12DBL(index), + mode->dbl12); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MAX96717_FRONTTOP_20(index), + MAX96717_FRONTTOP_20_SOFT_BPP | + MAX96717_FRONTTOP_20_SOFT_BPP_EN, + FIELD_PREP(MAX96717_FRONTTOP_20_SOFT_BPP, + mode->soft_bpp) | + FIELD_PREP(MAX96717_FRONTTOP_20_SOFT_BPP_EN, + !!mode->soft_bpp)); + if (ret) + return ret; + + return 0; +} + +static int max96717_set_i2c_xlate(struct max_ser *ser, unsigned int i, + struct max_i2c_xlate *xlate) +{ + struct max96717_priv *priv = ser_to_priv(ser); + int ret; + + ret = regmap_update_bits(priv->regmap, MAX96717_I2C_2(i), + MAX96717_I2C_2_SRC, + FIELD_PREP(MAX96717_I2C_2_SRC, xlate->src)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MAX96717_I2C_3(i), + MAX96717_I2C_3_DST, + FIELD_PREP(MAX96717_I2C_3_DST, xlate->dst)); + if (ret) + return ret; + + return 0; +} + +static int max96717_set_tunnel_enable(struct max_ser *ser, bool enable) +{ + struct max96717_priv *priv = ser_to_priv(ser); + + return regmap_assign_bits(priv->regmap, MAX96717_EXT11, + MAX96717_EXT11_TUN_MODE, enable); +} + +static const struct max_phys_config max96717_phys_configs[] = { + { { 4 } }, +}; + +static int max96717_init(struct max_ser *ser) +{ + struct max96717_priv *priv = ser_to_priv(ser); + int ret; + + /* + * Set CMU2 PFDDIV to 1.1V for correct functionality of the device, + * as mentioned in the datasheet, under section MANDATORY REGISTER PROGRAMMING. + */ + ret = regmap_update_bits(priv->regmap, MAX96717_CMU2, + MAX96717_CMU2_PFDDIV_RSHORT, + FIELD_PREP(MAX96717_CMU2_PFDDIV_RSHORT, + MAX96717_CMU2_PFDDIV_RSHORT_1_1V)); + if (ret) + return ret; + + if (ser->ops->set_tunnel_enable) { + ret = ser->ops->set_tunnel_enable(ser, false); + if (ret) + return ret; + } + + return 0; +} + +static const struct pinctrl_ops max96717_ctrl_ops = { + .get_groups_count = max96717_ctrl_get_groups_count, + .get_group_name = max96717_ctrl_get_group_name, + .get_group_pins = max96717_ctrl_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static const struct pinconf_ops max96717_conf_ops = { + .pin_config_get = max96717_conf_pin_config_get, + .pin_config_set = max96717_conf_pin_config_set, + .is_generic = true, +}; + +static const struct pinmux_ops max96717_mux_ops = { + .get_functions_count = max96717_mux_get_functions_count, + .get_function_name = max96717_mux_get_function_name, + .get_function_groups = max96717_mux_get_groups, + .set_mux = max96717_mux_set, +}; + +static const struct max_ser_ops max96717_ops = { + .num_i2c_xlates = 2, + .phys_configs = { + .num_configs = ARRAY_SIZE(max96717_phys_configs), + .configs = max96717_phys_configs, + }, + .reg_read = max96717_reg_read, + .reg_write = max96717_reg_write, + .log_status = max96717_log_status, + .log_pipe_status = max96717_log_pipe_status, + .log_phy_status = max96717_log_phy_status, + .init = max96717_init, + .set_i2c_xlate = max96717_set_i2c_xlate, + .init_phy = max96717_init_phy, + .set_phy_active = max96717_set_phy_active, + .set_pipe_enable = max96717_set_pipe_enable, + .set_pipe_dt = max96717_set_pipe_dt, + .set_pipe_dt_en = max96717_set_pipe_dt_en, + .set_pipe_vcs = max96717_set_pipe_vcs, + .set_pipe_mode = max96717_set_pipe_mode, + .set_pipe_stream_id = max96717_set_pipe_stream_id, + .set_pipe_phy = max96717_set_pipe_phy, +}; + +struct max96717_pll_predef_freq { + unsigned long freq; + bool is_alt; + u8 val; +}; + +static const struct max96717_pll_predef_freq max96717_predef_freqs[] = { + { 13500000, true, 0 }, { 19200000, false, 0 }, + { 24000000, true, 1 }, { 27000000, false, 1 }, + { 37125000, false, 2 }, { 74250000, false, 3 }, +}; + +static unsigned long +max96717_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct max96717_priv *priv = clk_hw_to_priv(hw); + + return max96717_predef_freqs[priv->pll_predef_index].freq; +} + +static unsigned int max96717_clk_find_best_index(struct max96717_priv *priv, + unsigned long rate) +{ + unsigned int i, idx = 0; + unsigned long diff_new, diff_old = U32_MAX; + + for (i = 0; i < ARRAY_SIZE(max96717_predef_freqs); i++) { + diff_new = abs(rate - max96717_predef_freqs[i].freq); + if (diff_new < diff_old) { + diff_old = diff_new; + idx = i; + } + } + + return idx; +} + +static long max96717_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct max96717_priv *priv = clk_hw_to_priv(hw); + struct device *dev = &priv->client->dev; + unsigned int idx; + + idx = max96717_clk_find_best_index(priv, rate); + + if (rate != max96717_predef_freqs[idx].freq) { + dev_warn(dev, "Request CLK freq:%lu, found CLK freq:%lu\n", + rate, max96717_predef_freqs[idx].freq); + } + + return max96717_predef_freqs[idx].freq; +} + +static int max96717_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct max96717_priv *priv = clk_hw_to_priv(hw); + unsigned int val, idx; + int ret = 0; + + idx = max96717_clk_find_best_index(priv, rate); + + val = FIELD_PREP(MAX96717_REF_VTG0_REFGEN_PREDEF_FREQ, + max96717_predef_freqs[idx].val); + + if (max96717_predef_freqs[idx].is_alt) + val |= MAX96717_REF_VTG0_REFGEN_PREDEF_FREQ_ALT; + + val |= MAX96717_REF_VTG0_REFGEN_RST | MAX96717_REF_VTG0_REFGEN_EN; + + ret = regmap_write(priv->regmap, MAX96717_REF_VTG0, val); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, MAX96717_REF_VTG0, + MAX96717_REF_VTG0_REFGEN_RST); + if (ret) + return ret; + + priv->pll_predef_index = idx; + + return 0; +} + +static int max96717_clk_prepare(struct clk_hw *hw) +{ + struct max96717_priv *priv = clk_hw_to_priv(hw); + + return regmap_set_bits(priv->regmap, MAX96717_REG6, MAX96717_REG6_RCLKEN); +} + +static void max96717_clk_unprepare(struct clk_hw *hw) +{ + struct max96717_priv *priv = clk_hw_to_priv(hw); + + regmap_clear_bits(priv->regmap, MAX96717_REG6, MAX96717_REG6_RCLKEN); +} + +static const struct clk_ops max96717_clk_ops = { + .prepare = max96717_clk_prepare, + .unprepare = max96717_clk_unprepare, + .set_rate = max96717_clk_set_rate, + .recalc_rate = max96717_clk_recalc_rate, + .round_rate = max96717_clk_round_rate, +}; + +static int max96717_register_clkout(struct max96717_priv *priv) +{ + struct device *dev = &priv->client->dev; + struct clk_init_data init = { .ops = &max96717_clk_ops }; + unsigned long config; + int ret; + + config = pinconf_to_config_packed(MAX96717_PINCTRL_RCLKOUT_CLK, + MAX96717_REG3_RCLKSEL_REFERENCE_PLL); + ret = max96717_conf_pin_config_set_one(priv, 4, config); + if (ret) + return ret; + + config = pinconf_to_config_packed(PIN_CONFIG_SLEW_RATE, + MAX96717_PIO_SLEW_FASTEST); + ret = max96717_conf_pin_config_set_one(priv, 4, config); + if (ret) + return ret; + + init.name = kasprintf(GFP_KERNEL, "max96717.%s.clk_out", dev_name(dev)); + if (!init.name) + return -ENOMEM; + + priv->clk_hw.init = &init; + + ret = max96717_clk_set_rate(&priv->clk_hw, + MAX96717_DEFAULT_CLKOUT_RATE, 0); + if (ret) + goto free_init_name; + + ret = devm_clk_hw_register(dev, &priv->clk_hw); + kfree(init.name); + if (ret) + return dev_err_probe(dev, ret, "Cannot register clock HW\n"); + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + &priv->clk_hw); + if (ret) + return dev_err_probe(dev, ret, + "Cannot add OF clock provider\n"); + + return 0; + +free_init_name: + kfree(init.name); + return ret; +} + +static int max96717_gpiochip_probe(struct max96717_priv *priv) +{ + struct device *dev = priv->dev; + int ret; + + priv->pctldesc = (struct pinctrl_desc) { + .owner = THIS_MODULE, + .name = MAX96717_PINCTRL_NAME, + .pins = max96717_pins, + .npins = ARRAY_SIZE(max96717_pins), + .pctlops = &max96717_ctrl_ops, + .confops = &max96717_conf_ops, + .pmxops = &max96717_mux_ops, + .custom_params = max96717_cfg_params, + .num_custom_params = ARRAY_SIZE(max96717_cfg_params), + }; + + ret = devm_pinctrl_register_and_init(dev, &priv->pctldesc, priv, &priv->pctldev); + if (ret) + return ret; + + ret = pinctrl_enable(priv->pctldev); + if (ret) + return ret; + + priv->gc = (struct gpio_chip) { + .owner = THIS_MODULE, + .label = MAX96717_GPIOCHIP_NAME, + .base = -1, + .ngpio = MAX96717_GPIO_NUM, + .parent = dev, + .can_sleep = true, + .request = gpiochip_generic_request, + .free = gpiochip_generic_free, + .set_config = gpiochip_generic_config, + .get_direction = max96717_gpio_get_direction, + .direction_input = max96717_gpio_direction_input, + .direction_output = max96717_gpio_direction_output, + .get = max96717_gpio_get, + .set = max96717_gpio_set, + }; + + return devm_gpiochip_add_data(dev, &priv->gc, priv); +} + +static int max96717_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct max96717_priv *priv; + struct max_ser_ops *ops; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL); + if (!ops) + return -ENOMEM; + + priv->info = device_get_match_data(dev); + if (!priv->info) { + dev_err(dev, "Failed to get match data\n"); + return -ENODEV; + } + + priv->dev = dev; + priv->client = client; + i2c_set_clientdata(client, priv); + + priv->regmap = devm_regmap_init_i2c(client, &max96717_i2c_regmap); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + *ops = max96717_ops; + + if (priv->info->supports_tunnel_mode) + ops->set_tunnel_enable = max96717_set_tunnel_enable; + + ops->supports_noncontinuous_clock = priv->info->supports_noncontinuous_clock; + ops->num_pipes = priv->info->num_pipes; + ops->num_dts_per_pipe = priv->info->num_dts_per_pipe; + ops->num_phys = priv->info->num_phys; + priv->ser.ops = ops; + + ret = max96717_wait_for_device(priv); + if (ret) + return ret; + + ret = max96717_gpiochip_probe(priv); + if (ret) + return ret; + + ret = max96717_register_clkout(priv); + if (ret) + return ret; + + return max_ser_probe(client, &priv->ser); +} + +static void max96717_remove(struct i2c_client *client) +{ + struct max96717_priv *priv = i2c_get_clientdata(client); + + max_ser_remove(&priv->ser); +} + +static const struct max96717_chip_info max9295a_info = { + .num_pipes = 4, + .num_dts_per_pipe = 2, + .pipe_hw_ids = { 0, 1, 2, 3 }, + .num_phys = 1, + .phy_hw_ids = { 1 }, +}; + +static const struct max96717_chip_info max96717_info = { + .supports_3_data_lanes = true, + .supports_pkt_cnt = true, + .supports_tunnel_mode = true, + .supports_noncontinuous_clock = true, + .num_pipes = 1, + .num_dts_per_pipe = 4, + .pipe_hw_ids = { 2 }, + .num_phys = 1, + .phy_hw_ids = { 1 }, +}; + +static const struct of_device_id max96717_of_ids[] = { + { .compatible = "maxim,max9295a", .data = &max9295a_info }, + { .compatible = "maxim,max96717", .data = &max96717_info }, + { .compatible = "maxim,max96793", .data = &max96717_info }, + { } +}; +MODULE_DEVICE_TABLE(of, max96717_of_ids); + +static struct i2c_driver max96717_i2c_driver = { + .driver = { + .name = MAX96717_NAME, + .of_match_table = max96717_of_ids, + }, + .probe = max96717_probe, + .remove = max96717_remove, +}; + +module_i2c_driver(max96717_i2c_driver); + +MODULE_DESCRIPTION("MAX96717 GMSL2 Serializer Driver"); +MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/maxim-serdes/max96724.c b/drivers/media/i2c/maxim-serdes/max96724.c new file mode 100644 index 000000000000..d60dbfff2f2b --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max96724.c @@ -0,0 +1,905 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Maxim MAX96724 Quad GMSL2 Deserializer Driver + * + * Copyright (C) 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "max_des.h" + +#define MAX96724_REG0 0x0 + +#define MAX96724_REG3 0x3 +#define MAX96724_REG3_DIS_REM_CC_0(x) (BIT(0) << (2 * (x))) + +#define MAX96724_REG6 0x6 +#define MAX96724_REG6_LINK_EN GENMASK(3, 0) + +#define MAX96724_PWR1 0x13 +#define MAX96724_PWR1_RESET_ALL BIT(6) + +#define MAX96724_VIDEO_PIPE_SEL(p) (0xf0 + (p) / 2) +#define MAX96724_VIDEO_PIPE_SEL_STREAM(p) (GENMASK(1, 0) << (4 * ((p) % 2))) + +#define MAX96724_VIDEO_PIPE_EN 0xf4 +#define MAX96724_VIDEO_PIPE_EN_MASK(p) BIT(p) +#define MAX96724_VIDEO_PIPE_EN_STREAM_SEL_ALL BIT(4) + +#define MAX96724_VPRBS(p) (0x1dc + (p) * 0x20) +#define MAX96724_VPRBS_VIDEO_LOCK BIT(0) + +#define MAX96724_BACKTOP12 0x40b +#define MAX96724_BACKTOP12_CSI_OUT_EN BIT(1) + +#define MAX96724_BACKTOP21 0x414 +#define MAX96724_BACKTOP21_BPP8DBL(p) BIT(4 + (p)) + +#define MAX96724_BACKTOP22(x) (0x415 * (x) * 0x3) +#define MAX96724_BACKTOP22_PHY_CSI_TX_DPLL GENMASK(4, 0) +#define MAX96724_BACKTOP22_PHY_CSI_TX_DPLL_EN BIT(5) + +#define MAX96724_BACKTOP24 0x417 +#define MAX96724_BACKTOP24_BPP8DBL_MODE(p) BIT(4 + (p)) + +#define MAX96724_BACKTOP30 0x41d +#define MAX96724_BACKTOP30_BPP10DBL3 BIT(4) +#define MAX96724_BACKTOP30_BPP10DBL3_MODE BIT(5) + +#define MAX96724_BACKTOP31 0x41e +#define MAX96724_BACKTOP31_BPP10DBL2 BIT(6) +#define MAX96724_BACKTOP31_BPP10DBL2_MODE BIT(7) + +#define MAX96724_BACKTOP32 0x41f +#define MAX96724_BACKTOP32_BPP12(p) BIT(p) +#define MAX96724_BACKTOP32_BPP10DBL0 BIT(4) +#define MAX96724_BACKTOP32_BPP10DBL0_MODE BIT(5) +#define MAX96724_BACKTOP32_BPP10DBL1 BIT(6) +#define MAX96724_BACKTOP32_BPP10DBL1_MODE BIT(7) + +#define MAX96724_MIPI_PHY0 0x8a0 +#define MAX96724_MIPI_PHY0_PHY_CONFIG GENMASK(4, 0) +#define MAX96724_MIPI_PHY0_PHY_4X2 BIT(0) +#define MAX96724_MIPI_PHY0_PHY_2X4 BIT(2) +#define MAX96724_MIPI_PHY0_PHY_1X4A_2X2 BIT(3) +#define MAX96724_MIPI_PHY0_PHY_1X4B_2X2 BIT(4) + +#define MAX96724_MIPI_PHY2 0x8a2 +#define MAX96724_MIPI_PHY2_PHY_STDB_N_4(x) (GENMASK(5, 4) << ((x) / 2 * 2)) +#define MAX96724_MIPI_PHY2_PHY_STDB_N_2(x) (BIT(4 + (x))) + +#define MAX96724_MIPI_PHY3(x) (0x8a3 + (x) / 2) +#define MAX96724_MIPI_PHY3_PHY_LANE_MAP_4 GENMASK(7, 0) +#define MAX96724_MIPI_PHY3_PHY_LANE_MAP_2(x) (GENMASK(3, 0) << (4 * ((x) % 2))) + +#define MAX96724_MIPI_PHY5(x) (0x8a5 + (x) / 2) +#define MAX96724_MIPI_PHY5_PHY_POL_MAP_4_0_1 GENMASK(1, 0) +#define MAX96724_MIPI_PHY5_PHY_POL_MAP_4_2_3 GENMASK(4, 3) +#define MAX96724_MIPI_PHY5_PHY_POL_MAP_4_CLK BIT(5) +#define MAX96724_MIPI_PHY5_PHY_POL_MAP_2(x) (GENMASK(1, 0) << (3 * ((x) % 2))) +#define MAX96724_MIPI_PHY5_PHY_POL_MAP_2_CLK(x) BIT(2 + 3 * ((x) % 2)) + +#define MAX96724_MIPI_PHY13 0x8ad +#define MAX96724_MIPI_PHY13_T_T3_PREBEGIN GENMASK(5, 0) +#define MAX96724_MIPI_PHY13_T_T3_PREBEGIN_64X7 FIELD_PREP(MAX96724_MIPI_PHY13_T_T3_PREBEGIN, 63) + +#define MAX96724_MIPI_PHY14 0x8ae +#define MAX96724_MIPI_PHY14_T_T3_PREP GENMASK(1, 0) +#define MAX96724_MIPI_PHY14_T_T3_PREP_55NS FIELD_PREP(MAX96724_MIPI_PHY14_T_T3_PREP, 0b01) +#define MAX96724_MIPI_PHY14_T_T3_POST GENMASK(6, 2) +#define MAX96724_MIPI_PHY14_T_T3_POST_32X7 FIELD_PREP(MAX96724_MIPI_PHY14_T_T3_POST, 31) + +#define MAX96724_MIPI_CTRL_SEL 0x8ca +#define MAX96724_MIPI_CTRL_SEL_MASK(p) (GENMASK(1, 0) << ((p) * 2)) + +#define MAX96724_MIPI_PHY25(x) (0x8d0 + (x) / 2) +#define MAX96724_MIPI_PHY25_CSI2_TX_PKT_CNT(x) (GENMASK(3, 0) << (4 * ((x) % 2))) + +#define MAX96724_MIPI_PHY27(x) (0x8d2 + (x) / 2) +#define MAX96724_MIPI_PHY27_PHY_PKT_CNT(x) (GENMASK(3, 0) << (4 * ((x) % 2))) + +#define MAX96724_MIPI_TX3(x) (0x903 + (x) * 0x40) +#define MAX96724_MIPI_TX3_DESKEW_INIT_8X32K FIELD_PREP(GENMASK(2, 0), 0b001) +#define MAX96724_MIPI_TX3_DESKEW_INIT_AUTO BIT(7) + +#define MAX96724_MIPI_TX4(x) (0x904 + (x) * 0x40) +#define MAX96724_MIPI_TX4_DESKEW_PER_2K FIELD_PREP(GENMASK(2, 0), 0b001) +#define MAX96724_MIPI_TX4_DESKEW_PER_AUTO BIT(7) + +#define MAX96724_MIPI_TX10(x) (0x90a + (x) * 0x40) +#define MAX96724_MIPI_TX10_CSI2_CPHY_EN BIT(5) +#define MAX96724_MIPI_TX10_CSI2_LANE_CNT GENMASK(7, 6) + +#define MAX96724_MIPI_TX11(p) (0x90b + (p) * 0x40) +#define MAX96724_MIPI_TX12(p) (0x90c + (p) * 0x40) + +#define MAX96724_MIPI_TX13(p, x) (0x90d + (p) * 0x40 + (x) * 0x2) +#define MAX96724_MIPI_TX13_MAP_SRC_DT GENMASK(5, 0) +#define MAX96724_MIPI_TX13_MAP_SRC_VC GENMASK(7, 6) + +#define MAX96724_MIPI_TX14(p, x) (0x90e + (p) * 0x40 + (x) * 0x2) +#define MAX96724_MIPI_TX14_MAP_DST_DT GENMASK(5, 0) +#define MAX96724_MIPI_TX14_MAP_DST_VC GENMASK(7, 6) + +#define MAX96724_MIPI_TX45(p, x) (0x92d + (p) * 0x40 + (x) / 4) +#define MAX96724_MIPI_TX45_MAP_DPHY_DEST(x) (GENMASK(1, 0) << (2 * ((x) % 4))) + +#define MAX96724_MIPI_TX51(x) (0x933 + (x) * 0x40) +#define MAX96724_MIPI_TX51_ALT_MEM_MAP_12 BIT(0) +#define MAX96724_MIPI_TX51_ALT_MEM_MAP_8 BIT(1) +#define MAX96724_MIPI_TX51_ALT_MEM_MAP_10 BIT(2) +#define MAX96724_MIPI_TX51_ALT2_MEM_MAP_8 BIT(4) + +#define MAX96724_MIPI_TX54(x) (0x936 + (x) * 0x40) +#define MAX96724_MIPI_TX54_TUN_EN BIT(0) + +#define MAX96724_MIPI_TX57(x) (0x939 + (x) * 0x40) +#define MAX96724_MIPI_TX57_TUN_DEST GENMASK(5, 4) +#define MAX96724_MIPI_TX57_DIS_AUTO_TUN_DET BIT(6) + +#define MAX96724_DE_DET 0x11f0 +#define MAX96724_HS_DET 0x11f1 +#define MAX96724_VS_DET 0x11f2 +#define MAX96724_HS_POL 0x11f3 +#define MAX96724_VS_POL 0x11f4 +#define MAX96724_DET(p) BIT(p) + +#define MAX96724_DPLL_0(x) (0x1c00 + (x) * 0x100) +#define MAX96724_DPLL_0_CONFIG_SOFT_RST_N BIT(0) + +#define MAX96724_PHY1_ALT_CLOCK 5 + +#define field_get(mask, val) (((val) & (mask)) >> __ffs(mask)) +#define field_prep(mask, val) (((val) << __ffs(mask)) & (mask)) + +static const struct regmap_config max96724_i2c_regmap = { + .reg_bits = 16, + .val_bits = 8, + .max_register = 0x1f00, +}; + +struct max96724_priv { + struct max_des des; + const struct max96724_chip_info *info; + + struct device *dev; + struct i2c_client *client; + struct regmap *regmap; + + struct gpio_desc *gpiod_pwdn; +}; + +struct max96724_chip_info { + bool supports_pipe_stream_autoselect; + unsigned int num_pipes; +}; + +#define des_to_priv(_des) \ + container_of(_des, struct max96724_priv, des) + +static int max96724_wait_for_device(struct max96724_priv *priv) +{ + unsigned int i; + int ret; + + for (i = 0; i < 10; i++) { + unsigned int val; + + ret = regmap_read(priv->regmap, MAX96724_REG0, &val); + if (!ret && val) + return 0; + + msleep(100); + + dev_err(priv->dev, "Retry %u waiting for deserializer: %d\n", i, ret); + } + + return ret; +} + +static int max96724_reset(struct max96724_priv *priv) +{ + int ret; + + ret = max96724_wait_for_device(priv); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, MAX96724_PWR1, + MAX96724_PWR1_RESET_ALL, + FIELD_PREP(MAX96724_PWR1_RESET_ALL, 1)); + if (ret) + return ret; + + fsleep(10000); + + ret = max96724_wait_for_device(priv); + if (ret) + return ret; + + return 0; +} + +static int max96724_reg_read(struct max_des *des, unsigned int reg, + unsigned int *val) +{ + struct max96724_priv *priv = des_to_priv(des); + + return regmap_read(priv->regmap, reg, val); +} + +static int max96724_reg_write(struct max_des *des, unsigned int reg, + unsigned int val) +{ + struct max96724_priv *priv = des_to_priv(des); + + return regmap_write(priv->regmap, reg, val); +} + +static unsigned int max96724_phy_id(struct max_des *des, struct max_des_phy *phy) +{ + unsigned int num_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy); + + /* PHY 1 is the master PHY when combining PHY 0 and PHY 1. */ + if (phy->index == 0 && num_hw_data_lanes == 4) + return 1; + + return phy->index; +} + +static int max96724_log_pipe_status(struct max_des *des, + struct max_des_pipe *pipe, const char *name) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = pipe->index; + unsigned int val, mask; + int ret; + + ret = regmap_read(priv->regmap, MAX96724_VPRBS(index), &val); + if (ret) + return ret; + + pr_info("%s: \tvideo_lock: %u\n", name, + !!(val & MAX96724_VPRBS_VIDEO_LOCK)); + + mask = MAX96724_DET(index); + + ret = regmap_read(priv->regmap, MAX96724_DE_DET, &val); + if (ret) + return ret; + + pr_info("%s: \tde_det: %u\n", name, !!(val & mask)); + + ret = regmap_read(priv->regmap, MAX96724_HS_DET, &val); + if (ret) + return ret; + + pr_info("%s: \ths_det: %u\n", name, !!(val & mask)); + + ret = regmap_read(priv->regmap, MAX96724_VS_DET, &val); + if (ret) + return ret; + + pr_info("%s: \tvs_det: %u\n", name, !!(val & mask)); + + ret = regmap_read(priv->regmap, MAX96724_HS_POL, &val); + if (ret) + return ret; + + pr_info("%s: \ths_pol: %u\n", name, !!(val & mask)); + + ret = regmap_read(priv->regmap, MAX96724_VS_POL, &val); + if (ret) + return ret; + + pr_info("%s: \tvs_pol: %u\n", name, !!(val & mask)); + + return 0; +} + +static int max96724_log_phy_status(struct max_des *des, + struct max_des_phy *phy, const char *name) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = max96724_phy_id(des, phy); + unsigned int val; + int ret; + + ret = regmap_read(priv->regmap, MAX96724_MIPI_PHY25(index), &val); + if (ret) + return ret; + + pr_info("%s: \tcsi2_pkt_cnt: %lu\n", name, + field_get(MAX96724_MIPI_PHY25_CSI2_TX_PKT_CNT(index), val)); + + ret = regmap_read(priv->regmap, MAX96724_MIPI_PHY27(index), &val); + if (ret) + return ret; + + pr_info("%s: \tphy_pkt_cnt: %lu\n", name, + field_get(MAX96724_MIPI_PHY27_PHY_PKT_CNT(index), val)); + + return 0; +} + +static int max96724_set_enable(struct max_des *des, bool enable) +{ + struct max96724_priv *priv = des_to_priv(des); + + return regmap_assign_bits(priv->regmap, MAX96724_BACKTOP12, + MAX96724_BACKTOP12_CSI_OUT_EN, enable); +} + +static const unsigned int max96724_phys_configs_reg_val[] = { + MAX96724_MIPI_PHY0_PHY_1X4A_2X2, + MAX96724_MIPI_PHY0_PHY_2X4, + + MAX96724_MIPI_PHY0_PHY_4X2, + MAX96724_MIPI_PHY0_PHY_1X4A_2X2, + MAX96724_MIPI_PHY0_PHY_1X4B_2X2, + MAX96724_MIPI_PHY0_PHY_2X4, +}; + +static const struct max_phys_config max96724_phys_configs[] = { + /* + * PHY 1 can be in 4-lane mode (combining lanes of PHY 0 and PHY 1) + * but only use the data lanes of PHY0, while continuing to use the + * clock lane of PHY 1. + * Specifying clock-lanes as 5 turns on alternate clocking mode. + */ + { { 2, 0, 2, 2 }, { MAX96724_PHY1_ALT_CLOCK, 0, 0, 0 } }, + { { 2, 0, 4, 0 }, { MAX96724_PHY1_ALT_CLOCK, 0, 0, 0 } }, + + /* + * When combining PHY 0 and PHY 1 to make them function in 4-lane mode, + * PHY 1 is the master PHY, but we use PHY 0 here to maintain + * compatibility. + */ + { { 2, 2, 2, 2 } }, + { { 4, 0, 2, 2 } }, + { { 2, 2, 4, 0 } }, + { { 4, 0, 4, 0 } }, +}; + +static int max96724_init(struct max_des *des) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int i; + int ret; + + for (i = 0; i < des->ops->num_pipes; i++) { + ret = regmap_set_bits(priv->regmap, MAX96724_MIPI_TX57(i), + MAX96724_MIPI_TX57_DIS_AUTO_TUN_DET); + if (ret) + return ret; + } + + if (priv->info->supports_pipe_stream_autoselect) { + /* Enable stream autoselect. */ + ret = regmap_update_bits(priv->regmap, MAX96724_VIDEO_PIPE_EN, + MAX96724_VIDEO_PIPE_EN_STREAM_SEL_ALL, + FIELD_PREP(MAX96724_VIDEO_PIPE_EN_STREAM_SEL_ALL, 1)); + if (ret) + return ret; + } + + /* Set PHY mode. */ + ret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY0, + MAX96724_MIPI_PHY0_PHY_CONFIG, + max96724_phys_configs_reg_val[des->phys_config]); + if (ret) + return ret; + + return 0; +} + +static int max96724_init_phy(struct max_des *des, struct max_des_phy *phy) +{ + struct max96724_priv *priv = des_to_priv(des); + bool is_cphy = phy->bus_type == V4L2_MBUS_CSI2_CPHY; + unsigned int num_data_lanes = phy->mipi.num_data_lanes; + unsigned int dpll_freq = phy->link_frequency * 2; + unsigned int num_hw_data_lanes; + unsigned int index; + unsigned int used_data_lanes = 0; + unsigned int val, mask; + unsigned int i; + int ret; + + index = max96724_phy_id(des, phy); + num_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy); + + ret = regmap_update_bits(priv->regmap, MAX96724_MIPI_TX10(index), + MAX96724_MIPI_TX10_CSI2_LANE_CNT, + FIELD_PREP(MAX96724_MIPI_TX10_CSI2_LANE_CNT, + num_data_lanes - 1)); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX10(index), + MAX96724_MIPI_TX10_CSI2_CPHY_EN, is_cphy); + if (ret) + return ret; + + /* Configure lane mapping. */ + val = 0; + for (i = 0; i < num_hw_data_lanes ; i++) { + unsigned int map; + + if (i < num_data_lanes) + map = phy->mipi.data_lanes[i] - 1; + else + map = ffz(used_data_lanes); + + val |= map << (i * 2); + used_data_lanes |= BIT(map); + } + + if (num_hw_data_lanes == 4) + mask = MAX96724_MIPI_PHY3_PHY_LANE_MAP_4; + else + mask = MAX96724_MIPI_PHY3_PHY_LANE_MAP_2(index); + + ret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY3(index), + mask, field_prep(mask, val)); + if (ret) + return ret; + + /* Configure lane polarity. */ + val = 0; + for (i = 0; i < num_data_lanes; i++) + if (phy->mipi.lane_polarities[i + 1]) + val |= BIT(i); + + if (num_hw_data_lanes == 4) { + ret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY5(index), + MAX96724_MIPI_PHY5_PHY_POL_MAP_4_0_1 | + MAX96724_MIPI_PHY5_PHY_POL_MAP_4_2_3, + FIELD_PREP(MAX96724_MIPI_PHY5_PHY_POL_MAP_4_0_1, + val) | + FIELD_PREP(MAX96724_MIPI_PHY5_PHY_POL_MAP_4_2_3, + val >> 2)); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_PHY5(index), + MAX96724_MIPI_PHY5_PHY_POL_MAP_4_CLK, + phy->mipi.lane_polarities[0]); + if (ret) + return ret; + } else { + ret = regmap_update_bits(priv->regmap, MAX96724_MIPI_PHY5(index), + MAX96724_MIPI_PHY5_PHY_POL_MAP_2(index), + field_prep(MAX96724_MIPI_PHY5_PHY_POL_MAP_2(index), val)); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_PHY5(index), + MAX96724_MIPI_PHY5_PHY_POL_MAP_2_CLK(index), + phy->mipi.lane_polarities[0]); + if (ret) + return ret; + } + + if (!is_cphy && dpll_freq > 1500000000ull) { + /* Enable initial deskew with 2 x 32k UI. */ + ret = regmap_write(priv->regmap, MAX96724_MIPI_TX3(index), + MAX96724_MIPI_TX3_DESKEW_INIT_AUTO | + MAX96724_MIPI_TX3_DESKEW_INIT_8X32K); + if (ret) + return ret; + + /* Enable periodic deskew with 2 x 1k UI.. */ + ret = regmap_write(priv->regmap, MAX96724_MIPI_TX4(index), + MAX96724_MIPI_TX4_DESKEW_PER_AUTO | + MAX96724_MIPI_TX4_DESKEW_PER_2K); + if (ret) + return ret; + } else { + /* Disable initial deskew. */ + ret = regmap_write(priv->regmap, MAX96724_MIPI_TX3(index), 0x0); + if (ret) + return ret; + + /* Disable periodic deskew. */ + ret = regmap_write(priv->regmap, MAX96724_MIPI_TX4(index), 0x0); + if (ret) + return ret; + } + + if (is_cphy) { + /* Configure C-PHY timings. */ + ret = regmap_write(priv->regmap, MAX96724_MIPI_PHY13, + MAX96724_MIPI_PHY13_T_T3_PREBEGIN_64X7); + if (ret) + return ret; + + ret = regmap_write(priv->regmap, MAX96724_MIPI_PHY14, + MAX96724_MIPI_PHY14_T_T3_PREP_55NS | + MAX96724_MIPI_PHY14_T_T3_POST_32X7); + if (ret) + return ret; + } + + /* Put DPLL block into reset. */ + ret = regmap_clear_bits(priv->regmap, MAX96724_DPLL_0(index), + MAX96724_DPLL_0_CONFIG_SOFT_RST_N); + if (ret) + return ret; + + /* Set DPLL frequency. */ + ret = regmap_update_bits(priv->regmap, MAX96724_BACKTOP22(index), + MAX96724_BACKTOP22_PHY_CSI_TX_DPLL, + FIELD_PREP(MAX96724_BACKTOP22_PHY_CSI_TX_DPLL, + div_u64(dpll_freq, 100000000))); + if (ret) + return ret; + + /* Enable DPLL frequency. */ + ret = regmap_set_bits(priv->regmap, MAX96724_BACKTOP22(index), + MAX96724_BACKTOP22_PHY_CSI_TX_DPLL_EN); + if (ret) + return ret; + + /* Pull DPLL block out of reset. */ + ret = regmap_set_bits(priv->regmap, MAX96724_DPLL_0(index), + MAX96724_DPLL_0_CONFIG_SOFT_RST_N); + if (ret) + return ret; + + return 0; +} + +static int max96724_set_phy_mode(struct max_des *des, struct max_des_phy *phy, + struct max_des_phy_mode *mode) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = max96724_phy_id(des, phy); + int ret; + + /* Set alternate memory map modes. */ + ret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index), + MAX96724_MIPI_TX51_ALT_MEM_MAP_12, + mode->alt_mem_map12); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index), + MAX96724_MIPI_TX51_ALT_MEM_MAP_8, + mode->alt_mem_map8); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index), + MAX96724_MIPI_TX51_ALT_MEM_MAP_10, + mode->alt_mem_map10); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX51(index), + MAX96724_MIPI_TX51_ALT2_MEM_MAP_8, + mode->alt2_mem_map8); + if (ret) + return ret; + + return 0; +} + +static int max96724_set_phy_active(struct max_des *des, struct max_des_phy *phy, + bool enable) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = max96724_phy_id(des, phy); + unsigned int num_hw_data_lanes; + unsigned int mask; + + num_hw_data_lanes = max_des_phy_hw_data_lanes(des, phy); + + if (num_hw_data_lanes == 4) + /* PHY 1 -> bits [1:0] */ + /* PHY 2 -> bits [3:2] */ + mask = MAX96724_MIPI_PHY2_PHY_STDB_N_4(index); + else + mask = MAX96724_MIPI_PHY2_PHY_STDB_N_2(index); + + return regmap_assign_bits(priv->regmap, MAX96724_MIPI_PHY2, mask, enable); +} + +static int max96724_set_pipe_remap(struct max_des *des, + struct max_des_pipe *pipe, + unsigned int i, + struct max_des_remap *remap) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = pipe->index; + int ret; + + /* Set source Data Type and Virtual Channel. */ + /* TODO: implement extended Virtual Channel. */ + ret = regmap_write(priv->regmap, MAX96724_MIPI_TX13(index, i), + FIELD_PREP(MAX96724_MIPI_TX13_MAP_SRC_DT, + remap->from_dt) | + FIELD_PREP(MAX96724_MIPI_TX13_MAP_SRC_VC, + remap->from_vc)); + if (ret) + return ret; + + /* Set destination Data Type and Virtual Channel. */ + /* TODO: implement extended Virtual Channel. */ + ret = regmap_write(priv->regmap, MAX96724_MIPI_TX14(index, i), + FIELD_PREP(MAX96724_MIPI_TX14_MAP_DST_DT, + remap->to_dt) | + FIELD_PREP(MAX96724_MIPI_TX14_MAP_DST_VC, + remap->to_vc)); + if (ret) + return ret; + + /* Set destination PHY. */ + return regmap_update_bits(priv->regmap, MAX96724_MIPI_TX45(index, i), + MAX96724_MIPI_TX45_MAP_DPHY_DEST(i), + field_prep(MAX96724_MIPI_TX45_MAP_DPHY_DEST(i), + remap->phy)); +} + +static int max96724_set_pipe_remaps_enable(struct max_des *des, + struct max_des_pipe *pipe, + unsigned int mask) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = pipe->index; + int ret; + + ret = regmap_write(priv->regmap, MAX96724_MIPI_TX11(index), mask); + if (ret) + return ret; + + return regmap_write(priv->regmap, MAX96724_MIPI_TX12(index), mask >> 8); +} + +static int max96724_set_pipe_phy(struct max_des *des, struct max_des_pipe *pipe, + struct max_des_phy *phy) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int phy_index = max96724_phy_id(des, phy); + unsigned int index = pipe->index; + int ret; + + ret = regmap_update_bits(priv->regmap, MAX96724_MIPI_TX57(index), + MAX96724_MIPI_TX57_TUN_DEST, + FIELD_PREP(MAX96724_MIPI_TX57_TUN_DEST, + phy_index)); + if (ret) + return ret; + + return regmap_update_bits(priv->regmap, MAX96724_MIPI_CTRL_SEL, + MAX96724_MIPI_CTRL_SEL_MASK(index), + field_prep(MAX96724_MIPI_CTRL_SEL_MASK(index), + phy_index)); +} + +static int max96724_set_pipe_enable(struct max_des *des, struct max_des_pipe *pipe, + bool enable) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = pipe->index; + + return regmap_assign_bits(priv->regmap, MAX96724_VIDEO_PIPE_EN, + MAX96724_VIDEO_PIPE_EN_MASK(index), enable); +} + +static int max96724_set_pipe_stream_id(struct max_des *des, struct max_des_pipe *pipe, + unsigned int stream_id) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = pipe->index; + + return regmap_update_bits(priv->regmap, MAX96724_VIDEO_PIPE_SEL(index), + MAX96724_VIDEO_PIPE_SEL_STREAM(index), + field_prep(MAX96724_VIDEO_PIPE_SEL_STREAM(index), + stream_id)); +} + +static int max96724_set_pipe_mode(struct max_des *des, + struct max_des_pipe *pipe, + struct max_des_pipe_mode *mode) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int index = pipe->index; + unsigned int reg, mask, mode_mask; + int ret; + + /* Set 8bit double mode. */ + ret = regmap_assign_bits(priv->regmap, MAX96724_BACKTOP21, + MAX96724_BACKTOP21_BPP8DBL(index), mode->dbl8); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, MAX96724_BACKTOP24, + MAX96724_BACKTOP24_BPP8DBL_MODE(index), + mode->dbl8mode); + if (ret) + return ret; + + /* Set 10bit double mode. */ + if (index == 3) { + reg = MAX96724_BACKTOP30; + mask = MAX96724_BACKTOP30_BPP10DBL3; + mode_mask = MAX96724_BACKTOP30_BPP10DBL3_MODE; + } else if (index == 2) { + reg = MAX96724_BACKTOP31; + mask = MAX96724_BACKTOP31_BPP10DBL2; + mode_mask = MAX96724_BACKTOP31_BPP10DBL2_MODE; + } else if (index == 1) { + reg = MAX96724_BACKTOP32; + mask = MAX96724_BACKTOP32_BPP10DBL1; + mode_mask = MAX96724_BACKTOP32_BPP10DBL1_MODE; + } else { + reg = MAX96724_BACKTOP32; + mask = MAX96724_BACKTOP32_BPP10DBL0; + mode_mask = MAX96724_BACKTOP32_BPP10DBL0_MODE; + } + + ret = regmap_assign_bits(priv->regmap, reg, mask, mode->dbl10); + if (ret) + return ret; + + ret = regmap_assign_bits(priv->regmap, reg, mode_mask, mode->dbl10mode); + if (ret) + return ret; + + /* Set 12bit double mode. */ + return regmap_assign_bits(priv->regmap, MAX96724_BACKTOP32, + MAX96724_BACKTOP32_BPP12(index), mode->dbl12); +} + +static int max96724_set_pipe_tunnel_enable(struct max_des *des, + struct max_des_pipe *pipe, bool enable) +{ + struct max96724_priv *priv = des_to_priv(des); + + return regmap_assign_bits(priv->regmap, MAX96724_MIPI_TX54(pipe->index), + MAX96724_MIPI_TX54_TUN_EN, enable); +} + +static int max96724_select_links(struct max_des *des, unsigned int mask) +{ + struct max96724_priv *priv = des_to_priv(des); + unsigned int val = 0; + unsigned int i; + + for (i = 0; i < des->ops->num_links; i++) { + if ((mask & BIT(i))) + continue; + + val |= MAX96724_REG3_DIS_REM_CC_0(i); + } + + return regmap_write(priv->regmap, MAX96724_REG3, val); +} + +static const struct max_des_ops max96724_ops = { + .num_phys = 4, + .num_links = 4, + .num_remaps_per_pipe = 16, + .phys_configs = { + .num_configs = ARRAY_SIZE(max96724_phys_configs), + .configs = max96724_phys_configs, + }, + .reg_read = max96724_reg_read, + .reg_write = max96724_reg_write, + .log_pipe_status = max96724_log_pipe_status, + .log_phy_status = max96724_log_phy_status, + .set_enable = max96724_set_enable, + .init = max96724_init, + .init_phy = max96724_init_phy, + .set_phy_mode = max96724_set_phy_mode, + .set_phy_active = max96724_set_phy_active, + .set_pipe_phy = max96724_set_pipe_phy, + .set_pipe_stream_id = max96724_set_pipe_stream_id, + .set_pipe_enable = max96724_set_pipe_enable, + .set_pipe_remap = max96724_set_pipe_remap, + .set_pipe_remaps_enable = max96724_set_pipe_remaps_enable, + .set_pipe_mode = max96724_set_pipe_mode, + .set_pipe_tunnel_enable = max96724_set_pipe_tunnel_enable, + .select_links = max96724_select_links, +}; + +static const struct max96724_chip_info max96724_info = { + .supports_pipe_stream_autoselect = true, + .num_pipes = 4, +}; + +static const struct max96724_chip_info max96712_info = { + .num_pipes = 8, +}; + +static int max96724_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct max96724_priv *priv; + struct max_des_ops *ops; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL); + if (!ops) + return -ENOMEM; + + priv->info = device_get_match_data(dev); + if (!priv->info) { + dev_err(dev, "Failed to get match data\n"); + return -ENODEV; + } + + priv->dev = dev; + priv->client = client; + i2c_set_clientdata(client, priv); + + priv->regmap = devm_regmap_init_i2c(client, &max96724_i2c_regmap); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable", + GPIOD_OUT_HIGH); + if (IS_ERR(priv->gpiod_pwdn)) + return PTR_ERR(priv->gpiod_pwdn); + + if (priv->gpiod_pwdn) { + /* PWDN must be held for 1us for reset */ + udelay(1); + + gpiod_set_value_cansleep(priv->gpiod_pwdn, 0); + /* Maximum power-up time (tLOCK) 4ms */ + usleep_range(4000, 5000); + } + + *ops = max96724_ops; + ops->num_pipes = priv->info->num_pipes; + priv->des.ops = ops; + + ret = max96724_reset(priv); + if (ret) + return ret; + + return max_des_probe(client, &priv->des); +} + +static void max96724_remove(struct i2c_client *client) +{ + struct max96724_priv *priv = i2c_get_clientdata(client); + + max_des_remove(&priv->des); + + gpiod_set_value_cansleep(priv->gpiod_pwdn, 1); +} + +static const struct of_device_id max96724_of_table[] = { + { .compatible = "maxim,max96712", .data = &max96712_info }, + { .compatible = "maxim,max96724", .data = &max96724_info }, + { }, +}; +MODULE_DEVICE_TABLE(of, max96724_of_table); + +static struct i2c_driver max96724_i2c_driver = { + .driver = { + .name = "max96724", + .of_match_table = of_match_ptr(max96724_of_table), + }, + .probe = max96724_probe, + .remove = max96724_remove, +}; + +module_i2c_driver(max96724_i2c_driver); + +MODULE_DESCRIPTION("Maxim MAX96724 Quad GMSL2 Deserializer Driver"); +MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/maxim-serdes/max_des.c b/drivers/media/i2c/maxim-serdes/max_des.c new file mode 100644 index 000000000000..ba4c697ad60e --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max_des.c @@ -0,0 +1,2321 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Maxim GMSL2 Deserializer Driver + * + * Copyright (C) 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "max_des.h" +#include "max_ser.h" +#include "max_serdes.h" + +#define MAX_DES_LINK_FREQUENCY_MIN 100000000ull +#define MAX_DES_LINK_FREQUENCY_DEFAULT 750000000ull +#define MAX_DES_LINK_FREQUENCY_MAX 1250000000ull + +#define MAX_DES_PHYS_NUM 4 +#define MAX_DES_PIPES_NUM 8 + +struct max_des_priv { + struct max_des *des; + unsigned int versions; + + struct device *dev; + struct i2c_client *client; + struct i2c_atr *atr; + struct i2c_mux_core *mux; + + struct media_pad *pads; + struct regulator **pocs; + struct max_source *sources; + u64 *streams_masks; + + struct v4l2_subdev sd; + struct v4l2_async_notifier nf; + + struct max_des_phy *unused_phy; +}; + +struct max_des_remap_context { + /* Mark whether chip can function in tunnel mode. */ + bool tunnel_enable; + /* Mark the PHYs to which each pipe is mapped. */ + unsigned long pipe_phy_masks[MAX_DES_PIPES_NUM]; + /* Mark whether pipe has remapped VC ids. */ + bool vc_ids_remapped[MAX_DES_PIPES_NUM]; + /* Map between pipe VC ids and PHY VC ids. */ + unsigned int vc_ids_map[MAX_DES_PIPES_NUM][MAX_DES_PHYS_NUM][MAX_SERDES_VC_ID_NUM]; + /* Mark whether a pipe VC id has been mapped to a PHY VC id. */ + unsigned long vc_ids_masks[MAX_DES_PIPES_NUM][MAX_DES_PHYS_NUM]; + /* Mark whether a PHY VC id has been mapped. */ + unsigned long dst_vc_ids_masks[MAX_DES_PHYS_NUM]; +}; + +struct max_des_mode_context { + bool phys_bpp8_shared_with_16[MAX_DES_PHYS_NUM]; + bool pipes_bpp8_shared_with_16[MAX_DES_PIPES_NUM]; + u32 phys_double_bpps[MAX_DES_PHYS_NUM]; + u32 pipes_double_bpps[MAX_DES_PIPES_NUM]; +}; + +static inline struct max_des_priv *sd_to_priv(struct v4l2_subdev *sd) +{ + return container_of(sd, struct max_des_priv, sd); +} + +static inline struct max_des_priv *nf_to_priv(struct v4l2_async_notifier *nf) +{ + return container_of(nf, struct max_des_priv, nf); +} + +static inline bool max_des_pad_is_sink(struct max_des *des, u32 pad) +{ + return pad < des->ops->num_links; +} + +static inline bool max_des_pad_is_source(struct max_des *des, u32 pad) +{ + return pad >= des->ops->num_links; +} + +static inline unsigned int max_des_link_to_pad(struct max_des *des, + struct max_des_link *link) +{ + return link->index; +} + +static inline unsigned int max_des_phy_to_pad(struct max_des *des, + struct max_des_phy *phy) +{ + return phy->index + des->ops->num_links; +} + +static inline unsigned int max_des_num_pads(struct max_des *des) +{ + return des->ops->num_links + des->ops->num_phys; +} + +static struct max_des_phy *max_des_pad_to_phy(struct max_des *des, u32 pad) +{ + if (!max_des_pad_is_source(des, pad)) + return NULL; + + return &des->phys[pad - des->ops->num_links]; +} + +static struct max_des_link *max_des_pad_to_link(struct max_des *des, u32 pad) +{ + if (!max_des_pad_is_sink(des, pad)) + return NULL; + + return &des->links[pad]; +} + +static struct max_des_pipe * +max_des_find_link_pipe(struct max_des *des, struct max_des_link *link) +{ + unsigned int i; + + for (i = 0; i < des->ops->num_pipes; i++) { + struct max_des_pipe *pipe = &des->pipes[i]; + + if (pipe->link_id == link->index) + return pipe; + } + + return NULL; +} + +static struct max_source * +max_des_find_link_source(struct max_des_priv *priv, struct max_des_link *link) +{ + return &priv->sources[link->index]; +} + +static int max_des_set_pipe_remaps(struct max_des_priv *priv, + struct max_des_pipe *pipe, + struct max_des_remap *remaps, + unsigned int num_remaps) +{ + struct max_des *des = priv->des; + unsigned int i; + int ret; + + for (i = 0; i < num_remaps; i++) { + struct max_des_remap *remap = &remaps[i]; + + ret = des->ops->set_pipe_remap(des, pipe, i, remap); + if (ret) + return ret; + } + + return des->ops->set_pipe_remaps_enable(des, pipe, GENMASK(num_remaps - 1, 0)); +} + +static int max_des_set_phy_active(struct max_des *des, struct max_des_phy *phy, + bool active) +{ + int ret; + + ret = des->ops->set_phy_active(des, phy, active); + if (ret) + return ret; + + phy->active = active; + + return 0; +} + +static int max_des_set_pipe_enable(struct max_des *des, struct max_des_pipe *pipe, + bool enable) +{ + int ret; + + ret = des->ops->set_pipe_enable(des, pipe, enable); + if (ret) + return ret; + + pipe->enabled = enable; + + return 0; +} + +static int max_des_map_src_dst_vc_id(struct max_des_remap_context *context, + unsigned int pipe_id, unsigned int phy_id, + unsigned int src_vc_id, unsigned int *dst_vc_id) +{ + unsigned int vc_id; + + if (src_vc_id >= MAX_SERDES_VC_ID_NUM) + return -E2BIG; + + if (context->vc_ids_masks[pipe_id][phy_id] & BIT(src_vc_id)) { + *dst_vc_id = context->vc_ids_map[pipe_id][phy_id][src_vc_id]; + return 0; + } + + if (!(context->dst_vc_ids_masks[phy_id] & BIT(src_vc_id))) { + vc_id = src_vc_id; + } else { + context->vc_ids_remapped[pipe_id] = true; + vc_id = ffz(context->dst_vc_ids_masks[phy_id]); + } + + if (vc_id >= MAX_SERDES_VC_ID_NUM) + return -E2BIG; + + context->pipe_phy_masks[pipe_id] |= BIT(phy_id); + context->dst_vc_ids_masks[phy_id] |= BIT(vc_id); + + context->vc_ids_map[pipe_id][phy_id][src_vc_id] = vc_id; + context->vc_ids_masks[pipe_id][phy_id] |= BIT(src_vc_id); + + *dst_vc_id = vc_id; + + return 0; +} + +static int max_des_populate_remap_context(struct max_des_priv *priv, + struct max_des_remap_context *context, + const struct v4l2_subdev_krouting *routing) +{ + struct max_des *des = priv->des; + struct v4l2_subdev_route *route; + unsigned int link_id; + bool tunnel_enable; + int ret; + + for_each_active_route(routing, route) { + struct v4l2_mbus_frame_desc_entry entry; + struct max_source *source; + struct max_des_link *link; + struct max_des_pipe *pipe; + struct max_des_phy *phy; + unsigned int vc_id; + + link = max_des_pad_to_link(des, route->sink_pad); + if (!link) { + dev_err(priv->dev, "Failed to find link for pad %u\n", + route->sink_pad); + return -ENOENT; + } + + phy = max_des_pad_to_phy(des, route->source_pad); + if (!phy) { + dev_err(priv->dev, "Failed to find PHY for pad %u\n", + route->source_pad); + return -ENOENT; + } + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + if (!source->sd) + continue; + + ret = max_get_fd_stream_entry(source->sd, source->pad, + route->sink_stream, &entry); + if (ret) { + dev_err(priv->dev, + "Failed to find frame desc entry for stream %u:%u: %d\n", + route->sink_pad, route->sink_stream, ret); + return ret; + } + + ret = max_des_map_src_dst_vc_id(context, pipe->index, phy->index, + entry.bus.csi2.vc, &vc_id); + if (ret) + return ret; + } + + if (!des->ops->set_pipe_tunnel_enable) + return 0; + + tunnel_enable = true; + + for (link_id = 0; link_id < des->ops->num_links; link_id++) { + struct max_des_link *link = &des->links[link_id]; + struct max_des_pipe *pipe; + struct max_source *source; + + if (!link->enabled) + continue; + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + if (!source->sd) + continue; + + if (max_ser_supports_tunnel_mode(source->sd) && + hweight_long(context->pipe_phy_masks[pipe->index]) <= 1 && + !context->vc_ids_remapped[pipe->index]) + continue; + + tunnel_enable = false; + } + + context->tunnel_enable = tunnel_enable; + + return 0; +} + +static int max_des_populate_mode_context(struct max_des_priv *priv, + struct max_des_mode_context *context, + const struct v4l2_subdev_krouting *routing) +{ + bool bpp8_not_shared_with_16_phys[MAX_DES_PHYS_NUM] = { 0 }; + u32 undoubled_bpps_phys[MAX_DES_PHYS_NUM] = { 0 }; + struct max_des *des = priv->des; + struct v4l2_subdev_route *route; + struct max_des_link *link; + struct max_des_pipe *pipe; + struct max_des_phy *phy; + unsigned int doubled_bpp; + unsigned int bpp; + unsigned int i; + u32 stream_bpps; + u32 sink_bpps; + int ret; + + /* + * Go over all streams and check if the current stream is doubled. + * + * If the current stream is doubled, add it to a doubled mask for both + * the pipe and the PHY. + * + * If the current stream is not doubled, add it to a local undoubled + * mask for the PHY. + * + * Also, track whether an 8bpp stream is shared with any bpp > 8 on both + * the PHYs and the pipes, since that needs to be special cased. + * + * After going over all the streams, remove the undoubled streams from + * the doubled ones. Doubled and undoubled streams cannot be streamed + * over the same PHY. + * + * Then, do a second pass to remove the undoubled streams from the pipes. + * + * This operation cannot be done in a single pass because any pipe might + * generate an undoubled stream for a specific bpp, causing already + * processed pipes to need to have their doubled bpps updated. + */ + + for_each_active_route(routing, route) { + unsigned int min_bpp; + unsigned int max_bpp; + + phy = max_des_pad_to_phy(des, route->source_pad); + if (!phy) + return -ENOENT; + + link = max_des_pad_to_link(des, route->sink_pad); + if (!link) + return -ENOENT; + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + ret = max_get_bpps(priv->sources, 0, &stream_bpps, + routing, route->sink_pad, + BIT_ULL(route->sink_stream)); + if (ret) + return ret; + + ret = max_get_bpps(priv->sources, 0, &sink_bpps, + routing, route->sink_pad, ~0ULL); + if (ret) + return ret; + + ret = max_process_bpps(priv->dev, sink_bpps, ~0U, &doubled_bpp); + if (ret) + return ret; + + bpp = __ffs(stream_bpps); + min_bpp = __ffs(sink_bpps); + max_bpp = __fls(sink_bpps); + + if (bpp == doubled_bpp) { + context->phys_double_bpps[phy->index] |= BIT(bpp); + context->pipes_double_bpps[pipe->index] |= BIT(bpp); + } else { + undoubled_bpps_phys[phy->index] |= BIT(bpp); + } + + if (min_bpp == 8 && max_bpp > 8) { + context->phys_bpp8_shared_with_16[phy->index] = true; + context->pipes_bpp8_shared_with_16[pipe->index] = true; + } else if (min_bpp == 8 && max_bpp == 8) { + bpp8_not_shared_with_16_phys[phy->index] = true; + } + } + + for (i = 0; i < des->ops->num_phys; i++) { + if (context->phys_bpp8_shared_with_16[i] && bpp8_not_shared_with_16_phys[i]) { + dev_err(priv->dev, + "Cannot stream 8bpp coming from pipes padded to 16bpp " + "and pipes not padded to 16bpp on the same PHY\n"); + return -EINVAL; + } + } + + for (i = 0; i < des->ops->num_phys; i++) + context->phys_double_bpps[i] &= ~undoubled_bpps_phys[i]; + + for_each_active_route(routing, route) { + struct max_des_link *link; + struct max_des_pipe *pipe; + struct max_des_phy *phy; + + phy = max_des_pad_to_phy(des, route->source_pad); + if (!phy) + return -ENOENT; + + link = max_des_pad_to_link(des, route->sink_pad); + if (!link) + return -ENOENT; + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + context->pipes_double_bpps[pipe->index] &= + context->phys_double_bpps[phy->index]; + } + + return 0; +} + +static void max_des_get_pipe_mode(struct max_des_mode_context *context, + struct max_des_pipe *pipe, + struct max_des_pipe_mode *mode) +{ + u32 double_bpps = context->pipes_double_bpps[pipe->index]; + + if ((double_bpps & BIT(8)) && + !context->pipes_bpp8_shared_with_16[pipe->index]) { + mode->dbl8 = true; + mode->dbl8mode = true; + } +} + +static void max_des_get_phy_mode(struct max_des_mode_context *context, + struct max_des_phy *phy, + struct max_des_phy_mode *mode) +{ + bool bpp8_pipe_shared_with_16 = context->phys_bpp8_shared_with_16[phy->index]; + u32 double_bpps = context->phys_double_bpps[phy->index]; + + if (BIT(8) & double_bpps) { + if (bpp8_pipe_shared_with_16) + mode->alt2_mem_map8 = true; + else + mode->alt_mem_map8 = true; + } + + if (BIT(10) & double_bpps) + mode->alt_mem_map10 = true; + + if (BIT(12) & double_bpps) + mode->alt_mem_map12 = true; +} + +static int max_des_set_modes(struct max_des_priv *priv, + struct max_des_mode_context *context) +{ + struct max_des *des = priv->des; + unsigned int i; + int ret; + + for (i = 0; i < des->ops->num_phys; i++) { + struct max_des_phy *phy = &des->phys[i]; + struct max_des_phy_mode mode = { 0 }; + + max_des_get_phy_mode(context, phy, &mode); + + if (phy->mode.alt_mem_map8 == mode.alt_mem_map8 && + phy->mode.alt_mem_map10 == mode.alt_mem_map10 && + phy->mode.alt_mem_map12 == mode.alt_mem_map12 && + phy->mode.alt2_mem_map8 == mode.alt2_mem_map8) + continue; + + ret = des->ops->set_phy_mode(des, phy, &mode); + if (ret) + return ret; + + phy->mode = mode; + } + + for (i = 0; i < des->ops->num_pipes; i++) { + struct max_des_pipe *pipe = &des->pipes[i]; + struct max_des_pipe_mode mode = { 0 }; + + max_des_get_pipe_mode(context, pipe, &mode); + + if (pipe->mode.dbl8 == mode.dbl8 && + pipe->mode.dbl10 == mode.dbl10 && + pipe->mode.dbl12 == mode.dbl12 && + pipe->mode.dbl8mode == mode.dbl8mode && + pipe->mode.dbl10mode == mode.dbl10mode) + continue; + + ret = des->ops->set_pipe_mode(des, pipe, &mode); + if (ret) + return ret; + + pipe->mode = mode; + } + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + struct max_des_pipe *pipe; + struct max_source *source; + + if (!link->enabled) + continue; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + if (!source->sd) + continue; + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + if (!source->sd) + continue; + + ret = max_ser_set_double_bpps(source->sd, + context->pipes_double_bpps[pipe->index]); + if (ret) + return ret; + } + + return 0; +} + +static int max_des_set_tunnel(struct max_des_priv *priv, + struct max_des_remap_context *context) +{ + struct max_des *des = priv->des; + unsigned int i; + int ret; + + if (des->tunnel == context->tunnel_enable) + return 0; + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + struct max_des_pipe *pipe; + struct max_source *source; + + if (!link->enabled) + continue; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + if (!source->sd) + continue; + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + if (!source->sd) + continue; + + if (des->ops->set_pipe_tunnel_enable) { + ret = des->ops->set_pipe_tunnel_enable(des, pipe, + context->tunnel_enable); + if (ret) + return ret; + } + + ret = max_ser_set_tunnel_enable(source->sd, context->tunnel_enable); + if (ret) + return ret; + } + + des->tunnel = context->tunnel_enable; + + return 0; +} + +static int max_des_set_pipes_phy(struct max_des_priv *priv, + struct max_des_remap_context *context) +{ + struct max_des *des = priv->des; + unsigned int i; + int ret; + + if (!des->ops->set_pipe_phy) + return 0; + + for (i = 0; i < des->ops->num_pipes; i++) { + struct max_des_pipe *pipe = &des->pipes[i]; + struct max_des_phy *phy; + unsigned int phy_id; + + phy_id = find_first_bit(&context->pipe_phy_masks[pipe->index], + des->ops->num_phys); + + if (priv->unused_phy && + (!context->tunnel_enable || phy_id == des->ops->num_phys)) + phy_id = priv->unused_phy->index; + + if (phy_id != des->ops->num_phys) { + phy = &des->phys[phy_id]; + + ret = des->ops->set_pipe_phy(des, pipe, phy); + if (ret) + return ret; + } + + pipe->phy_id = phy_id; + } + + return 0; +} + +static int max_des_add_remap(struct max_des_remap *remaps, + unsigned int *num_remaps, unsigned int phy_id, + unsigned int src_vc_id, unsigned int dst_vc_id, + unsigned int dt) +{ + struct max_des_remap *remap = &remaps[*num_remaps]; + + remap->from_dt = dt; + remap->from_vc = src_vc_id; + remap->to_dt = dt; + remap->to_vc = dst_vc_id; + remap->phy = phy_id; + + (*num_remaps)++; + + return 0; +} + +static int max_des_get_pipe_remaps(struct max_des_priv *priv, + struct max_des_remap_context *context, + struct max_des_pipe *pipe, + struct max_source *source, + struct max_des_remap *remaps, + unsigned int *num_remaps, + const struct v4l2_subdev_krouting *routing, + u32 pad, u64 streams_mask) +{ + struct max_des *des = priv->des; + struct v4l2_subdev_route *route; + unsigned long vc_ids_masks = 0; + unsigned int phy_id; + int ret; + + *num_remaps = 0; + + if (context->tunnel_enable) + return 0; + + for_each_active_route(routing, route) { + struct v4l2_mbus_frame_desc_entry entry; + struct max_des_phy *phy; + unsigned int src_vc_id, dst_vc_id; + + if (pad != route->sink_pad) + continue; + + if (!(BIT_ULL(route->sink_stream) & streams_mask)) + continue; + + if (*num_remaps + 1 > des->ops->num_remaps_per_pipe) { + dev_err(priv->dev, "Too many streams for pipe %u\n", + pipe->index); + return -E2BIG; + } + + phy = max_des_pad_to_phy(des, route->source_pad); + if (!phy) { + dev_err(priv->dev, "Failed to find PHY for pad %u\n", + route->source_pad); + return -ENOENT; + } + + ret = max_get_fd_stream_entry(source->sd, source->pad, + route->sink_stream, &entry); + if (ret) { + dev_err(priv->dev, + "Failed to find frame desc entry for stream %u:%u: %d\n", + route->sink_pad, route->sink_stream, ret); + return ret; + } + + src_vc_id = entry.bus.csi2.vc; + vc_ids_masks |= BIT(src_vc_id); + + ret = max_des_map_src_dst_vc_id(context, pipe->index, phy->index, + src_vc_id, &dst_vc_id); + if (ret) + return ret; + + ret = max_des_add_remap(remaps, num_remaps, phy->index, + src_vc_id, dst_vc_id, + entry.bus.csi2.dt); + if (ret) + return ret; + } + + for (phy_id = 0; phy_id < des->ops->num_phys; phy_id++) { + unsigned long mask = context->vc_ids_masks[pipe->index][phy_id]; + unsigned int src_vc_id; + + for_each_set_bit(src_vc_id, &mask, MAX_SERDES_VC_ID_NUM) { + unsigned int dst_vc_id; + + if (!(vc_ids_masks & BIT(src_vc_id))) + continue; + + if (*num_remaps + 2 > des->ops->num_remaps_per_pipe) { + dev_err(priv->dev, "Too many streams for pipe %u\n", + pipe->index); + return -E2BIG; + } + + ret = max_des_map_src_dst_vc_id(context, pipe->index, phy_id, + src_vc_id, &dst_vc_id); + if (ret) + return ret; + + ret = max_des_add_remap(remaps, num_remaps, phy_id, + src_vc_id, dst_vc_id, + MIPI_CSI2_DT_FS); + if (ret) + return ret; + + ret = max_des_add_remap(remaps, num_remaps, phy_id, + src_vc_id, dst_vc_id, + MIPI_CSI2_DT_FE); + if (ret) + return ret; + } + } + + return 0; +} + +static int max_des_update_pipe(struct max_des_priv *priv, + struct max_des_remap_context *context, + struct max_source *source, + struct max_des_pipe *pipe, + const struct v4l2_subdev_krouting *routing, + u32 pad, u64 streams_mask) +{ + struct max_des *des = priv->des; + struct max_des_remap *remaps; + unsigned int num_remaps; + int ret; + + remaps = devm_kcalloc(priv->dev, des->ops->num_remaps_per_pipe, + sizeof(*remaps), GFP_KERNEL); + if (!remaps) + return -ENOMEM; + + ret = max_des_get_pipe_remaps(priv, context, pipe, source, remaps, + &num_remaps, routing, pad, streams_mask); + if (ret) + goto err_free_new_remaps; + + ret = max_des_set_pipe_remaps(priv, pipe, remaps, num_remaps); + if (ret) + goto err_free_new_remaps; + + if (pipe->remaps) + devm_kfree(priv->dev, pipe->remaps); + + pipe->remaps = remaps; + pipe->num_remaps = num_remaps; + + return 0; + +err_free_new_remaps: + devm_kfree(priv->dev, remaps); + + return ret; +} + +static int max_des_init_link_ser_xlate(struct max_des_priv *priv, + struct max_des_link *link, + struct i2c_adapter *adapter, + u8 power_up_addr, u8 new_addr) +{ + struct max_des *des = priv->des; + u8 addrs[] = { power_up_addr, new_addr }; + u8 current_addr; + int ret; + + ret = des->ops->select_links(des, BIT(link->index)); + if (ret) + return ret; + + ret = max_ser_wait_for_multiple(adapter, addrs, ARRAY_SIZE(addrs), + ¤t_addr); + if (ret) { + dev_err(priv->dev, + "Failed to wait for serializer at 0x%02x or 0x%02x: %d\n", + power_up_addr, new_addr, ret); + return ret; + } + + ret = max_ser_reset(adapter, current_addr); + if (ret) { + dev_err(priv->dev, "Failed to reset serializer: %d\n", ret); + return ret; + } + + ret = max_ser_wait(adapter, power_up_addr); + if (ret) { + dev_err(priv->dev, + "Failed to wait for serializer at 0x%02x: %d\n", + power_up_addr, ret); + return ret; + } + + ret = max_ser_change_address(adapter, power_up_addr, new_addr); + if (ret) { + dev_err(priv->dev, + "Failed to change serializer from 0x%02x to 0x%02x: %d\n", + power_up_addr, new_addr, ret); + return ret; + } + + ret = max_ser_wait(adapter, new_addr); + if (ret) { + dev_err(priv->dev, + "Failed to wait for serializer at 0x%02x: %d\n", + new_addr, ret); + return ret; + } + + if (des->ops->fix_tx_ids) { + ret = max_ser_fix_tx_ids(adapter, new_addr); + if (ret) + return ret; + } + + return ret; +} + +static int max_des_init(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + unsigned int i; + int ret; + + ret = des->ops->init(des); + if (ret) + return ret; + + ret = des->ops->set_enable(des, false); + if (ret) + return ret; + + for (i = 0; i < des->ops->num_phys; i++) { + struct max_des_phy *phy = &des->phys[i]; + + if (phy->enabled) { + ret = des->ops->init_phy(des, phy); + if (ret) + return ret; + } + + ret = des->ops->set_phy_active(des, phy, false); + if (ret) + return ret; + } + + for (i = 0; i < des->ops->num_pipes; i++) { + struct max_des_pipe *pipe = &des->pipes[i]; + + ret = des->ops->set_pipe_enable(des, pipe, false); + if (ret) + return ret; + + if (des->ops->set_pipe_tunnel_enable) { + ret = des->ops->set_pipe_tunnel_enable(des, pipe, false); + if (ret) + return ret; + } + + ret = des->ops->set_pipe_stream_id(des, pipe, pipe->stream_id); + if (ret) + return ret; + + ret = max_des_set_pipe_remaps(priv, pipe, pipe->remaps, + pipe->num_remaps); + if (ret) + return ret; + } + + if (!des->ops->init_link) + return 0; + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + + if (!link->enabled) + continue; + + ret = des->ops->init_link(des, link); + if (ret) + return ret; + } + + return 0; +} + +static int max_des_ser_atr_attach_addr(struct i2c_atr *atr, u32 chan_id, + u16 addr, u16 alias) +{ + struct max_des_priv *priv = i2c_atr_get_driver_data(atr); + struct max_des *des = priv->des; + struct max_des_link *link = &des->links[chan_id]; + unsigned int i; + int ret; + + if (link->ser_xlate.en) { + dev_err(priv->dev, "Serializer for link %u already bound\n", + link->index); + return -EINVAL; + } + + for (i = MAX_GMSL_MAX; i >= MAX_GMSL_MIN; i--) { + if (!(priv->versions & BIT(i))) + continue; + + if (des->ops->select_link_version) { + ret = des->ops->select_link_version(des, link, i); + if (ret) + return ret; + } + + ret = max_des_init_link_ser_xlate(priv, link, priv->client->adapter, + addr, alias); + if (!ret) + break; + } + + if (ret) { + dev_err(priv->dev, "Cannot find serializer for link %u\n", + link->index); + return -ENOENT; + } + + link->version = i; + link->ser_xlate.src = alias; + link->ser_xlate.dst = addr; + link->ser_xlate.en = true; + + return 0; +} + +static void max_des_ser_atr_detach_addr(struct i2c_atr *atr, u32 chan_id, u16 addr) +{ + /* Don't do anything. */ +} + +static const struct i2c_atr_ops max_des_i2c_atr_ops = { + .attach_addr = max_des_ser_atr_attach_addr, + .detach_addr = max_des_ser_atr_detach_addr, +}; + +static void max_des_i2c_atr_deinit(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + unsigned int i; + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + + /* Deleting adapters that haven't been added does no harm. */ + i2c_atr_del_adapter(priv->atr, link->index); + } + + i2c_atr_delete(priv->atr); +} + +static int max_des_i2c_atr_init(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + unsigned int mask = 0; + unsigned int i; + int ret; + + if (!i2c_check_functionality(priv->client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -ENODEV; + + priv->atr = i2c_atr_new(priv->client->adapter, priv->dev, + &max_des_i2c_atr_ops, des->ops->num_links, + I2C_ATR_F_STATIC | I2C_ATR_F_PASSTHROUGH); + if (IS_ERR(priv->atr)) + return PTR_ERR(priv->atr); + + i2c_atr_set_driver_data(priv->atr, priv); + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + struct i2c_atr_adap_desc desc = { + .chan_id = i, + }; + + if (!link->enabled) + continue; + + ret = i2c_atr_add_adapter(priv->atr, &desc); + if (ret) + goto err_add_adapters; + } + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + + if (!link->enabled) + continue; + + mask |= BIT(link->index); + } + + return des->ops->select_links(des, mask); + +err_add_adapters: + max_des_i2c_atr_deinit(priv); + + return ret; +} + +static void max_des_i2c_mux_deinit(struct max_des_priv *priv) +{ + i2c_mux_del_adapters(priv->mux); +} + +static int max_des_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan) +{ + struct max_des_priv *priv = i2c_mux_priv(muxc); + struct max_des *des = priv->des; + + if (!des->ops->select_links) + return 0; + + return des->ops->select_links(des, BIT(chan)); +} + +static int max_des_i2c_mux_init(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + u32 flags = I2C_MUX_LOCKED; + unsigned int i; + int ret; + + if (des->ops->num_links == 1) + flags |= I2C_MUX_GATE; + + priv->mux = i2c_mux_alloc(priv->client->adapter, priv->dev, + des->ops->num_links, 0, flags, + max_des_i2c_mux_select, NULL); + if (!priv->mux) + return -ENOMEM; + + priv->mux->priv = priv; + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + + if (!link->enabled) + continue; + + ret = i2c_mux_add_adapter(priv->mux, 0, i); + if (ret) + goto err_add_adapters; + } + + return 0; + +err_add_adapters: + i2c_mux_del_adapters(priv->mux); + + return ret; +} + +static void max_des_i2c_adapter_deinit(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + + if (des->ops->select_resets_link) + return max_des_i2c_atr_deinit(priv); + else + return max_des_i2c_mux_deinit(priv); +} + +static int max_des_i2c_adapter_init(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + + if (des->ops->select_resets_link) + return max_des_i2c_atr_init(priv); + else + return max_des_i2c_mux_init(priv); + + return 0; +} + +static int max_des_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *format) +{ + struct max_des_priv *priv = v4l2_get_subdevdata(sd); + struct max_des *des = priv->des; + struct v4l2_mbus_framefmt *fmt; + + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && des->active) + return -EBUSY; + + /* No transcoding, source and sink formats must match. */ + if (max_des_pad_is_source(des, format->pad)) + return v4l2_subdev_get_fmt(sd, state, format); + + fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream); + if (!fmt) + return -EINVAL; + + *fmt = format->format; + + fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, + format->stream); + if (!fmt) + return -EINVAL; + + *fmt = format->format; + + return 0; +} + +static int max_des_log_status(struct v4l2_subdev *sd) +{ + struct max_des_priv *priv = v4l2_get_subdevdata(sd); + struct max_des *des = priv->des; + unsigned int i, j; + int ret; + + v4l2_info(sd, "active: %u\n", des->active); + v4l2_info(sd, "tunnel: %u", des->tunnel); + if (des->ops->log_status) { + ret = des->ops->log_status(des, sd->name); + if (ret) + return ret; + } + v4l2_info(sd, "\n"); + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + + v4l2_info(sd, "link: %u\n", link->index); + v4l2_info(sd, "\tenabled: %u\n", link->enabled); + + if (!link->enabled) { + v4l2_info(sd, "\n"); + continue; + } + + v4l2_info(sd, "\tversion: %u\n", link->version); + v4l2_info(sd, "\tser_xlate: en: %u, src: 0x%02x dst: 0x%02x\n", + link->ser_xlate.en, link->ser_xlate.src, + link->ser_xlate.dst); + v4l2_info(sd, "\n"); + } + + for (i = 0; i < des->ops->num_pipes; i++) { + struct max_des_pipe *pipe = &des->pipes[i]; + + v4l2_info(sd, "pipe: %u\n", pipe->index); + v4l2_info(sd, "\tenabled: %u\n", pipe->enabled); + if (pipe->phy_id == des->ops->num_phys) + v4l2_info(sd, "\tphy_id: invalid\n"); + else + v4l2_info(sd, "\tphy_id: %u\n", pipe->phy_id); + v4l2_info(sd, "\tstream_id: %u\n", pipe->stream_id); + v4l2_info(sd, "\tlink_id: %u\n", pipe->link_id); + v4l2_info(sd, "\tdbl8: %u\n", pipe->mode.dbl8); + v4l2_info(sd, "\tdbl8mode: %u\n", pipe->mode.dbl8mode); + v4l2_info(sd, "\tdbl10: %u\n", pipe->mode.dbl10); + v4l2_info(sd, "\tdbl10mode: %u\n", pipe->mode.dbl10mode); + v4l2_info(sd, "\tdbl12: %u\n", pipe->mode.dbl12); + v4l2_info(sd, "\tremaps: %u\n", pipe->num_remaps); + for (j = 0; j < pipe->num_remaps; j++) { + struct max_des_remap *remap = &pipe->remaps[j]; + + v4l2_info(sd, "\t\tremap: from: vc: %u, dt: 0x%02x\n", + remap->from_vc, remap->from_dt); + v4l2_info(sd, "\t\t to: vc: %u, dt: 0x%02x, phy: %u\n", + remap->to_vc, remap->to_dt, remap->phy); + } + if (des->ops->log_pipe_status) { + ret = des->ops->log_pipe_status(des, pipe, sd->name); + if (ret) + return ret; + } + v4l2_info(sd, "\n"); + } + + for (i = 0; i < des->ops->num_phys; i++) { + struct max_des_phy *phy = &des->phys[i]; + + v4l2_info(sd, "phy: %u\n", phy->index); + v4l2_info(sd, "\tenabled: %u\n", phy->enabled); + + if (!phy->enabled) { + v4l2_info(sd, "\n"); + continue; + } + + v4l2_info(sd, "\tactive: %u\n", phy->active); + v4l2_info(sd, "\tlink_frequency: %llu\n", phy->link_frequency); + v4l2_info(sd, "\tnum_data_lanes: %u\n", phy->mipi.num_data_lanes); + v4l2_info(sd, "\tclock_lane: %u\n", phy->mipi.clock_lane); + v4l2_info(sd, "\talt_mem_map8: %u\n", phy->mode.alt_mem_map8); + v4l2_info(sd, "\talt2_mem_map8: %u\n", phy->mode.alt2_mem_map8); + v4l2_info(sd, "\talt_mem_map10: %u\n", phy->mode.alt_mem_map10); + v4l2_info(sd, "\talt_mem_map12: %u\n", phy->mode.alt_mem_map12); + if (des->ops->log_phy_status) { + ret = des->ops->log_phy_status(des, phy, sd->name); + if (ret) + return ret; + } + v4l2_info(sd, "\n"); + } + + return 0; +} + +static int max_des_get_frame_desc_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_mbus_frame_desc *fd, + unsigned int pad) +{ + struct max_des_remap_context context = { 0 }; + struct max_des_priv *priv = sd_to_priv(sd); + struct max_des *des = priv->des; + struct v4l2_subdev_route *route; + struct max_des_phy *phy; + int ret; + + phy = max_des_pad_to_phy(des, pad); + if (!phy) { + dev_err(priv->dev, "Failed to find PHY for pad %u\n", pad); + return -ENOENT; + } + + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + + ret = max_des_populate_remap_context(priv, &context, &state->routing); + if (ret) + return ret; + + for_each_active_route(&state->routing, route) { + struct v4l2_mbus_frame_desc_entry entry; + struct max_source *source; + struct max_des_link *link; + struct max_des_pipe *pipe; + unsigned int dst_vc_id; + + if (pad != route->source_pad) + continue; + + link = max_des_pad_to_link(des, route->sink_pad); + if (!link) { + dev_err(priv->dev, "Failed to find link for pad %u\n", + route->sink_pad); + return -ENOENT; + } + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + if (!source->sd) + continue; + + ret = max_get_fd_stream_entry(source->sd, source->pad, + route->sink_stream, &entry); + if (ret) { + dev_err(priv->dev, + "Failed to find frame desc entry for stream %u:%u: %d\n", + route->sink_pad, route->sink_stream, ret); + return ret; + } + + ret = max_des_map_src_dst_vc_id(&context, pipe->index, phy->index, + entry.bus.csi2.vc, &dst_vc_id); + if (ret) + return ret; + + entry.bus.csi2.vc = dst_vc_id; + entry.stream = route->source_stream; + + fd->entry[fd->num_entries++] = entry; + } + + return 0; +} + +static int max_des_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_frame_desc *fd) +{ + struct max_des_priv *priv = sd_to_priv(sd); + struct v4l2_subdev_state *state; + int ret; + + state = v4l2_subdev_lock_and_get_active_state(&priv->sd); + + ret = max_des_get_frame_desc_state(sd, state, fd, pad); + + v4l2_subdev_unlock_state(state); + + return ret; +} + +static int max_des_get_mbus_config(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_config *cfg) +{ + struct max_des_priv *priv = sd_to_priv(sd); + struct max_des *des = priv->des; + struct max_des_phy *phy; + + phy = max_des_pad_to_phy(des, pad); + if (!phy) + return -EINVAL; + + cfg->type = phy->bus_type; + cfg->bus.mipi_csi2 = phy->mipi; + cfg->link_freq = phy->link_frequency; + + return 0; +} + +static int max_des_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + enum v4l2_subdev_format_whence which, + struct v4l2_subdev_krouting *routing) +{ + struct max_des_priv *priv = sd_to_priv(sd); + struct max_des *des = priv->des; + int ret; + + if (which == V4L2_SUBDEV_FORMAT_ACTIVE && des->active) + return -EBUSY; + + /* + * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until + * frame desc is made dynamically allocated. + */ + + if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX) + return -E2BIG; + + ret = v4l2_subdev_routing_validate(sd, routing, + V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 | + V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX); + if (ret) + return ret; + + return v4l2_subdev_set_routing(sd, state, routing); +} + +static int max_des_update_link(struct max_des_priv *priv, + struct max_des_remap_context *context, + struct max_des_link *link, + const struct v4l2_subdev_krouting *routing, + u64 streams_mask) +{ + struct max_source *source; + struct max_des *des = priv->des; + u32 pad = max_des_link_to_pad(des, link); + bool enable_changed = !streams_mask != !priv->streams_masks[pad]; + bool enable = !!streams_mask; + struct max_des_pipe *pipe; + int ret; + + pipe = max_des_find_link_pipe(des, link); + if (!pipe) + return -ENOENT; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + if (!source->sd) + return 0; + + if (!enable && enable_changed) { + ret = max_des_set_pipe_enable(des, pipe, enable); + if (ret) + return ret; + } + + ret = max_des_update_pipe(priv, context, source, pipe, + routing, pad, streams_mask); + if (ret) + goto err_revert_pipe_disable; + + if (enable && enable_changed) { + ret = max_des_set_pipe_enable(des, pipe, enable); + if (ret) + goto err_revert_update_pipe; + } + + return 0; + +err_revert_update_pipe: + max_des_update_pipe(priv, context, source, pipe, + routing, pad, priv->streams_masks[pad]); + +err_revert_pipe_disable: + if (!enable && enable_changed) + max_des_set_pipe_enable(des, pipe, !enable); + + return ret; +} + +static int max_des_update_phy(struct max_des_priv *priv, + const struct v4l2_subdev_krouting *routing, + u32 pad, u64 *streams_masks) +{ + bool enable_changed = !streams_masks[pad] != !priv->streams_masks[pad]; + bool enable = !!streams_masks[pad]; + struct max_des *des = priv->des; + struct max_des_phy *phy; + int ret; + + phy = max_des_pad_to_phy(des, pad); + if (!phy) + return -EINVAL; + + if (enable_changed) { + ret = max_des_set_phy_active(des, phy, enable); + if (ret) + return ret; + } + + return 0; +} + +static int max_des_update_active(struct max_des_priv *priv, u64 *streams_masks, + bool expected_active) +{ + struct max_des *des = priv->des; + bool active = false; + unsigned int i; + int ret; + + for (i = 0; i < des->ops->num_phys; i++) { + struct max_des_phy *phy = &des->phys[i]; + u32 pad = max_des_phy_to_pad(des, phy); + + if (streams_masks[pad]) { + active = true; + break; + } + } + + if (active != expected_active || des->active == active) + return 0; + + ret = des->ops->set_enable(des, active); + if (ret) + return ret; + + des->active = active; + + return 0; +} + +static int max_des_update_links(struct max_des_priv *priv, + struct max_des_remap_context *context, + const struct v4l2_subdev_krouting *routing, + u64 *streams_masks) +{ + struct max_des *des = priv->des; + unsigned int failed_update_link_id = des->ops->num_links; + unsigned int i; + int ret; + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + u32 sink_pad = max_des_link_to_pad(des, link); + + ret = max_des_update_link(priv, context, link, routing, + streams_masks[sink_pad]); + if (ret) { + failed_update_link_id = i; + goto err; + } + } + + return 0; + +err: + for (i = 0; i < failed_update_link_id; i++) { + struct max_des_link *link = &des->links[i]; + u32 sink_pad = max_des_link_to_pad(des, link); + + max_des_update_link(priv, context, link, routing, + priv->streams_masks[sink_pad]); + } + + return ret; +} + +static int max_des_enable_disable_streams(struct max_des_priv *priv, + struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, + bool enable) +{ + struct max_des *des = priv->des; + + return max_xlate_enable_disable_streams(priv->sources, 0, state, + pad, updated_streams_mask, 0, + des->ops->num_links, enable); +} + +static int max_des_update_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, bool enable) +{ + struct max_des_priv *priv = v4l2_get_subdevdata(sd); + struct max_des_remap_context context = { 0 }; + struct max_des_mode_context mode_context = { 0 }; + struct max_des *des = priv->des; + unsigned int num_pads = max_des_num_pads(des); + u64 *streams_masks; + int ret; + + ret = max_des_populate_remap_context(priv, &context, &state->routing); + if (ret) + return ret; + + ret = max_des_populate_mode_context(priv, &mode_context, &state->routing); + if (ret) + return ret; + + ret = max_get_streams_masks(priv->dev, state, pad, updated_streams_mask, + num_pads, 0, des->ops->num_links, + priv->streams_masks, &streams_masks, enable); + if (ret) + return ret; + + ret = max_des_set_pipes_phy(priv, &context); + if (ret) + goto err_free_streams_masks; + + ret = max_des_set_tunnel(priv, &context); + if (ret) + goto err_free_streams_masks; + + ret = max_des_set_modes(priv, &mode_context); + if (ret) + goto err_free_streams_masks; + + if (!enable) { + ret = max_des_enable_disable_streams(priv, state, pad, + updated_streams_mask, enable); + if (ret) + goto err_free_streams_masks; + } + + ret = max_des_update_active(priv, streams_masks, false); + if (ret) + goto err_revert_streams_disable; + + ret = max_des_update_links(priv, &context, &state->routing, streams_masks); + if (ret) + goto err_revert_active_disable; + + ret = max_des_update_phy(priv, &state->routing, pad, streams_masks); + if (ret) + goto err_revert_links_update; + + ret = max_des_update_active(priv, streams_masks, true); + if (ret) + goto err_revert_phy_update; + + if (enable) { + ret = max_des_enable_disable_streams(priv, state, pad, + updated_streams_mask, enable); + if (ret) + goto err_revert_active_enable; + } + + devm_kfree(priv->dev, priv->streams_masks); + priv->streams_masks = streams_masks; + + return 0; + +err_revert_active_enable: + max_des_update_active(priv, priv->streams_masks, false); + +err_revert_phy_update: + max_des_update_phy(priv, &state->routing, pad, priv->streams_masks); + +err_revert_links_update: + max_des_update_links(priv, &context, &state->routing, priv->streams_masks); + +err_revert_active_disable: + max_des_update_active(priv, priv->streams_masks, true); + +err_revert_streams_disable: + if (!enable) + max_des_enable_disable_streams(priv, state, pad, + updated_streams_mask, !enable); + +err_free_streams_masks: + devm_kfree(priv->dev, streams_masks); + + return ret; +} + +static int max_des_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + return max_des_update_streams(sd, state, pad, streams_mask, true); +} + +static int max_des_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + return max_des_update_streams(sd, state, pad, streams_mask, false); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int max_des_g_register(struct v4l2_subdev *sd, + struct v4l2_dbg_register *reg) +{ + struct max_des_priv *priv = v4l2_get_subdevdata(sd); + struct max_des *des = priv->des; + unsigned int val; + int ret; + + ret = des->ops->reg_read(des, reg->reg, &val); + if (ret) + return ret; + + reg->val = val; + reg->size = 1; + + return 0; +} + +static int max_des_s_register(struct v4l2_subdev *sd, + const struct v4l2_dbg_register *reg) +{ + struct max_des_priv *priv = v4l2_get_subdevdata(sd); + struct max_des *des = priv->des; + + return des->ops->reg_write(des, reg->reg, reg->val); +} +#endif + +static const struct v4l2_subdev_core_ops max_des_core_ops = { + .log_status = max_des_log_status, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = max_des_g_register, + .s_register = max_des_s_register, +#endif +}; + +static const struct v4l2_subdev_pad_ops max_des_pad_ops = { + .enable_streams = max_des_enable_streams, + .disable_streams = max_des_disable_streams, + + .set_routing = max_des_set_routing, + .get_frame_desc = max_des_get_frame_desc, + + .get_mbus_config = max_des_get_mbus_config, + + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = max_des_set_fmt, +}; + +static const struct v4l2_subdev_ops max_des_subdev_ops = { + .core = &max_des_core_ops, + .pad = &max_des_pad_ops, +}; + +static const struct media_entity_operations max_des_media_ops = { + .link_validate = v4l2_subdev_link_validate, + .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1, +}; + +static int max_des_notify_bound(struct v4l2_async_notifier *nf, + struct v4l2_subdev *subdev, + struct v4l2_async_connection *base_asc) +{ + struct max_des_priv *priv = nf_to_priv(nf); + struct max_asc *asc = asc_to_max(base_asc); + struct max_source *source = asc->source; + struct max_des *des = priv->des; + struct max_des_link *link = &des->links[source->index]; + u32 pad = max_des_link_to_pad(des, link); + int ret; + + ret = media_entity_get_fwnode_pad(&subdev->entity, + source->ep_fwnode, + MEDIA_PAD_FL_SOURCE); + if (ret < 0) { + dev_err(priv->dev, "Failed to find pad for %s\n", subdev->name); + return ret; + } + + source->sd = subdev; + source->pad = ret; + + ret = media_create_pad_link(&source->sd->entity, source->pad, + &priv->sd.entity, pad, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret) { + dev_err(priv->dev, "Unable to link %s:%u -> %s:%u\n", + source->sd->name, source->pad, priv->sd.name, pad); + return ret; + } + + return 0; +} + +static void max_des_notify_unbind(struct v4l2_async_notifier *nf, + struct v4l2_subdev *subdev, + struct v4l2_async_connection *base_asc) +{ + struct max_asc *asc = asc_to_max(base_asc); + struct max_source *source = asc->source; + + source->sd = NULL; +} + +static const struct v4l2_async_notifier_operations max_des_notify_ops = { + .bound = max_des_notify_bound, + .unbind = max_des_notify_unbind, +}; + +static int max_des_v4l2_notifier_register(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + unsigned int i; + int ret; + + v4l2_async_subdev_nf_init(&priv->nf, &priv->sd); + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + struct max_source *source; + struct max_asc *asc; + + if (!link->enabled) + continue; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + if (!source->ep_fwnode) + continue; + + asc = v4l2_async_nf_add_fwnode(&priv->nf, source->ep_fwnode, + struct max_asc); + if (IS_ERR(asc)) { + dev_err(priv->dev, + "Failed to add subdev for source %u: %pe", i, + asc); + + v4l2_async_nf_cleanup(&priv->nf); + + return PTR_ERR(asc); + } + + asc->source = source; + } + + priv->nf.ops = &max_des_notify_ops; + + ret = v4l2_async_nf_register(&priv->nf); + if (ret) { + dev_err(priv->dev, "Failed to register subdev notifier"); + v4l2_async_nf_cleanup(&priv->nf); + return ret; + } + + return 0; +} + +static void max_des_v4l2_notifier_unregister(struct max_des_priv *priv) +{ + v4l2_async_nf_unregister(&priv->nf); + v4l2_async_nf_cleanup(&priv->nf); +} + +static int max_des_v4l2_register(struct max_des_priv *priv) +{ + struct v4l2_subdev *sd = &priv->sd; + struct max_des *des = priv->des; + void *data = i2c_get_clientdata(priv->client); + unsigned int num_pads = max_des_num_pads(des); + unsigned int i; + int ret; + + v4l2_i2c_subdev_init(sd, priv->client, &max_des_subdev_ops); + i2c_set_clientdata(priv->client, data); + sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + sd->entity.ops = &max_des_media_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS; + + for (i = 0; i < num_pads; i++) { + if (max_des_pad_is_sink(des, i)) + priv->pads[i].flags = MEDIA_PAD_FL_SINK; + else + priv->pads[i].flags = MEDIA_PAD_FL_SOURCE; + } + + v4l2_set_subdevdata(sd, priv); + + ret = media_entity_pads_init(&sd->entity, num_pads, priv->pads); + if (ret) + return ret; + + ret = max_des_v4l2_notifier_register(priv); + if (ret) + goto err_media_entity_cleanup; + + ret = v4l2_subdev_init_finalize(sd); + if (ret) + goto err_nf_cleanup; + + ret = v4l2_async_register_subdev(sd); + if (ret) + goto err_sd_cleanup; + + return 0; + +err_sd_cleanup: + v4l2_subdev_cleanup(sd); +err_nf_cleanup: + max_des_v4l2_notifier_unregister(priv); +err_media_entity_cleanup: + media_entity_cleanup(&sd->entity); + + return ret; +} + +static void max_des_v4l2_unregister(struct max_des_priv *priv) +{ + struct v4l2_subdev *sd = &priv->sd; + + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); + max_des_v4l2_notifier_unregister(priv); + media_entity_cleanup(&sd->entity); +} + +static int max_des_update_pocs(struct max_des_priv *priv, bool enable) +{ + struct max_des *des = priv->des; + unsigned int i; + int ret; + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + unsigned int index = link->index; + + if (!link->enabled) + continue; + + if (!priv->pocs) + continue; + + if (enable) + ret = regulator_enable(priv->pocs[index]); + else + ret = regulator_disable(priv->pocs[index]); + + if (ret) { + dev_err(priv->dev, + "Failed to set POC supply to %u: %u\n", + enable, ret); + return ret; + } + } + + return 0; +} + +static int max_des_parse_sink_dt_endpoint(struct max_des_priv *priv, + struct max_des_link *link, + struct max_source *source, + struct fwnode_handle *fwnode) +{ + struct max_des *des = priv->des; + u32 pad = max_des_link_to_pad(des, link); + unsigned int index = link->index; + struct fwnode_handle *ep; + char poc_name[10]; + int ret; + + ep = fwnode_graph_get_endpoint_by_id(fwnode, pad, 0, 0); + if (!ep) + return 0; + + source->ep_fwnode = fwnode_graph_get_remote_endpoint(ep); + fwnode_handle_put(ep); + if (!source->ep_fwnode) { + dev_err(priv->dev, + "Failed to get remote endpoint on port %u\n", pad); + return -ENODEV; + } + + snprintf(poc_name, sizeof(poc_name), "port%u-poc", index); + priv->pocs[index] = devm_regulator_get_optional(priv->dev, poc_name); + if (IS_ERR(priv->pocs[index])) { + ret = PTR_ERR(priv->pocs[index]); + if (ret != -ENODEV) { + dev_err(priv->dev, + "Failed to get POC supply on port %u: %d\n", + index, ret); + goto err_put_source_ep_fwnode; + } + + priv->pocs[index] = NULL; + } + + link->enabled = true; + + return 0; + +err_put_source_ep_fwnode: + fwnode_handle_put(source->ep_fwnode); + + return ret; +} + +static int max_des_parse_src_dt_endpoint(struct max_des_priv *priv, + struct max_des_phy *phy, + struct fwnode_handle *fwnode) +{ + struct max_des *des = priv->des; + u32 pad = max_des_phy_to_pad(des, phy); + struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = V4L2_MBUS_UNKNOWN }; + struct v4l2_mbus_config_mipi_csi2 *mipi = &v4l2_ep.bus.mipi_csi2; + enum v4l2_mbus_type bus_type; + struct fwnode_handle *ep; + u64 link_frequency; + unsigned int i; + int ret; + + ep = fwnode_graph_get_endpoint_by_id(fwnode, pad, 0, 0); + if (!ep) + return 0; + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &v4l2_ep); + fwnode_handle_put(ep); + if (ret) { + dev_err(priv->dev, "Could not parse endpoint on port %u\n", pad); + return ret; + } + + bus_type = v4l2_ep.bus_type; + if (bus_type != V4L2_MBUS_CSI2_DPHY && + bus_type != V4L2_MBUS_CSI2_CPHY) { + v4l2_fwnode_endpoint_free(&v4l2_ep); + dev_err(priv->dev, "Unsupported bus-type %u on port %u\n", + pad, bus_type); + return -EINVAL; + } + + ret = 0; + if (v4l2_ep.nr_of_link_frequencies == 0) + link_frequency = MAX_DES_LINK_FREQUENCY_DEFAULT; + else if (v4l2_ep.nr_of_link_frequencies == 1) + link_frequency = v4l2_ep.link_frequencies[0]; + else + ret = -EINVAL; + + v4l2_fwnode_endpoint_free(&v4l2_ep); + + if (ret) { + dev_err(priv->dev, "Invalid link frequencies %u on port %u\n", + v4l2_ep.nr_of_link_frequencies, pad); + return -EINVAL; + } + + if (link_frequency < MAX_DES_LINK_FREQUENCY_MIN || + link_frequency > MAX_DES_LINK_FREQUENCY_MAX) { + dev_err(priv->dev, "Invalid link frequency %llu on port %u\n", + link_frequency, pad); + return -EINVAL; + } + + for (i = 0; i < mipi->num_data_lanes; i++) { + if (mipi->data_lanes[i] > mipi->num_data_lanes) { + dev_err(priv->dev, "Invalid data lane %u on port %u\n", + mipi->data_lanes[i], pad); + return -EINVAL; + } + } + + phy->bus_type = bus_type; + phy->mipi = *mipi; + phy->link_frequency = link_frequency; + phy->enabled = true; + + return 0; +} + +int max_des_phy_hw_data_lanes(struct max_des *des, struct max_des_phy *phy) +{ + const struct max_phys_configs *configs = &des->ops->phys_configs; + const struct max_phys_config *config = &configs->configs[des->phys_config]; + + return config->lanes[phy->index]; +} +EXPORT_SYMBOL(max_des_phy_hw_data_lanes); + +static int max_des_find_phys_config(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + const struct max_phys_configs *configs = &des->ops->phys_configs; + struct max_des_phy *phy; + unsigned int i, j; + + if (!configs->num_configs) + return 0; + + for (i = 0; i < configs->num_configs; i++) { + const struct max_phys_config *config = &configs->configs[i]; + bool matching = true; + + for (j = 0; j < des->ops->num_phys; j++) { + phy = &des->phys[j]; + + if (!phy->enabled) + continue; + + if (phy->mipi.num_data_lanes <= config->lanes[j] && + phy->mipi.clock_lane == config->clock_lane[j]) + continue; + + matching = false; + + break; + } + + if (matching) + break; + } + + if (i == configs->num_configs) { + dev_err(priv->dev, "Invalid lane configuration\n"); + return -EINVAL; + } + + des->phys_config = i; + + return 0; +} + +static int max_des_parse_dt(struct max_des_priv *priv) +{ + struct fwnode_handle *fwnode = dev_fwnode(priv->dev); + struct max_des *des = priv->des; + struct max_des_link *link; + struct max_des_pipe *pipe; + struct max_des_phy *phy; + unsigned int i; + int ret; + + for (i = 0; i < des->ops->num_phys; i++) { + phy = &des->phys[i]; + phy->index = i; + + ret = max_des_parse_src_dt_endpoint(priv, phy, fwnode); + if (ret) + return ret; + } + + ret = max_des_find_phys_config(priv); + if (ret) + return ret; + + /* Find an unsed PHY to send unampped data to. */ + for (i = 0; i < des->ops->num_phys; i++) { + phy = &des->phys[i]; + + if (!phy->enabled) { + priv->unused_phy = phy; + break; + } + } + + for (i = 0; i < des->ops->num_pipes; i++) { + pipe = &des->pipes[i]; + pipe->index = i; + + /* + * Serializers can send data on different stream ids over the + * same link, and some deserializers support stream id autoselect + * allowing them to receive data from all stream ids. + * Deserializers that support that feature should enable it. + * Others are limited to using just stream id 0 for now to + * prevent the routing from getting too complicated. + */ + pipe->stream_id = 0; + + /* + * We already checked that num_pipes >= num_links. + * Set up pipe to receive data from the link with the same index. + * This is already the default for most chips, and some of them + * don't even support receiving pipe data from a different link. + */ + pipe->link_id = i; + } + + for (i = 0; i < des->ops->num_links; i++) { + link = &des->links[i]; + link->index = i; + } + + for (i = 0; i < des->ops->num_links; i++) { + struct max_des_link *link = &des->links[i]; + struct max_source *source; + + source = max_des_find_link_source(priv, link); + if (!source) + return -ENOENT; + + source->index = i; + + ret = max_des_parse_sink_dt_endpoint(priv, link, source, fwnode); + if (ret) + return ret; + } + + return 0; +} + +static int max_des_allocate(struct max_des_priv *priv) +{ + struct max_des *des = priv->des; + unsigned int num_pads = max_des_num_pads(des); + + des->phys = devm_kcalloc(priv->dev, des->ops->num_phys, + sizeof(*des->phys), GFP_KERNEL); + if (!des->phys) + return -ENOMEM; + + des->pipes = devm_kcalloc(priv->dev, des->ops->num_pipes, + sizeof(*des->pipes), GFP_KERNEL); + if (!des->pipes) + return -ENOMEM; + + des->links = devm_kcalloc(priv->dev, des->ops->num_links, + sizeof(*des->links), GFP_KERNEL); + if (!des->links) + return -ENOMEM; + + priv->sources = devm_kcalloc(priv->dev, des->ops->num_links, + sizeof(*priv->sources), GFP_KERNEL); + if (!priv->sources) + return -ENOMEM; + + priv->pocs = devm_kcalloc(priv->dev, des->ops->num_links, + sizeof(*priv->pocs), GFP_KERNEL); + if (!priv->pocs) + return -ENOMEM; + + priv->pads = devm_kcalloc(priv->dev, num_pads, + sizeof(*priv->pads), GFP_KERNEL); + if (!priv->pads) + return -ENOMEM; + + priv->streams_masks = devm_kcalloc(priv->dev, num_pads, + sizeof(*priv->streams_masks), + GFP_KERNEL); + if (!priv->streams_masks) + return -ENOMEM; + + return 0; +} + +int max_des_probe(struct i2c_client *client, struct max_des *des) +{ + struct device *dev = &client->dev; + struct max_des_priv *priv; + int ret; + + if (des->ops->num_phys > MAX_DES_PHYS_NUM) + return -E2BIG; + + if (des->ops->num_pipes > MAX_DES_PIPES_NUM) + return -E2BIG; + + if (des->ops->num_links > des->ops->num_pipes) + return -E2BIG; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + if (des->ops->select_link_version && !des->ops->select_links) { + dev_err(dev, + "Cannot implement .select_link_version() without .select_links()\n"); + return -EINVAL; + } + + if (des->ops->select_link_version && !des->ops->select_resets_link) { + dev_err(dev, + "Cannot implement .select_link_version() without .select_resets_link\n"); + return -EINVAL; + } + + priv->versions = des->ops->versions; + if (!priv->versions) + priv->versions = BIT(MAX_GMSL_2); + + if (hweight_long(priv->versions) != 1 && + !des->ops->select_link_version) { + dev_err(dev, "Multiple version without .select_link_version()\n"); + return -EINVAL; + } + + priv->client = client; + priv->dev = dev; + priv->des = des; + des->priv = priv; + + ret = max_des_allocate(priv); + if (ret) + return ret; + + ret = max_des_parse_dt(priv); + if (ret) + return ret; + + ret = max_des_init(priv); + if (ret) + return ret; + + ret = max_des_update_pocs(priv, true); + if (ret) + return ret; + + ret = max_des_i2c_adapter_init(priv); + if (ret) + goto err_disable_pocs; + + ret = max_des_v4l2_register(priv); + if (ret) + goto err_i2c_adapter_deinit; + + return 0; + +err_i2c_adapter_deinit: + max_des_i2c_adapter_deinit(priv); + +err_disable_pocs: + max_des_update_pocs(priv, false); + + return ret; +} +EXPORT_SYMBOL_GPL(max_des_probe); + +int max_des_remove(struct max_des *des) +{ + struct max_des_priv *priv = des->priv; + + max_des_v4l2_unregister(priv); + + max_des_i2c_adapter_deinit(priv); + + max_des_update_pocs(priv, false); + + return 0; +} +EXPORT_SYMBOL_GPL(max_des_remove); + +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("I2C_ATR"); diff --git a/drivers/media/i2c/maxim-serdes/max_des.h b/drivers/media/i2c/maxim-serdes/max_des.h new file mode 100644 index 000000000000..3ce16d03a8a3 --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max_des.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2025 Analog Devices Inc. + */ + +#ifndef MAX_DES_H +#define MAX_DES_H + +#include + +#include "max_serdes.h" + +#define MAX_DES_DT_VC(dt, vc) (((vc) & 0x3) << 6 | ((dt) & 0x3f)) + +struct max_des_remap { + u8 from_dt; + u8 from_vc; + u8 to_dt; + u8 to_vc; + u8 phy; +}; + +struct max_des_link { + unsigned int index; + bool enabled; + enum max_gmsl_version version; + struct max_i2c_xlate ser_xlate; +}; + +struct max_des_pipe_mode { + bool dbl8; + bool dbl10; + bool dbl12; + bool dbl8mode; + bool dbl10mode; +}; + +struct max_des_pipe { + unsigned int index; + unsigned int stream_id; + unsigned int link_id; + unsigned int phy_id; + struct max_des_remap *remaps; + unsigned int num_remaps; + struct max_des_pipe_mode mode; + bool enabled; +}; + +struct max_des_phy_mode { + bool alt_mem_map8; + bool alt2_mem_map8; + bool alt_mem_map10; + bool alt_mem_map12; +}; + +struct max_des_phy { + unsigned int index; + s64 link_frequency; + struct v4l2_mbus_config_mipi_csi2 mipi; + enum v4l2_mbus_type bus_type; + struct max_des_phy_mode mode; + bool enabled; + bool active; +}; + +struct max_des; + +struct max_des_ops { + unsigned int num_phys; + unsigned int num_pipes; + unsigned int num_links; + unsigned int num_remaps_per_pipe; + unsigned int versions; + bool fix_tx_ids; + bool select_resets_link; + + struct max_phys_configs phys_configs; + + int (*reg_read)(struct max_des *des, unsigned int reg, unsigned int *val); + int (*reg_write)(struct max_des *des, unsigned int reg, unsigned int val); + int (*log_status)(struct max_des *des, const char *name); + int (*log_pipe_status)(struct max_des *des, struct max_des_pipe *pipe, + const char *name); + int (*log_phy_status)(struct max_des *des, struct max_des_phy *phy, + const char *name); + int (*set_enable)(struct max_des *des, bool enable); + int (*init)(struct max_des *des); + int (*init_phy)(struct max_des *des, struct max_des_phy *phy); + int (*set_phy_mode)(struct max_des *des, struct max_des_phy *phy, + struct max_des_phy_mode *mode); + int (*set_phy_active)(struct max_des *des, struct max_des_phy *phy, + bool active); + int (*set_pipe_stream_id)(struct max_des *des, struct max_des_pipe *pipe, + unsigned int stream_id); + int (*set_pipe_phy)(struct max_des *des, struct max_des_pipe *pipe, + struct max_des_phy *phy); + int (*set_pipe_enable)(struct max_des *des, struct max_des_pipe *pipe, + bool enable); + int (*set_pipe_remap)(struct max_des *des, struct max_des_pipe *pipe, + unsigned int i, struct max_des_remap *remap); + int (*set_pipe_remaps_enable)(struct max_des *des, struct max_des_pipe *pipe, + unsigned int mask); + int (*set_pipe_mode)(struct max_des *des, struct max_des_pipe *pipe, + struct max_des_pipe_mode *mode); + int (*set_pipe_tunnel_enable)(struct max_des *des, struct max_des_pipe *pipe, + bool enable); + int (*init_link)(struct max_des *des, struct max_des_link *link); + int (*select_links)(struct max_des *des, unsigned int mask); + int (*select_link_version)(struct max_des *des, struct max_des_link *link, + enum max_gmsl_version version); +}; + +struct max_des_priv; + +struct max_des { + struct max_des_priv *priv; + + const struct max_des_ops *ops; + + struct max_des_phy *phys; + struct max_des_pipe *pipes; + struct max_des_link *links; + + unsigned int phys_config; + bool tunnel; + bool active; +}; + +int max_des_probe(struct i2c_client *client, struct max_des *des); + +int max_des_remove(struct max_des *des); + +int max_des_phy_hw_data_lanes(struct max_des *des, struct max_des_phy *phy); + +#endif // MAX_DES_H diff --git a/drivers/media/i2c/maxim-serdes/max_ser.c b/drivers/media/i2c/maxim-serdes/max_ser.c new file mode 100644 index 000000000000..5302ff8da25c --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max_ser.c @@ -0,0 +1,1584 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Maxim GMSL2 Serializer Driver + * + * Copyright (C) 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "max_ser.h" +#include "max_serdes.h" + +#define MAX_SER_NUM_LINKS 1 + +struct max_ser_priv { + struct max_ser *ser; + struct device *dev; + struct i2c_client *client; + + struct i2c_atr *atr; + struct i2c_mux_core *mux; + + struct media_pad *pads; + struct max_source *sources; + u64 *streams_masks; + u32 double_bpps; + + struct v4l2_subdev sd; + struct v4l2_async_notifier nf; +}; + +static inline struct max_ser_priv *sd_to_priv(struct v4l2_subdev *sd) +{ + return container_of(sd, struct max_ser_priv, sd); +} + +static inline struct max_ser_priv *nf_to_priv(struct v4l2_async_notifier *nf) +{ + return container_of(nf, struct max_ser_priv, nf); +} + +static inline bool max_ser_pad_is_sink(struct max_ser *ser, u32 pad) +{ + return pad < ser->ops->num_phys; +} + +static inline bool max_ser_pad_is_source(struct max_ser *ser, u32 pad) +{ + return pad >= ser->ops->num_phys; +} + +static inline unsigned int max_ser_phy_to_pad(struct max_ser *ser, + struct max_ser_phy *phy) +{ + return phy->index; +} + +static inline unsigned int max_ser_num_pads(struct max_ser *ser) +{ + return ser->ops->num_phys + MAX_SER_NUM_LINKS; +} + +static struct max_ser_phy *max_ser_pad_to_phy(struct max_ser *ser, u32 pad) +{ + if (!max_ser_pad_is_sink(ser, pad)) + return NULL; + + return &ser->phys[pad]; +} + +static struct max_ser_pipe * +max_ser_find_phy_pipe(struct max_ser *ser, struct max_ser_phy *phy) +{ + unsigned int i; + + for (i = 0; i < ser->ops->num_pipes; i++) { + struct max_ser_pipe *pipe = &ser->pipes[i]; + + if (pipe->phy_id == phy->index) + return pipe; + } + + return NULL; +} + +static struct max_source * +max_ser_find_phy_source(struct max_ser_priv *priv, struct max_ser_phy *phy) +{ + return &priv->sources[phy->index]; +} + +static int max_ser_phy_set_active(struct max_ser *ser, struct max_ser_phy *phy, + bool active) +{ + int ret; + + ret = ser->ops->set_phy_active(ser, phy, active); + if (ret) + return ret; + + phy->active = active; + + return 0; +} + +static int max_ser_set_pipe_enable(struct max_ser *ser, struct max_ser_pipe *pipe, + bool enable) +{ + int ret; + + ret = ser->ops->set_pipe_enable(ser, pipe, enable); + if (ret) + return ret; + + pipe->enabled = enable; + + return 0; +} + +static int max_ser_set_pipe_dts(struct max_ser_priv *priv, struct max_ser_pipe *pipe, + unsigned int *dts, unsigned int num_dts) +{ + struct max_ser *ser = priv->ser; + unsigned int i; + int ret; + + for (i = 0; i < num_dts; i++) { + ret = ser->ops->set_pipe_dt(ser, pipe, i, dts[i]); + if (ret) + return ret; + + ret = ser->ops->set_pipe_dt_en(ser, pipe, i, true); + if (ret) + return ret; + } + + if (num_dts == pipe->num_dts) + return 0; + + for (i = num_dts; i < ser->ops->num_dts_per_pipe; i++) { + ret = ser->ops->set_pipe_dt_en(ser, pipe, i, false); + if (ret) + return ret; + } + + return 0; +} + +static int max_ser_set_pipe_mode(struct max_ser_priv *priv, struct max_ser_pipe *pipe, + struct max_ser_pipe_mode *mode) +{ + struct max_ser *ser = priv->ser; + + if (mode->bpp == pipe->mode.bpp && + mode->soft_bpp == pipe->mode.soft_bpp && + mode->dbl8 == pipe->mode.dbl8 && + mode->dbl10 == pipe->mode.dbl10 && + mode->dbl12 == pipe->mode.dbl12) + return 0; + + return ser->ops->set_pipe_mode(ser, pipe, mode); +} + +static int max_ser_i2c_atr_attach_addr(struct i2c_atr *atr, u32 chan_id, + u16 addr, u16 alias) +{ + struct max_i2c_xlate xlate = { .src = alias, .dst = addr, .en = true }; + struct max_ser_priv *priv = i2c_atr_get_driver_data(atr); + struct max_ser *ser = priv->ser; + unsigned int i; + int ret; + + for (i = 0; i < ser->ops->num_i2c_xlates; i++) + if (!ser->i2c_xlates[i].en) + break; + + if (i == ser->ops->num_i2c_xlates) { + dev_err(priv->dev, + "Reached maximum number of I2C translations\n"); + return -EINVAL; + } + + ret = ser->ops->set_i2c_xlate(ser, i, &xlate); + if (ret) + return ret; + + ser->i2c_xlates[i] = xlate; + + return 0; +} + +static void max_ser_i2c_atr_detach_addr(struct i2c_atr *atr, u32 chan_id, u16 addr) +{ + struct max_ser_priv *priv = i2c_atr_get_driver_data(atr); + struct max_ser *ser = priv->ser; + struct max_i2c_xlate xlate = { 0 }; + unsigned int i; + + /* Find index of matching I2C translation. */ + for (i = 0; i < ser->ops->num_i2c_xlates; i++) + if (ser->i2c_xlates[i].dst == addr) + break; + + WARN_ON(i == ser->ops->num_i2c_xlates); + + ser->ops->set_i2c_xlate(ser, i, &xlate); + ser->i2c_xlates[i] = xlate; +} + +static const struct i2c_atr_ops max_ser_i2c_atr_ops = { + .attach_addr = max_ser_i2c_atr_attach_addr, + .detach_addr = max_ser_i2c_atr_detach_addr, +}; + +static void max_ser_i2c_atr_deinit(struct max_ser_priv *priv) +{ + /* Deleting adapters that haven't been added does no harm. */ + i2c_atr_del_adapter(priv->atr, 0); + + i2c_atr_delete(priv->atr); +} + +static int max_ser_i2c_atr_init(struct max_ser_priv *priv) +{ + struct i2c_atr_adap_desc desc = { + .chan_id = 0, + }; + + if (!i2c_check_functionality(priv->client->adapter, + I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -ENODEV; + + priv->atr = i2c_atr_new(priv->client->adapter, priv->dev, + &max_ser_i2c_atr_ops, 1, 0); + if (IS_ERR(priv->atr)) + return PTR_ERR(priv->atr); + + i2c_atr_set_driver_data(priv->atr, priv); + + return i2c_atr_add_adapter(priv->atr, &desc); +} + +static int max_ser_i2c_mux_select(struct i2c_mux_core *mux, u32 chan) +{ + return 0; +} + +static void max_ser_i2c_mux_deinit(struct max_ser_priv *priv) +{ + i2c_mux_del_adapters(priv->mux); +} + +static int max_ser_i2c_mux_init(struct max_ser_priv *priv) +{ + priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev, + 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE, + max_ser_i2c_mux_select, NULL); + if (!priv->mux) + return -ENOMEM; + + return i2c_mux_add_adapter(priv->mux, 0, 0); +} + +static int max_ser_i2c_adapter_init(struct max_ser_priv *priv) +{ + if (device_get_named_child_node(priv->dev, "i2c-gate")) + return max_ser_i2c_mux_init(priv); + else + return max_ser_i2c_atr_init(priv); +} + +static void max_ser_i2c_adapter_deinit(struct max_ser_priv *priv) +{ + if (device_get_named_child_node(priv->dev, "i2c-gate")) + max_ser_i2c_mux_deinit(priv); + else + max_ser_i2c_atr_deinit(priv); +} + +static int max_ser_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *format) +{ + struct max_ser_priv *priv = v4l2_get_subdevdata(sd); + struct max_ser *ser = priv->ser; + struct v4l2_mbus_framefmt *fmt; + + if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && ser->active) + return -EBUSY; + + /* No transcoding, source and sink formats must match. */ + if (max_ser_pad_is_source(ser, format->pad)) + return v4l2_subdev_get_fmt(sd, state, format); + + fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream); + if (!fmt) + return -EINVAL; + + *fmt = format->format; + + fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, + format->stream); + if (!fmt) + return -EINVAL; + + *fmt = format->format; + + return 0; +} + +static int max_ser_log_status(struct v4l2_subdev *sd) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct max_ser *ser = priv->ser; + unsigned int i, j; + int ret; + + v4l2_info(sd, "tunnel: %u\n", ser->tunnel); + if (ser->ops->log_status) { + ret = ser->ops->log_status(ser, sd->name); + if (ret) + return ret; + } + for (i = 0; i < ser->ops->num_i2c_xlates; i++) + v4l2_info(sd, "\ten: %u, src: 0x%02x dst: 0x%02x\n", + ser->i2c_xlates[i].en, ser->i2c_xlates[i].src, + ser->i2c_xlates[i].dst); + v4l2_info(sd, "\n"); + + for (i = 0; i < ser->ops->num_pipes; i++) { + struct max_ser_pipe *pipe = &ser->pipes[i]; + + v4l2_info(sd, "pipe: %u\n", pipe->index); + v4l2_info(sd, "\tenabled: %u\n", pipe->enabled); + + if (!pipe->enabled) { + v4l2_info(sd, "\n"); + continue; + } + + v4l2_info(sd, "\tphy_id: %u\n", pipe->phy_id); + v4l2_info(sd, "\tstream_id: %u\n", pipe->stream_id); + v4l2_info(sd, "\tdts: %u\n", pipe->num_dts); + for (j = 0; j < pipe->num_dts; j++) + v4l2_info(sd, "\t\tdt: 0x%02x\n", pipe->dts[j]); + v4l2_info(sd, "\tvcs: 0x%08x\n", pipe->vcs); + v4l2_info(sd, "\tdbl8: %u\n", pipe->mode.dbl8); + v4l2_info(sd, "\tdbl10: %u\n", pipe->mode.dbl10); + v4l2_info(sd, "\tdbl12: %u\n", pipe->mode.dbl12); + v4l2_info(sd, "\tsoft_bpp: %u\n", pipe->mode.soft_bpp); + v4l2_info(sd, "\tbpp: %u\n", pipe->mode.bpp); + if (ser->ops->log_pipe_status) { + ret = ser->ops->log_pipe_status(ser, pipe, sd->name); + if (ret) + return ret; + } + v4l2_info(sd, "\n"); + } + + for (i = 0; i < ser->ops->num_phys; i++) { + struct max_ser_phy *phy = &ser->phys[i]; + + v4l2_info(sd, "phy: %u\n", phy->index); + v4l2_info(sd, "\tenabled: %u\n", phy->enabled); + + if (!phy->enabled) { + v4l2_info(sd, "\n"); + continue; + } + + v4l2_info(sd, "\tactive: %u\n", phy->active); + v4l2_info(sd, "\tnum_data_lanes: %u\n", phy->mipi.num_data_lanes); + v4l2_info(sd, "\tclock_lane: %u\n", phy->mipi.clock_lane); + v4l2_info(sd, "\tnoncontinuous_clock: %u\n", + !!(phy->mipi.flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK)); + if (ser->ops->log_phy_status) { + ret = ser->ops->log_phy_status(ser, phy, sd->name); + if (ret) + return ret; + } + v4l2_info(sd, "\n"); + } + + return 0; +} + +static int max_ser_get_frame_desc_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_mbus_frame_desc *fd, + unsigned int pad) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct max_ser *ser = priv->ser; + struct v4l2_subdev_route *route; + int ret; + + if (!max_ser_pad_is_source(ser, pad)) + return -ENOENT; + + fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2; + + for_each_active_route(&state->routing, route) { + struct v4l2_mbus_frame_desc_entry entry; + struct max_source *source; + struct max_ser_phy *phy; + + if (pad != route->source_pad) + continue; + + phy = max_ser_pad_to_phy(ser, route->sink_pad); + if (!phy) { + dev_err(priv->dev, "Failed to find link for pad %u\n", + route->sink_pad); + return -ENOENT; + } + + source = max_ser_find_phy_source(priv, phy); + if (!source) + return -ENOENT; + + if (!source->sd) + continue; + + ret = max_get_fd_stream_entry(source->sd, source->pad, + route->sink_stream, &entry); + if (ret) { + dev_err(priv->dev, + "Failed to find frame desc entry for stream %u:%u: %d\n", + route->sink_pad, route->sink_stream, ret); + return ret; + } + + entry.stream = route->source_stream; + + fd->entry[fd->num_entries++] = entry; + } + + return 0; +} + +static int max_ser_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, + struct v4l2_mbus_frame_desc *fd) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct v4l2_subdev_state *state; + int ret; + + state = v4l2_subdev_lock_and_get_active_state(&priv->sd); + + ret = max_ser_get_frame_desc_state(sd, state, fd, pad); + + v4l2_subdev_unlock_state(state); + + return ret; +} + +static int max_ser_set_routing(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + enum v4l2_subdev_format_whence which, + struct v4l2_subdev_krouting *routing) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct max_ser *ser = priv->ser; + int ret; + + if (which == V4L2_SUBDEV_FORMAT_ACTIVE && ser->active) + return -EBUSY; + + /* + * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until + * frame desc is made dynamically allocated. + */ + + if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX) + return -E2BIG; + + ret = v4l2_subdev_routing_validate(sd, routing, + V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 | + V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX); + if (ret) + return ret; + + return v4l2_subdev_set_routing(sd, state, routing); +} + +static int max_ser_get_vcs_dts(struct max_ser_priv *priv, + const struct v4l2_subdev_krouting *routing, + struct max_source *source, + unsigned int *vcs, + unsigned int *dts, unsigned int *num_dts, + u32 sink_pad, u64 streams_mask) +{ + struct max_ser *ser = priv->ser; + struct v4l2_subdev_route *route; + unsigned int i; + int ret; + + *vcs = 0; + *num_dts = 0; + + if (ser->tunnel) + return 0; + + for_each_active_route(routing, route) { + struct v4l2_mbus_frame_desc_entry entry; + unsigned int vc, dt; + + if (sink_pad != route->sink_pad) + continue; + + if (!(BIT_ULL(route->sink_stream) & streams_mask)) + continue; + + ret = max_get_fd_stream_entry(source->sd, source->pad, + route->sink_stream, &entry); + if (ret) { + dev_err(priv->dev, + "Failed to find frame desc entry for stream %u:%u: %d\n", + route->sink_pad, route->sink_stream, ret); + return ret; + } + + vc = entry.bus.csi2.vc; + dt = entry.bus.csi2.dt; + + if (vc >= MAX_SERDES_VC_ID_NUM) + return -E2BIG; + + *vcs |= BIT(vc); + + /* Skip already added DT. */ + for (i = 0; i < *num_dts; i++) + if (dts[i] == dt) + break; + + if (i < *num_dts) + continue; + + dts[*num_dts] = dt; + (*num_dts)++; + } + + /* + * Hardware cannot distinguish between different pairs of VC and DT, + * issue a warning. + */ + for_each_active_route(routing, route) { + struct v4l2_mbus_frame_desc_entry entry; + unsigned int vc, dt; + + if (sink_pad != route->sink_pad) + continue; + + /* + * Skip enabled streams, we only want to check for leaks + * among the disabled streams. + */ + if ((BIT_ULL(route->sink_stream) & streams_mask)) + continue; + + ret = max_get_fd_stream_entry(source->sd, source->pad, + route->sink_stream, &entry); + if (ret) { + dev_err(priv->dev, + "Failed to find frame desc entry for stream %u:%u: %d\n", + route->sink_pad, route->sink_stream, ret); + return ret; + } + + vc = entry.bus.csi2.vc; + dt = entry.bus.csi2.dt; + + if (vc >= MAX_SERDES_VC_ID_NUM) + return -E2BIG; + + if (!(*vcs & BIT(vc))) + continue; + + for (i = 0; i < *num_dts; i++) + if (dts[i] == dt) + break; + + if (i == *num_dts) + continue; + + dev_warn(priv->dev, "Leaked disabled stream %u:%u with VC: %u, DT: %u", + route->source_pad, route->source_stream, vc, dt); + } + + return 0; +} + +static int max_ser_get_mode(struct max_ser_priv *priv, + struct max_ser_pipe_mode *mode, + const struct v4l2_subdev_krouting *routing, u32 pad) +{ + struct max_ser *ser = priv->ser; + unsigned int doubled_bpp; + unsigned int min_bpp; + unsigned int max_bpp; + u32 bpps; + int ret; + + if (ser->tunnel) + return 0; + + ret = max_get_bpps(priv->sources, 0, &bpps, routing, pad, ~0ULL); + if (ret) + return ret; + + ret = max_process_bpps(priv->dev, bpps, priv->double_bpps, &doubled_bpp); + if (ret) + return ret; + + if (doubled_bpp == 8) + mode->dbl8 = true; + else if (doubled_bpp == 10) + mode->dbl10 = true; + else if (doubled_bpp == 12) + mode->dbl12 = true; + + if (doubled_bpp) { + bpps &= ~BIT(doubled_bpp); + bpps |= BIT(doubled_bpp * 2); + } + + min_bpp = __ffs(bpps); + max_bpp = __fls(bpps); + + if (doubled_bpp) + mode->soft_bpp = min_bpp; + + if (min_bpp != max_bpp) + mode->bpp = max_bpp; + + return 0; +} + +static int max_ser_update_pipe(struct max_ser_priv *priv, + struct max_source *source, + struct max_ser_pipe *pipe, + const struct v4l2_subdev_krouting *routing, + u32 pad, u64 streams_mask) +{ + struct max_ser *ser = priv->ser; + struct max_ser_pipe_mode mode = { 0 }; + unsigned int num_dts; + unsigned int *dts; + unsigned int vcs; + int ret; + + dts = devm_kcalloc(priv->dev, ser->ops->num_dts_per_pipe, sizeof(*dts), + GFP_KERNEL); + if (!dts) + return -ENOMEM; + + ret = max_ser_get_vcs_dts(priv, routing, source, &vcs, dts, &num_dts, + pad, streams_mask); + if (ret) + goto err_free_dts; + + ret = max_ser_get_mode(priv, &mode, routing, pad); + if (ret) + goto err_free_dts; + + ret = ser->ops->set_pipe_vcs(ser, pipe, vcs); + if (ret) + goto err_free_dts; + + ret = max_ser_set_pipe_mode(priv, pipe, &mode); + if (ret) + goto err_revert_vcs; + + ret = max_ser_set_pipe_dts(priv, pipe, dts, num_dts); + if (ret) + goto err_revert_mode; + + pipe->vcs = vcs; + pipe->mode = mode; + + if (pipe->dts) + devm_kfree(priv->dev, pipe->dts); + + pipe->dts = dts; + pipe->num_dts = num_dts; + + return 0; + +err_revert_mode: + max_ser_set_pipe_mode(priv, pipe, &pipe->mode); + +err_revert_vcs: + ser->ops->set_pipe_vcs(ser, pipe, pipe->vcs); + +err_free_dts: + devm_kfree(priv->dev, dts); + + return ret; +} + +static int max_ser_update_phy(struct max_ser_priv *priv, + const struct v4l2_subdev_krouting *routing, + struct max_ser_phy *phy, u64 streams_mask) +{ + struct max_ser *ser = priv->ser; + u32 pad = max_ser_phy_to_pad(ser, phy); + bool enable_changed = !streams_mask != !priv->streams_masks[pad]; + bool enable = !!streams_mask; + struct max_source *source; + struct max_ser_pipe *pipe; + int ret; + + pipe = max_ser_find_phy_pipe(ser, phy); + if (!pipe) + return -ENOENT; + + source = max_ser_find_phy_source(priv, phy); + if (!source) + return -ENOENT; + + if (!source->sd) + return 0; + + if (!enable && enable_changed) { + ret = max_ser_set_pipe_enable(ser, pipe, enable); + if (ret) + return -ENOENT; + + ret = max_ser_phy_set_active(ser, phy, enable); + if (ret) + goto err_revert_pipe_disable; + } + + ret = max_ser_update_pipe(priv, source, pipe, routing, pad, streams_mask); + if (ret) + goto err_revert_phy_disable; + + if (enable && enable_changed) { + ret = max_ser_phy_set_active(ser, phy, enable); + if (ret) + goto err_revert_pipe_update; + + ret = max_ser_set_pipe_enable(ser, pipe, enable); + if (ret) + goto err_revert_phy_enable; + } + + return 0; + +err_revert_phy_enable: + if (enable && enable_changed) + max_ser_set_pipe_enable(ser, pipe, !enable); + +err_revert_pipe_update: + max_ser_update_pipe(priv, source, pipe, routing, pad, priv->streams_masks[pad]); + +err_revert_phy_disable: + if (!enable && enable_changed) + max_ser_phy_set_active(ser, phy, !enable); + +err_revert_pipe_disable: + if (!enable && enable_changed) + max_ser_set_pipe_enable(ser, pipe, !enable); + + return ret; +} + +static int max_ser_update_phys(struct max_ser_priv *priv, + const struct v4l2_subdev_krouting *routing, + u64 *streams_masks) +{ + struct max_ser *ser = priv->ser; + unsigned int failed_update_phy_id = ser->ops->num_phys; + unsigned int i; + int ret; + + for (i = 0; i < ser->ops->num_phys; i++) { + struct max_ser_phy *phy = &ser->phys[i]; + u32 sink_pad = max_ser_phy_to_pad(ser, phy); + + ret = max_ser_update_phy(priv, routing, phy, streams_masks[sink_pad]); + if (ret) { + failed_update_phy_id = i; + goto err; + } + } + + return 0; + +err: + for (i = 0; i < failed_update_phy_id; i++) { + struct max_ser_phy *phy = &ser->phys[i]; + u32 sink_pad = max_ser_phy_to_pad(ser, phy); + + max_ser_update_phy(priv, routing, phy, priv->streams_masks[sink_pad]); + } + + return ret; +} + +static int max_ser_enable_disable_streams(struct max_ser_priv *priv, + struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, + bool enable) +{ + struct max_ser *ser = priv->ser; + + return max_xlate_enable_disable_streams(priv->sources, 0, state, + pad, updated_streams_mask, 0, + ser->ops->num_phys, enable); +} + +static int max_ser_update_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, bool enable) +{ + struct max_ser_priv *priv = v4l2_get_subdevdata(sd); + struct max_ser *ser = priv->ser; + unsigned int num_pads = max_ser_num_pads(ser); + u64 *streams_masks; + int ret; + + ret = max_get_streams_masks(priv->dev, state, pad, updated_streams_mask, + num_pads, 0, ser->ops->num_phys, + priv->streams_masks, &streams_masks, enable); + if (ret) + return ret; + + if (!enable) { + ret = max_ser_enable_disable_streams(priv, state, pad, + updated_streams_mask, enable); + if (ret) + goto err_free_streams_masks; + } + + ret = max_ser_update_phys(priv, &state->routing, streams_masks); + if (ret) + goto err_revert_streams_disable; + + if (enable) { + ret = max_ser_enable_disable_streams(priv, state, pad, + updated_streams_mask, enable); + if (ret) + goto err_revert_phys_update; + } + + devm_kfree(priv->dev, priv->streams_masks); + priv->streams_masks = streams_masks; + ser->active = !!streams_masks[pad]; + + return 0; + +err_revert_phys_update: + max_ser_update_phys(priv, &state->routing, priv->streams_masks); + +err_revert_streams_disable: + if (!enable) + max_ser_enable_disable_streams(priv, state, pad, + updated_streams_mask, !enable); + +err_free_streams_masks: + devm_kfree(priv->dev, streams_masks); + + return ret; +} + +static int max_ser_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + return max_ser_update_streams(sd, state, pad, streams_mask, true); +} + +static int max_ser_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + return max_ser_update_streams(sd, state, pad, streams_mask, false); +} + +#ifdef CONFIG_VIDEO_ADV_DEBUG +static int max_ser_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct max_ser *ser = priv->ser; + unsigned int val; + int ret; + + ret = ser->ops->reg_read(ser, reg->reg, &val); + if (ret) + return ret; + + reg->val = val; + reg->size = 1; + + return 0; +} + +static int max_ser_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct max_ser *ser = priv->ser; + + return ser->ops->reg_write(ser, reg->reg, reg->val); +} +#endif + +static const struct v4l2_subdev_core_ops max_ser_core_ops = { + .log_status = max_ser_log_status, +#ifdef CONFIG_VIDEO_ADV_DEBUG + .g_register = max_ser_g_register, + .s_register = max_ser_s_register, +#endif +}; + +static const struct v4l2_subdev_pad_ops max_ser_pad_ops = { + .enable_streams = max_ser_enable_streams, + .disable_streams = max_ser_disable_streams, + + .set_routing = max_ser_set_routing, + .get_frame_desc = max_ser_get_frame_desc, + + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = max_ser_set_fmt, +}; + +static const struct v4l2_subdev_ops max_ser_subdev_ops = { + .core = &max_ser_core_ops, + .pad = &max_ser_pad_ops, +}; + +static const struct media_entity_operations max_ser_media_ops = { + .link_validate = v4l2_subdev_link_validate, + .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1, +}; + +static int max_ser_init(struct max_ser_priv *priv) +{ + struct max_ser *ser = priv->ser; + unsigned int i; + int ret; + + ret = ser->ops->init(ser); + if (ret) + return ret; + + if (ser->ops->set_tunnel_enable) { + ret = ser->ops->set_tunnel_enable(ser, false); + if (ret) + return ret; + } + + for (i = 0; i < ser->ops->num_phys; i++) { + struct max_ser_phy *phy = &ser->phys[i]; + + if (phy->enabled) { + ret = ser->ops->init_phy(ser, phy); + if (ret) + return ret; + } + + ret = ser->ops->set_phy_active(ser, phy, false); + if (ret) + return ret; + } + + for (i = 0; i < ser->ops->num_pipes; i++) { + struct max_ser_pipe *pipe = &ser->pipes[i]; + struct max_ser_phy *phy = &ser->phys[pipe->phy_id]; + + ret = ser->ops->set_pipe_enable(ser, pipe, false); + if (ret) + return ret; + + ret = ser->ops->set_pipe_stream_id(ser, pipe, pipe->stream_id); + if (ret) + return ret; + + ret = ser->ops->set_pipe_phy(ser, pipe, phy); + if (ret) + return ret; + + ret = ser->ops->set_pipe_vcs(ser, pipe, 0); + if (ret) + return ret; + + ret = ser->ops->set_pipe_mode(ser, pipe, &pipe->mode); + if (ret) + return ret; + + ret = max_ser_set_pipe_dts(priv, pipe, NULL, 0); + if (ret) + return ret; + } + + return 0; +} + +static int max_ser_notify_bound(struct v4l2_async_notifier *nf, + struct v4l2_subdev *subdev, + struct v4l2_async_connection *base_asc) +{ + struct max_ser_priv *priv = nf_to_priv(nf); + struct max_asc *asc = asc_to_max(base_asc); + struct max_source *source = asc->source; + u32 pad = source->index; + int ret; + + ret = media_entity_get_fwnode_pad(&subdev->entity, + source->ep_fwnode, + MEDIA_PAD_FL_SOURCE); + if (ret < 0) { + dev_err(priv->dev, "Failed to find pad for %s\n", subdev->name); + return ret; + } + + source->sd = subdev; + source->pad = ret; + + ret = media_create_pad_link(&source->sd->entity, source->pad, + &priv->sd.entity, pad, + MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); + if (ret) { + dev_err(priv->dev, "Unable to link %s:%u -> %s:%u\n", + source->sd->name, source->pad, priv->sd.name, pad); + return ret; + } + + return 0; +} + +static void max_ser_notify_unbind(struct v4l2_async_notifier *nf, + struct v4l2_subdev *subdev, + struct v4l2_async_connection *base_asc) +{ + struct max_asc *asc = asc_to_max(base_asc); + struct max_source *source = asc->source; + + source->sd = NULL; +} + +static const struct v4l2_async_notifier_operations max_ser_notify_ops = { + .bound = max_ser_notify_bound, + .unbind = max_ser_notify_unbind, +}; + +static int max_ser_v4l2_notifier_register(struct max_ser_priv *priv) +{ + struct max_ser *ser = priv->ser; + unsigned int i; + int ret; + + v4l2_async_subdev_nf_init(&priv->nf, &priv->sd); + + for (i = 0; i < ser->ops->num_phys; i++) { + struct max_ser_phy *phy = &ser->phys[i]; + struct max_source *source; + struct max_asc *asc; + + source = max_ser_find_phy_source(priv, phy); + if (!source) + return -ENOENT; + + if (!source->ep_fwnode) + continue; + + asc = v4l2_async_nf_add_fwnode(&priv->nf, source->ep_fwnode, + struct max_asc); + if (IS_ERR(asc)) { + dev_err(priv->dev, + "Failed to add subdev for source %u: %pe", i, + asc); + + v4l2_async_nf_cleanup(&priv->nf); + + return PTR_ERR(asc); + } + + asc->source = source; + } + + priv->nf.ops = &max_ser_notify_ops; + + ret = v4l2_async_nf_register(&priv->nf); + if (ret) { + dev_err(priv->dev, "Failed to register subdev notifier"); + v4l2_async_nf_cleanup(&priv->nf); + return ret; + } + + return 0; +} + +static void max_ser_v4l2_notifier_unregister(struct max_ser_priv *priv) +{ + v4l2_async_nf_unregister(&priv->nf); + v4l2_async_nf_cleanup(&priv->nf); +} + +static int max_ser_v4l2_register(struct max_ser_priv *priv) +{ + struct v4l2_subdev *sd = &priv->sd; + struct max_ser *ser = priv->ser; + void *data = i2c_get_clientdata(priv->client); + unsigned int num_pads = max_ser_num_pads(ser); + unsigned int i; + int ret; + + v4l2_i2c_subdev_init(sd, priv->client, &max_ser_subdev_ops); + i2c_set_clientdata(priv->client, data); + sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + sd->entity.ops = &max_ser_media_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS; + + priv->pads = devm_kcalloc(priv->dev, num_pads, sizeof(*priv->pads), GFP_KERNEL); + if (!priv->pads) + return -ENOMEM; + + for (i = 0; i < num_pads; i++) { + if (max_ser_pad_is_sink(ser, i)) + priv->pads[i].flags = MEDIA_PAD_FL_SINK; + else + priv->pads[i].flags = MEDIA_PAD_FL_SOURCE; + } + + v4l2_set_subdevdata(sd, priv); + + ret = media_entity_pads_init(&sd->entity, num_pads, priv->pads); + if (ret) + return ret; + + ret = max_ser_v4l2_notifier_register(priv); + if (ret) + goto err_media_entity_cleanup; + + ret = v4l2_subdev_init_finalize(sd); + if (ret) + goto err_nf_cleanup; + + ret = v4l2_async_register_subdev(sd); + if (ret) + goto err_sd_cleanup; + + return 0; + +err_sd_cleanup: + v4l2_subdev_cleanup(sd); +err_nf_cleanup: + max_ser_v4l2_notifier_unregister(priv); +err_media_entity_cleanup: + media_entity_cleanup(&sd->entity); + + return ret; +} + +static void max_ser_v4l2_unregister(struct max_ser_priv *priv) +{ + struct v4l2_subdev *sd = &priv->sd; + + max_ser_v4l2_notifier_unregister(priv); + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); + media_entity_cleanup(&sd->entity); +} + +static int max_ser_parse_sink_dt_endpoint(struct max_ser_priv *priv, + struct max_ser_phy *phy, + struct max_source *source, + struct fwnode_handle *fwnode) +{ + struct max_ser *ser = priv->ser; + u32 pad = max_ser_phy_to_pad(ser, phy); + struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; + struct v4l2_mbus_config_mipi_csi2 *mipi = &v4l2_ep.bus.mipi_csi2; + struct fwnode_handle *ep; + int ret; + + ep = fwnode_graph_get_endpoint_by_id(fwnode, pad, 0, 0); + if (!ep) + return 0; + + source->ep_fwnode = fwnode_graph_get_remote_endpoint(ep); + if (!source->ep_fwnode) { + dev_err(priv->dev, + "Failed to get remote endpoint on port %u\n", pad); + return -EINVAL; + } + + ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep); + fwnode_handle_put(ep); + if (ret) { + dev_err(priv->dev, "Could not parse endpoint on port %u\n", pad); + return ret; + } + + if (mipi->flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK && + !ser->ops->supports_noncontinuous_clock) { + dev_err(priv->dev, + "Clock non-continuous mode is not supported on port %u\n", pad); + return -EINVAL; + } + + phy->mipi = v4l2_ep.bus.mipi_csi2; + phy->enabled = true; + + return 0; +} + +static int max_ser_find_phys_config(struct max_ser_priv *priv) +{ + struct max_ser *ser = priv->ser; + const struct max_phys_configs *configs = &ser->ops->phys_configs; + struct max_ser_phy *phy; + unsigned int i, j; + + if (!configs->num_configs) + return 0; + + for (i = 0; i < configs->num_configs; i++) { + const struct max_phys_config *config = &configs->configs[i]; + bool matching = true; + + for (j = 0; j < ser->ops->num_phys; j++) { + phy = &ser->phys[j]; + + if (!phy->enabled) + continue; + + if (phy->mipi.num_data_lanes <= config->lanes[j]) + continue; + + matching = false; + + break; + } + + if (matching) + break; + } + + if (i == configs->num_configs) { + dev_err(priv->dev, "Invalid lane configuration\n"); + return -EINVAL; + } + + ser->phys_config = i; + + return 0; +} + +static int max_ser_parse_dt(struct max_ser_priv *priv) +{ + struct fwnode_handle *fwnode = dev_fwnode(priv->dev); + struct max_ser *ser = priv->ser; + struct max_ser_pipe *pipe; + struct max_ser_phy *phy; + unsigned int i; + int ret; + + for (i = 0; i < ser->ops->num_phys; i++) { + phy = &ser->phys[i]; + phy->index = i; + } + + for (i = 0; i < ser->ops->num_pipes; i++) { + pipe = &ser->pipes[i]; + pipe->index = i; + pipe->phy_id = i % ser->ops->num_phys; + pipe->stream_id = i % MAX_SERDES_STREAMS_NUM; + } + + for (i = 0; i < ser->ops->num_phys; i++) { + struct max_ser_phy *phy = &ser->phys[i]; + struct max_source *source; + + source = max_ser_find_phy_source(priv, phy); + if (!source) + return -ENOENT; + + source->index = i; + + ret = max_ser_parse_sink_dt_endpoint(priv, phy, source, fwnode); + if (ret) + return ret; + } + + return max_ser_find_phys_config(priv); +} + +static int max_ser_allocate(struct max_ser_priv *priv) +{ + struct max_ser *ser = priv->ser; + unsigned int num_pads = max_ser_num_pads(ser); + + ser->phys = devm_kcalloc(priv->dev, ser->ops->num_phys, + sizeof(*ser->phys), GFP_KERNEL); + if (!ser->phys) + return -ENOMEM; + + ser->pipes = devm_kcalloc(priv->dev, ser->ops->num_pipes, + sizeof(*ser->pipes), GFP_KERNEL); + if (!ser->pipes) + return -ENOMEM; + + ser->i2c_xlates = devm_kcalloc(priv->dev, ser->ops->num_i2c_xlates, + sizeof(*ser->i2c_xlates), GFP_KERNEL); + if (!ser->i2c_xlates) + return -ENOMEM; + + priv->sources = devm_kcalloc(priv->dev, ser->ops->num_phys, + sizeof(*priv->sources), GFP_KERNEL); + if (!priv->sources) + return -ENOMEM; + + priv->streams_masks = devm_kcalloc(priv->dev, num_pads, + sizeof(*priv->streams_masks), + GFP_KERNEL); + if (!priv->streams_masks) + return -ENOMEM; + + return 0; +} + +int max_ser_probe(struct i2c_client *client, struct max_ser *ser) +{ + struct device *dev = &client->dev; + struct max_ser_priv *priv; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->client = client; + priv->dev = dev; + priv->ser = ser; + ser->priv = priv; + + ret = max_ser_allocate(priv); + if (ret) + return ret; + + ret = max_ser_parse_dt(priv); + if (ret) + return ret; + + ret = max_ser_init(priv); + if (ret) + return ret; + + ret = max_ser_i2c_adapter_init(priv); + if (ret) + return ret; + + ret = max_ser_v4l2_register(priv); + if (ret) + goto err_i2c_adapter_deinit; + + return 0; + +err_i2c_adapter_deinit: + max_ser_i2c_adapter_deinit(priv); + + return ret; +} +EXPORT_SYMBOL_GPL(max_ser_probe); + +int max_ser_remove(struct max_ser *ser) +{ + struct max_ser_priv *priv = ser->priv; + + max_ser_v4l2_unregister(priv); + + max_ser_i2c_adapter_deinit(priv); + + return 0; +} +EXPORT_SYMBOL_GPL(max_ser_remove); + +int max_ser_set_double_bpps(struct v4l2_subdev *sd, u32 double_bpps) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + + priv->double_bpps = double_bpps; + + return 0; +} +EXPORT_SYMBOL_GPL(max_ser_set_double_bpps); + +bool max_ser_supports_tunnel_mode(struct v4l2_subdev *sd) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct max_ser *ser = priv->ser; + + if (!ser->ops->set_tunnel_enable) + return false; + + return true; +} +EXPORT_SYMBOL(max_ser_supports_tunnel_mode); + +int max_ser_set_tunnel_enable(struct v4l2_subdev *sd, bool enable) +{ + struct max_ser_priv *priv = sd_to_priv(sd); + struct max_ser *ser = priv->ser; + int ret; + + if (!ser->ops->set_tunnel_enable) + return 0; + + if (ser->tunnel == enable) + return 0; + + ret = ser->ops->set_tunnel_enable(ser, enable); + if (ret) + return ret; + + ser->tunnel = enable; + + return 0; +} +EXPORT_SYMBOL(max_ser_set_tunnel_enable); + +static int max_ser_read_reg(struct i2c_adapter *adapter, u8 addr, + u16 reg, u8 *val) +{ + u8 buf[2] = { reg >> 8, reg & 0xff }; + struct i2c_msg msg[2] = { + { + .addr = addr, + .flags = 0, + .buf = buf, + .len = sizeof(buf), + }, + { + .addr = addr, + .flags = I2C_M_RD, + .buf = buf, + .len = 1, + }, + }; + int ret; + + ret = i2c_transfer(adapter, msg, ARRAY_SIZE(msg)); + if (ret < 0) + return ret; + + *val = buf[0]; + + return 0; +} + +static int max_ser_write_reg(struct i2c_adapter *adapter, u8 addr, + u16 reg, u8 val) +{ + u8 buf[3] = { reg >> 8, reg & 0xff, val }; + struct i2c_msg msg[1] = { + { + .addr = addr, + .flags = 0, + .buf = buf, + .len = sizeof(buf), + }, + }; + int ret; + + ret = i2c_transfer(adapter, msg, ARRAY_SIZE(msg)); + if (ret < 0) + return ret; + + return 0; +} + +int max_ser_reset(struct i2c_adapter *adapter, u8 addr) +{ + int ret; + u8 val; + + ret = max_ser_read_reg(adapter, addr, MAX_SER_CTRL0, &val); + if (ret) + return ret; + + val |= MAX_SER_CTRL0_RESET_ALL; + + return max_ser_write_reg(adapter, addr, MAX_SER_CTRL0, val); +} +EXPORT_SYMBOL_GPL(max_ser_reset); + +int max_ser_wait_for_multiple(struct i2c_adapter *adapter, u8 *addrs, + unsigned int num_addrs, u8 *current_addr) +{ + unsigned int i, j; + int ret = 0; + u8 val; + + for (i = 0; i < 10; i++) { + for (j = 0; j < num_addrs; j++) { + ret = max_ser_read_reg(adapter, addrs[j], MAX_SER_REG0, &val); + if (!ret && val) { + *current_addr = addrs[j]; + return 0; + } + + msleep(100); + } + } + + return ret; +} +EXPORT_SYMBOL_GPL(max_ser_wait_for_multiple); + +int max_ser_wait(struct i2c_adapter *adapter, u8 addr) +{ + u8 current_addr; + + return max_ser_wait_for_multiple(adapter, &addr, 1, ¤t_addr); +} +EXPORT_SYMBOL_GPL(max_ser_wait); + +static int max_ser_get_dev_id(struct i2c_adapter *adapter, u8 addr, u8 *dev_id) +{ + return max_ser_read_reg(adapter, addr, MAX_SER_REG13, dev_id); +} + +int max_ser_fix_tx_ids(struct i2c_adapter *adapter, u8 addr) +{ + unsigned int addr_regs[] = { + MAX_SER_CFGI_INFOFR_TR3, + MAX_SER_CFGL_SPI_TR3, + MAX_SER_CFGC_CC_TR3, + MAX_SER_CFGC_GPIO_TR3, + MAX_SER_CFGL_IIC_X_TR3, + MAX_SER_CFGL_IIC_Y_TR3, + }; + unsigned int i; + u8 dev_id; + int ret; + + ret = max_ser_get_dev_id(adapter, addr, &dev_id); + if (ret) + return ret; + + switch (dev_id) { + case MAX_SER_MAX9265A_DEV_ID: + for (i = 0; i < ARRAY_SIZE(addr_regs); i++) { + ret = max_ser_write_reg(adapter, addr, addr_regs[i], addr); + if (ret) + return ret; + } + + break; + default: + return 0; + } + + return 0; +} +EXPORT_SYMBOL_GPL(max_ser_fix_tx_ids); + +int max_ser_change_address(struct i2c_adapter *adapter, u8 addr, u8 new_addr) +{ + int ret; + u8 val; + + ret = max_ser_read_reg(adapter, addr, MAX_SER_REG0, &val); + if (ret) + return ret; + + val |= FIELD_PREP(MAX_SER_REG0_DEV_ADDR, new_addr); + + return max_ser_write_reg(adapter, addr, MAX_SER_REG0, val); +} +EXPORT_SYMBOL_GPL(max_ser_change_address); + +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("I2C_ATR"); diff --git a/drivers/media/i2c/maxim-serdes/max_ser.h b/drivers/media/i2c/maxim-serdes/max_ser.h new file mode 100644 index 000000000000..c68ef90bab4a --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max_ser.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2025 Analog Devices Inc. + */ + +#ifndef MAX_SER_H +#define MAX_SER_H + +#include + +#include + +#include "max_serdes.h" + +#define MAX_SER_REG0 0x0 +#define MAX_SER_REG0_DEV_ADDR GENMASK(7, 1) + +#define MAX_SER_CTRL0 0x10 +#define MAX_SER_CTRL0_RESET_ALL BIT(7) + +#define MAX_SER_REG13 0xd +#define MAX_SER_MAX96717_DEV_ID 0xbf +#define MAX_SER_MAX9265A_DEV_ID 0x91 + +#define MAX_SER_CFGI_INFOFR_TR3 0x7b +#define MAX_SER_CFGL_SPI_TR3 0x83 +#define MAX_SER_CFGC_CC_TR3 0x8b +#define MAX_SER_CFGC_GPIO_TR3 0x93 +#define MAX_SER_CFGL_IIC_X_TR3 0xa3 +#define MAX_SER_CFGL_IIC_Y_TR3 0xab + +struct max_ser_phy { + unsigned int index; + struct v4l2_mbus_config_mipi_csi2 mipi; + bool enabled; + bool active; +}; + +struct max_ser_pipe_mode { + unsigned int soft_bpp; + unsigned int bpp; + bool dbl8; + bool dbl10; + bool dbl12; +}; + +struct max_ser_pipe { + unsigned int index; + unsigned int phy_id; + unsigned int stream_id; + unsigned int *dts; + unsigned int num_dts; + unsigned int vcs; + struct max_ser_pipe_mode mode; + bool enabled; +}; + +struct max_ser; + +struct max_ser_ops { + unsigned int num_pipes; + unsigned int num_dts_per_pipe; + unsigned int num_phys; + unsigned int num_i2c_xlates; + bool supports_noncontinuous_clock; + + struct max_phys_configs phys_configs; + + int (*reg_read)(struct max_ser *ser, unsigned int reg, unsigned int *val); + int (*reg_write)(struct max_ser *ser, unsigned int reg, unsigned int val); + int (*log_status)(struct max_ser *ser, const char *name); + int (*log_pipe_status)(struct max_ser *ser, struct max_ser_pipe *pipe, + const char *name); + int (*log_phy_status)(struct max_ser *ser, struct max_ser_phy *phy, + const char *name); + int (*init)(struct max_ser *ser); + int (*set_i2c_xlate)(struct max_ser *ser, unsigned int i, + struct max_i2c_xlate *i2c_xlate); + int (*set_tunnel_enable)(struct max_ser *ser, bool enable); + int (*init_phy)(struct max_ser *ser, struct max_ser_phy *phy); + int (*set_phy_active)(struct max_ser *ser, struct max_ser_phy *phy, + bool enable); + int (*set_pipe_enable)(struct max_ser *ser, struct max_ser_pipe *pipe, + bool enable); + int (*set_pipe_dt)(struct max_ser *ser, struct max_ser_pipe *pipe, + unsigned int i, unsigned int dt); + int (*set_pipe_dt_en)(struct max_ser *ser, struct max_ser_pipe *pipe, + unsigned int i, bool enable); + int (*set_pipe_vcs)(struct max_ser *ser, struct max_ser_pipe *pipe, + unsigned int vcs); + int (*set_pipe_mode)(struct max_ser *ser, struct max_ser_pipe *pipe, + struct max_ser_pipe_mode *mode); + int (*set_pipe_stream_id)(struct max_ser *ser, struct max_ser_pipe *pipe, + unsigned int stream_id); + int (*set_pipe_phy)(struct max_ser *ser, struct max_ser_pipe *pipe, + struct max_ser_phy *phy); +}; + +struct max_ser_priv; + +struct max_ser { + struct max_ser_priv *priv; + + const struct max_ser_ops *ops; + + struct max_i2c_xlate *i2c_xlates; + + struct max_ser_phy *phys; + struct max_ser_pipe *pipes; + + unsigned int phys_config; + unsigned int active; + bool tunnel; +}; + +int max_ser_probe(struct i2c_client *client, struct max_ser *ser); + +int max_ser_remove(struct max_ser *ser); + +int max_ser_set_double_bpps(struct v4l2_subdev *sd, u32 double_bpps); +bool max_ser_supports_tunnel_mode(struct v4l2_subdev *sd); +int max_ser_set_tunnel_enable(struct v4l2_subdev *sd, bool enable); + +int max_ser_reset(struct i2c_adapter *adapter, u8 addr); +int max_ser_wait(struct i2c_adapter *adapter, u8 addr); +int max_ser_wait_for_multiple(struct i2c_adapter *adapter, u8 *addrs, + unsigned int num_addrs, u8 *current_addr); + +int max_ser_change_address(struct i2c_adapter *adapter, u8 addr, u8 new_addr); +int max_ser_fix_tx_ids(struct i2c_adapter *adapter, u8 addr); + +#endif // MAX_SER_H diff --git a/drivers/media/i2c/maxim-serdes/max_serdes.c b/drivers/media/i2c/maxim-serdes/max_serdes.c new file mode 100644 index 000000000000..e2863109a57b --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max_serdes.c @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include + +#include + +#include + +#include "max_serdes.h" + +#define MAX_MIPI_FMT(_dt, _bpp) \ +{ \ + .dt = (_dt), \ + .bpp = (_bpp), \ +} + +static const struct max_mipi_format max_mipi_formats[] = { + MAX_MIPI_FMT(MIPI_CSI2_DT_EMBEDDED_8B, 8), + MAX_MIPI_FMT(MIPI_CSI2_DT_YUV422_8B, 16), + MAX_MIPI_FMT(MIPI_CSI2_DT_YUV422_10B, 20), + MAX_MIPI_FMT(MIPI_CSI2_DT_RGB565, 16), + MAX_MIPI_FMT(MIPI_CSI2_DT_RGB666, 18), + MAX_MIPI_FMT(MIPI_CSI2_DT_RGB888, 24), + MAX_MIPI_FMT(MIPI_CSI2_DT_RAW8, 8), + MAX_MIPI_FMT(MIPI_CSI2_DT_RAW10, 10), + MAX_MIPI_FMT(MIPI_CSI2_DT_RAW12, 12), + MAX_MIPI_FMT(MIPI_CSI2_DT_RAW14, 14), + MAX_MIPI_FMT(MIPI_CSI2_DT_RAW16, 16), +}; + +const struct max_mipi_format *max_mipi_format_by_dt(u8 dt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(max_mipi_formats); i++) + if (max_mipi_formats[i].dt == dt) + return &max_mipi_formats[i]; + + return NULL; +} +EXPORT_SYMBOL_GPL(max_mipi_format_by_dt); + +int max_get_fd_stream_entry(struct v4l2_subdev *sd, u32 pad, u32 stream, + struct v4l2_mbus_frame_desc_entry *entry) +{ + struct v4l2_mbus_frame_desc fd; + unsigned int i; + int ret; + + ret = v4l2_subdev_call(sd, pad, get_frame_desc, pad, &fd); + if (ret) + return ret; + + if (fd.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2) + return -EOPNOTSUPP; + + for (i = 0; i < fd.num_entries; i++) { + if (fd.entry[i].stream == stream) { + *entry = fd.entry[i]; + return 0; + } + } + + return -ENOENT; +} +EXPORT_SYMBOL(max_get_fd_stream_entry); + +int max_get_bpps(struct max_source *sources, u32 source_sink_pad_offset, + u32 *bpps, const struct v4l2_subdev_krouting *routing, + u32 pad, u64 streams_mask) +{ + struct v4l2_subdev_route *route; + int ret; + + *bpps = 0; + + for_each_active_route(routing, route) { + struct v4l2_mbus_frame_desc_entry entry; + const struct max_mipi_format *format; + struct max_source *source; + + if (route->sink_pad == pad) { + if (!(BIT_ULL(route->sink_stream) & streams_mask)) + continue; + } else if (route->source_pad == pad) { + if (!(BIT_ULL(route->source_stream) & streams_mask)) + continue; + } else { + continue; + } + + source = &sources[route->sink_pad + source_sink_pad_offset]; + if (!source) + continue; + + ret = max_get_fd_stream_entry(source->sd, source->pad, + route->sink_stream, &entry); + if (ret) + return ret; + + format = max_mipi_format_by_dt(entry.bus.csi2.dt); + if (!format) + continue; + + *bpps |= BIT(format->bpp); + } + + return 0; +} +EXPORT_SYMBOL(max_get_bpps); + +int max_process_bpps(struct device *dev, u32 bpps, u32 allowed_double_bpps, + unsigned int *doubled_bpp) +{ + unsigned int min_bpp; + unsigned int max_bpp; + bool doubled = false; + + if (!bpps) + return 0; + + *doubled_bpp = 0; + + /* + * Hardware can double bpps 8, 10, 12, and it can pad bpps < 16 + * to another bpp <= 16: + * Hardware can only stream a single constant bpp up to 24. + * + * From these features and limitations, the following rules + * can be deduced: + * + * A bpp of 8 can always be doubled if present. + * A bpp of 10 can be doubled only if there are no other bpps or the + * only other bpp is 20. + * A bpp of 12 can be doubled only if there are no other bpps or the + * only other bpp is 24. + * Bpps <= 16 cannot coexist with bpps > 16. + * Bpps <= 16 need to be padded to the biggest bpp. + */ + + min_bpp = __ffs(bpps); + max_bpp = __fls(bpps); + + if (min_bpp == 8) { + doubled = true; + } else if (min_bpp == 10 || min_bpp == 12) { + u32 bpp_or_double = BIT(min_bpp) | BIT(min_bpp * 2); + u32 other_bpps = bpps & ~bpp_or_double; + + if (!other_bpps) + doubled = true; + } + + if (doubled && (allowed_double_bpps & BIT(min_bpp))) { + *doubled_bpp = min_bpp; + bpps &= ~BIT(min_bpp); + bpps |= BIT(min_bpp * 2); + } + + min_bpp = __ffs(bpps); + max_bpp = __fls(bpps); + + if (max_bpp > 24) { + dev_err(dev, "Cannot stream bpps > 24\n"); + return -EINVAL; + } + + if (min_bpp <= 16 && max_bpp > 16) { + dev_err(dev, "Cannot stream bpps <= 16 with bpps > 16\n"); + return -EINVAL; + } + + if (max_bpp > 16 && min_bpp != max_bpp) { + dev_err(dev, "Cannot stream multiple bpps when one is > 16\n"); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(max_process_bpps); + +int max_xlate_enable_disable_streams(struct max_source *sources, + u32 source_sink_pad_offset, + const struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, + u32 sink_pad_start, u32 num_sink_pads, + bool enable) +{ + u32 failed_sink_pad; + int ret; + u32 i; + + for (i = sink_pad_start; i < sink_pad_start + num_sink_pads; i++) { + u64 matched_streams_mask = updated_streams_mask; + u64 updated_sink_streams_mask; + struct max_source *source; + + updated_sink_streams_mask = + v4l2_subdev_state_xlate_streams(state, pad, i, + &matched_streams_mask); + if (!updated_sink_streams_mask) + continue; + + source = &sources[i + source_sink_pad_offset]; + if (!source) + continue; + + if (enable) + ret = v4l2_subdev_enable_streams(source->sd, source->pad, + updated_sink_streams_mask); + else + ret = v4l2_subdev_disable_streams(source->sd, source->pad, + updated_sink_streams_mask); + if (ret) { + failed_sink_pad = i; + goto err; + } + } + + return 0; + +err: + for (i = sink_pad_start; i < failed_sink_pad; i++) { + u64 matched_streams_mask = updated_streams_mask; + u64 updated_sink_streams_mask; + struct max_source *source; + + updated_sink_streams_mask = + v4l2_subdev_state_xlate_streams(state, pad, i, + &matched_streams_mask); + if (!updated_sink_streams_mask) + continue; + + source = &sources[i + source_sink_pad_offset]; + if (!source) + continue; + + if (!enable) + v4l2_subdev_enable_streams(source->sd, source->pad, + updated_sink_streams_mask); + else + v4l2_subdev_disable_streams(source->sd, source->pad, + updated_sink_streams_mask); + } + + return ret; +} +EXPORT_SYMBOL(max_xlate_enable_disable_streams); + +int max_get_streams_masks(struct device *dev, + const struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, + u32 num_pads, u32 sink_pad_start, + u32 num_sink_pads, u64 *old_streams_masks, + u64 **new_streams_masks, bool enable) +{ + u64 *streams_masks; + unsigned int i; + + streams_masks = devm_kcalloc(dev, num_pads, sizeof(*streams_masks), GFP_KERNEL); + if (!streams_masks) + return -ENOMEM; + + for (i = 0; i < num_pads; i++) + streams_masks[i] = old_streams_masks[i]; + + for (i = sink_pad_start; i < sink_pad_start + num_sink_pads; i++) { + u64 matched_streams_mask = updated_streams_mask; + u64 updated_sink_streams_mask; + + updated_sink_streams_mask = + v4l2_subdev_state_xlate_streams(state, pad, i, + &matched_streams_mask); + if (!updated_sink_streams_mask) + continue; + + if (enable) + streams_masks[i] |= updated_sink_streams_mask; + else + streams_masks[i] &= ~updated_sink_streams_mask; + } + + if (enable) + streams_masks[pad] |= updated_streams_mask; + else + streams_masks[pad] &= ~updated_streams_mask; + + *new_streams_masks = streams_masks; + + return 0; +} +EXPORT_SYMBOL(max_get_streams_masks); + +MODULE_DESCRIPTION("Maxim GMSL2 Serializer/Deserializer Driver"); +MODULE_AUTHOR("Cosmin Tanislav "); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/i2c/maxim-serdes/max_serdes.h b/drivers/media/i2c/maxim-serdes/max_serdes.h new file mode 100644 index 000000000000..f71fe824f152 --- /dev/null +++ b/drivers/media/i2c/maxim-serdes/max_serdes.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2025 Analog Devices Inc. + */ + +#ifndef MAX_SERDES_H +#define MAX_SERDES_H + +#include + +#include + +#define MAX_SERDES_PHYS_MAX 4 +#define MAX_SERDES_STREAMS_NUM 4 +#define MAX_SERDES_VC_ID_NUM 4 + +enum max_gmsl_version { + MAX_GMSL_2 = 2, + MAX_GMSL_MIN = MAX_GMSL_2, + MAX_GMSL_3 = 3, + MAX_GMSL_MAX = MAX_GMSL_3, +}; + +struct max_phys_config { + unsigned int lanes[MAX_SERDES_PHYS_MAX]; + unsigned int clock_lane[MAX_SERDES_PHYS_MAX]; +}; + +struct max_phys_configs { + const struct max_phys_config *configs; + unsigned int num_configs; +}; + +struct max_i2c_xlate { + u8 src; + u8 dst; + bool en; +}; + +struct max_mipi_format { + u8 dt; + u8 bpp; +}; + +struct max_source { + struct v4l2_subdev *sd; + u16 pad; + struct fwnode_handle *ep_fwnode; + + unsigned int index; +}; + +struct max_asc { + struct v4l2_async_connection base; + struct max_source *source; +}; + +static inline struct max_asc *asc_to_max(struct v4l2_async_connection *asc) +{ + return container_of(asc, struct max_asc, base); +} + +const struct max_mipi_format *max_mipi_format_by_dt(u8 dt); + +int max_get_fd_stream_entry(struct v4l2_subdev *sd, u32 pad, u32 stream, + struct v4l2_mbus_frame_desc_entry *entry); + +int max_get_bpps(struct max_source *sources, u32 source_sink_pad_offset, + u32 *bpps, const struct v4l2_subdev_krouting *routing, + u32 pad, u64 streams_mask); +int max_process_bpps(struct device *dev, u32 bpps, u32 allowed_double_bpps, + unsigned int *doubled_bpp); + +int max_xlate_enable_disable_streams(struct max_source *sources, + u32 source_sink_pad_offset, + const struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, + u32 sink_pad_start, u32 num_sink_pads, + bool enable); + +int max_get_streams_masks(struct device *dev, + const struct v4l2_subdev_state *state, + u32 pad, u64 updated_streams_mask, + u32 num_pads, u32 sink_pad_start, + u32 num_sink_pads, u64 *old_streams_masks, + u64 **new_streams_masks, bool enable); + +#endif // MAX_SERDES_H From patchwork Sat Mar 8 18:33:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872051 Received: from mail-ej1-f45.google.com (mail-ej1-f45.google.com [209.85.218.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72B3620E702; Sat, 8 Mar 2025 18:36:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458962; cv=none; b=KwMNoMBUT7OPY9L5fnvdmHn2L1ZD98D+pATlZO/wt68nSnpbKeeD0Y22zur9BnTwAlIWVdLgHzT9z24S6hjYzSrN3P6dZIUSlsu2DGFNGHukDYFJ0c+1TweWbRHxtK8E8s35co7ELfngLAz9Mj2JMsxlnk6IQu9fI8zGKCd1j/U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458962; c=relaxed/simple; bh=9o7dWxkAzzvkB2Imojs5J6AXrsEiMQLNW5n5ACM0GTM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=c5JC6IkZIKhaVpruFmLxmsbzy3umHmjhtlzWHFwFFimpBIlfL9ULIu2Ik8Mi6iaoNY4cEoJruOy+jPEyAYn5ovDC88w69MkQIGY8x/P/g3c12/wEcrN00rTxFD2XQ5OFK1umuin2rqcM9RU1p7/+KzF6cv3ewg9Ee0C6ZENzinc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AsEi+0hk; arc=none smtp.client-ip=209.85.218.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AsEi+0hk" Received: by mail-ej1-f45.google.com with SMTP id a640c23a62f3a-abf6f3b836aso455585366b.3; Sat, 08 Mar 2025 10:36:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458959; x=1742063759; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4dW4CzmrzcxsS+VFvHNn6mQCAsXdBank+JJs+zbf7Qs=; b=AsEi+0hku9sFE8k4miOVyiije1QBXYEo0XLRdMmveKXNdi3dVPOSykwQV89lcRzI8G KOWLzZvEF/78DlYHi8vlnL2lFAAHxSu6qmNlA/smQZeLFeNoct4BT54TbCZc3iknc9bk Ylq5yIbz837v7h3+FFjGgiLuKXnnj3sQUhVBuNiH0oOCIJ0rT/JZJwhPC6AGhsAw0kfR o5Is5FFIMZCvo2jq96EuWFdSbuzNU6ykzhnOwVokpY/607zDHkbqA0UVK1sUTfxgU1Fq hEGQ4qowTvbp9SZgiRo1eTt5aDWasxibdBiYPuzGoYskWqck4E+AQ20z9pIZEtjV7fmu 3C/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458959; x=1742063759; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4dW4CzmrzcxsS+VFvHNn6mQCAsXdBank+JJs+zbf7Qs=; b=ftt4G67WxMGmeiLCIXd1FseJdVO23E6xUfDPAafYvR0YhLvJLDovozdUfxUsMk/KxN YkB2/fwB5JME/V73l1u+Eft9swcrToQS1vw8E4iLOwyv/mAtmlmB3gna8PudVtuRh0RX UlkgsYA2sb1uInGb3V01PoTaTTzdPhWYFK6emUPSNQE9ta4w2OfVkKxS/Dcb5MeKcSlQ N+/R4sijqAvE/O4WXoe2y43G/zXOCGnKnrb7vSipN4qohYx3OIe6fMXHIURqNR+M1yOV qcwCvG7PpQf24HDedXePoYznmh6AxmGQv913RvKcGlf/3mJJpl9ayLTVRsiP8UpwwumP Ir0g== X-Forwarded-Encrypted: i=1; AJvYcCU4rR5a4mncfvXdP5ebkjRoiQQ6UVWJARNFZHf2BriGvDsDceVEczCYaY6dFgKACOCaINjdjJj7Euwzxg==@vger.kernel.org, AJvYcCUs3VAlRp6k9fQagAvoDemor+HqPUJFp2YjDy8NeI8r8UKak/ZS3+G9EhfItkWR+1d4zxmG1lduq0RktUGW@vger.kernel.org, AJvYcCW9YVmwHL8vOOD5zO61pnAjycXJUcstaZI7ytESBe6FFmotYiNilb66sS1DEWmYdBuIEhirRNp/VCjYAxA=@vger.kernel.org, AJvYcCWnxZaVdiLgj0GcpjaG6cYIZCIqZPf9joAUJVW5j87kS7+0lNsoWdd4YKgN3bv0GDSTxRdzLeWIQGhD@vger.kernel.org X-Gm-Message-State: AOJu0YxnUEsubTSJzev2wT/UgmBuhcX42EE9EMCZdncyawK2xW5A0kLY f11iM482nFaKIhg4ijLbaMMg6dfgPYOJlCHaKcxJcsFKIZRg47HX X-Gm-Gg: ASbGnctNhFuQj/K6/pTnQ7uYnSNqai1QrYmM+ja9QKzxMdtdy12aYy8Qhk2HKoVX2Op ieS77nhD+4vIup9bFIw4gxDnIpUwNN1uWgOZq77NRiqKRosFTc5YGGQ7ic605TjJDXBs8zmeANz GjTyPZnmdAMtKseKQvhaDZ2huy+TcRoLxfY+s3nLhoS20UEhCrK0BTY2JtbWHskr3o1HXlGf2Ys fFlVsGCgahIi5PPYEJifa1MFvxqXExrTbgy1nKBoLhJ1xy+9lreXDe+Cv1O4ZW76oA52mJkSwJ0 LOT8+XUvIEo0ZsW895m5CLET500y9wDnsVUmv9E5Sc9kzk2mqnRwgkG9Zg== X-Google-Smtp-Source: AGHT+IFeTY6f+Z5x+qQcdIB8S71nVbnmrDN479LQd6qexMksrmnIptmPnmurHuelrlJDcIOha3YkMA== X-Received: by 2002:a17:907:2cc4:b0:abf:5fe7:40db with SMTP id a640c23a62f3a-ac252b5a1fdmr879505766b.31.1741458958420; Sat, 08 Mar 2025 10:35:58 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:35:58 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 21/24] arm64: defconfig: disable deprecated MAX96712 driver Date: Sat, 8 Mar 2025 20:33:50 +0200 Message-ID: <20250308183410.3013996-22-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The staging MAX96712 driver will be removed as its functionality has been moved to the MAX96724 driver which makes use of the Maxim GMSL2/3 deserializer framework. Signed-off-by: Cosmin Tanislav --- arch/arm64/configs/defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index cb7da4415599..6e9bd9072d11 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -1272,7 +1272,6 @@ CONFIG_XEN_GNTDEV=y CONFIG_XEN_GRANT_DEV_ALLOC=y CONFIG_STAGING=y CONFIG_STAGING_MEDIA=y -CONFIG_VIDEO_MAX96712=m CONFIG_VIDEO_MESON_VDEC=m CONFIG_SND_BCM2835=m CONFIG_CHROME_PLATFORMS=y From patchwork Sat Mar 8 18:33:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871780 Received: from mail-ej1-f53.google.com (mail-ej1-f53.google.com [209.85.218.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0183321ABDC; Sat, 8 Mar 2025 18:36:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458966; cv=none; b=kjjEKt9Le/Lt1osOYXMNA9BAdUwFRPUyaMyzC4+jPRbf1Iv3YOYoHGAZDlmMfwyAuS+gefC1xl+O8QB6xwA0dFH5OzbtQpyrEAsouc7onUxSZrgCDpyqB29JEY6Gel9YQFnKjLthDGjO3KJKsisiMEK2AJITmXKQrUfqpCEV22c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458966; c=relaxed/simple; bh=oym60NuX5+/ncMsDDSDe22oqBxgvuyF14Yg460pADUM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NDZkdHwVBWCHDMm6tl2pjix9S5PT5/Wig7sQb6OjKoIFZKi3GrMiAsWzrYB/uroW2B/wabcEpK7hF7DeDnEC938BD/xUZ0t7KhjszvQvWPkkFuGjfB4qTupOSWgrAjINih3lQmzixXAnKUIu1qbfGVWKPn0bNuf6prdI3XyJrYU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Uhj39+pg; arc=none smtp.client-ip=209.85.218.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Uhj39+pg" Received: by mail-ej1-f53.google.com with SMTP id a640c23a62f3a-abf6f3b836aso455589866b.3; Sat, 08 Mar 2025 10:36:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458962; x=1742063762; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=cL+kwswwn5jzxwsJW9pLiPtPk53udtuocP3ZVoOJwGI=; b=Uhj39+pgtP1riSH+wsi07zdD/C+/SfdW5pl814vDc3/MBe+Ce4Ll5bdIdP2qHU/0O7 pu4bHXFs3kw7Zc8wowXFXGM5Z5jqpqVT7UvpFRh4katAOG4U+5Rc+2EA+L/HBrA06I0J I+CUeVI+UZD6So7EcP+wPpqKDXgicC9FBTAG+PFyMFGzj9IGbzGmRuqhHFnCt8mcjsrn M/yJ9jncJ0evUSYu/Me2PSAXr22Xuzcn6sQT3xPixBcf5oQwVrRGrLSozhJ4erKAuGI5 2uMNY2LWJTZusRxwNZgnIWbv9CW9Wguvs3wKfFn2prasfdDWYOW0ZtK4iNj8tvTHQczy I6mg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458962; x=1742063762; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=cL+kwswwn5jzxwsJW9pLiPtPk53udtuocP3ZVoOJwGI=; b=Ak08wkLmzfgEFDqhgQfwz5lY+QXpveR/FDxkOl1+Yqq9q/Ks4QVuM4hV7q9XpS3oAQ 898iWm8Z7KJwmCirTSNK7F8vJWBCLuqNbnB4xoQOfet5wXAs4Zc9KdvNmfNvmOFCTD2w Xt9Ip27mAnVIVOqkZKZRIr6oV6iweifEARI3Wp59mol/ZeMj7phKk0B6hTeuCeyZjgn8 bWbAqVCAeQ9miEL8zPfb1cFHcB5S1A7a3M1Nt238JDLjSazV/bSZj8gZEg62BV2aXcLY jaxTNWgVN0kv41GXQ6i+BmSylKBsIjLPBTyEa292DEW/jUfir16iR+4eZCEgAKZA8TAK NWcQ== X-Forwarded-Encrypted: i=1; AJvYcCV58l0Erw8RK+rGZwpu0CQ7lli27vwh/G39tr55dYr9++4+dM3NFgh4FZdkwC6Dzs03NBv0odbLfYWD@vger.kernel.org, AJvYcCWCvB37tAFOgcVD2eoNmZO0a4HEkBx/UTzHitYvKNh1jEx1c5gDCE5EWiKOGcjB/T61HriNrgTS7kYwP2KX@vger.kernel.org, AJvYcCWsWMtjgqkQeMKAUvfwLEh6bR5iGPlCvA4cETk1XyviJW6PzSUVEMBhmKZ17HihNukVvf06F7ZRjBX1Hg==@vger.kernel.org, AJvYcCX7g+BGPoQCaZ6sjjzg7nGIUaNFYxNO8XtbaPnWTquFlAxLm9m5Awqp4O44gapgM25I1Ea8Ps1xn6FOcQY=@vger.kernel.org X-Gm-Message-State: AOJu0Yx48RSVlcO1VZh2X9xZ3ZtWq3uDa4STWc/JSvLaoWq3gKHqezRT BYL3lMih4fdC4CyZuLG1JWEivuMBruCrCq2/RgXlTPTtzL1i8PXL X-Gm-Gg: ASbGncu0Jy6Mxj+qePuZEYNeW2ztlqLdfYSpussc1a7DUziNbDLLRPzoCRN31R2tbMx J7uvnswrmA3hXqUXdavc46TZcAiNv/nKxSaPpzg4YUZUHRGID132OmU6rco5cuz63VhznEDr7HO zj7yhFE9BrTxsaGPb4wb5hRhqE9jZwviYcTPf9aQdF0Bj3X6rPaWM81dPYrk36vh9Vk2Fl/vmmQ LALkx/Xkes69YdwysdFnscjumqIzee1Jz2I+FFum9MWs+fi8FbC012scCqXU9R31JkjSFxFEnX3 I3IPpOBQi5gROMRhXeopd6/A/ozyOL6IPG77Cruu6QBgCevHzXn0z0knfg== X-Google-Smtp-Source: AGHT+IF9zZA/uP78oxQN04qBg6JKFTvZVJk9xONUOw7SHitJgE7xQATAtSbohXVnkE66255V4sOErQ== X-Received: by 2002:a17:906:dac2:b0:ac2:c26:5608 with SMTP id a640c23a62f3a-ac252747d18mr773184766b.8.1741458962015; Sat, 08 Mar 2025 10:36:02 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.35.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:36:01 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 22/24] staging: media: remove MAX96712 driver Date: Sat, 8 Mar 2025 20:33:51 +0200 Message-ID: <20250308183410.3013996-23-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Remove the staging MAX96712 driver. Its functionality has been moved to the MAX96724 driver which makes use of the Maxim GMSL2/3 deserializer framework. Signed-off-by: Cosmin Tanislav --- MAINTAINERS | 1 - drivers/staging/media/Kconfig | 2 - drivers/staging/media/Makefile | 1 - drivers/staging/media/max96712/Kconfig | 14 - drivers/staging/media/max96712/Makefile | 2 - drivers/staging/media/max96712/max96712.c | 487 ---------------------- 6 files changed, 507 deletions(-) delete mode 100644 drivers/staging/media/max96712/Kconfig delete mode 100644 drivers/staging/media/max96712/Makefile delete mode 100644 drivers/staging/media/max96712/max96712.c diff --git a/MAINTAINERS b/MAINTAINERS index 1bc0ef81a1f0..7bc80ed9ba00 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14188,7 +14188,6 @@ M: Cosmin Tanislav L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/maxim,max96712.yaml -F: drivers/staging/media/max96712/max96712.c MAX96714 GMSL2 DESERIALIZER DRIVER M: Julien Massot diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index b44214854399..fe29821f64a3 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -28,8 +28,6 @@ source "drivers/staging/media/imx/Kconfig" source "drivers/staging/media/ipu3/Kconfig" -source "drivers/staging/media/max96712/Kconfig" - source "drivers/staging/media/meson/vdec/Kconfig" source "drivers/staging/media/rkvdec/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index ad4e9619a9e0..1a562b3b6881 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -2,7 +2,6 @@ obj-$(CONFIG_VIDEO_ATMEL_ISC_BASE) += deprecated/atmel/ obj-$(CONFIG_INTEL_ATOMISP) += atomisp/ obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/ -obj-$(CONFIG_VIDEO_MAX96712) += max96712/ obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/ obj-$(CONFIG_VIDEO_ROCKCHIP_VDEC) += rkvdec/ obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive/ diff --git a/drivers/staging/media/max96712/Kconfig b/drivers/staging/media/max96712/Kconfig deleted file mode 100644 index 117fadf81bd0..000000000000 --- a/drivers/staging/media/max96712/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config VIDEO_MAX96712 - tristate "Maxim MAX96712 Quad GMSL2 Deserializer support" - depends on I2C - depends on OF_GPIO - depends on VIDEO_DEV - select V4L2_FWNODE - select VIDEO_V4L2_SUBDEV_API - select MEDIA_CONTROLLER - help - This driver supports the Maxim MAX96712 Quad GMSL2 Deserializer. - - To compile this driver as a module, choose M here: the - module will be called max96712. diff --git a/drivers/staging/media/max96712/Makefile b/drivers/staging/media/max96712/Makefile deleted file mode 100644 index 70c1974ce3f0..000000000000 --- a/drivers/staging/media/max96712/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_VIDEO_MAX96712) += max96712.o diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c deleted file mode 100644 index 0751b2e04895..000000000000 --- a/drivers/staging/media/max96712/max96712.c +++ /dev/null @@ -1,487 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim MAX96712 Quad GMSL2 Deserializer Driver - * - * Copyright (C) 2021 Renesas Electronics Corporation - * Copyright (C) 2021 Niklas Söderlund - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define DEBUG_EXTRA_REG 0x09 -#define DEBUG_EXTRA_PCLK_25MHZ 0x00 -#define DEBUG_EXTRA_PCLK_75MHZ 0x01 - -enum max96712_pattern { - MAX96712_PATTERN_CHECKERBOARD = 0, - MAX96712_PATTERN_GRADIENT, -}; - -struct max96712_info { - unsigned int dpllfreq; - bool have_debug_extra; -}; - -struct max96712_priv { - struct i2c_client *client; - struct regmap *regmap; - struct gpio_desc *gpiod_pwdn; - - const struct max96712_info *info; - - bool cphy; - struct v4l2_mbus_config_mipi_csi2 mipi; - - struct v4l2_subdev sd; - struct v4l2_ctrl_handler ctrl_handler; - struct media_pad pads[1]; - - enum max96712_pattern pattern; -}; - -static int max96712_write(struct max96712_priv *priv, unsigned int reg, u8 val) -{ - int ret; - - ret = regmap_write(priv->regmap, reg, val); - if (ret) - dev_err(&priv->client->dev, "write 0x%04x failed\n", reg); - - return ret; -} - -static int max96712_update_bits(struct max96712_priv *priv, unsigned int reg, - u8 mask, u8 val) -{ - int ret; - - ret = regmap_update_bits(priv->regmap, reg, mask, val); - if (ret) - dev_err(&priv->client->dev, "update 0x%04x failed\n", reg); - - return ret; -} - -static int max96712_write_bulk(struct max96712_priv *priv, unsigned int reg, - const void *val, size_t val_count) -{ - int ret; - - ret = regmap_bulk_write(priv->regmap, reg, val, val_count); - if (ret) - dev_err(&priv->client->dev, "bulk write 0x%04x failed\n", reg); - - return ret; -} - -static int max96712_write_bulk_value(struct max96712_priv *priv, - unsigned int reg, unsigned int val, - size_t val_count) -{ - unsigned int i; - u8 values[4]; - - for (i = 1; i <= val_count; i++) - values[i - 1] = (val >> ((val_count - i) * 8)) & 0xff; - - return max96712_write_bulk(priv, reg, &values, val_count); -} - -static void max96712_reset(struct max96712_priv *priv) -{ - max96712_update_bits(priv, 0x13, 0x40, 0x40); - msleep(20); -} - -static void max96712_mipi_enable(struct max96712_priv *priv, bool enable) -{ - if (enable) { - max96712_update_bits(priv, 0x40b, 0x02, 0x02); - max96712_update_bits(priv, 0x8a0, 0x80, 0x80); - } else { - max96712_update_bits(priv, 0x8a0, 0x80, 0x00); - max96712_update_bits(priv, 0x40b, 0x02, 0x00); - } -} - -static void max96712_mipi_configure(struct max96712_priv *priv) -{ - unsigned int i; - u8 phy5 = 0; - - max96712_mipi_enable(priv, false); - - /* Select 2x4 mode. */ - max96712_write(priv, 0x8a0, 0x04); - - /* TODO: Add support for 2-lane and 1-lane configurations. */ - if (priv->cphy) { - /* Configure a 3-lane C-PHY using PHY0 and PHY1. */ - max96712_write(priv, 0x94a, 0xa0); - - /* Configure C-PHY timings. */ - max96712_write(priv, 0x8ad, 0x3f); - max96712_write(priv, 0x8ae, 0x7d); - } else { - /* Configure a 4-lane D-PHY using PHY0 and PHY1. */ - max96712_write(priv, 0x94a, 0xc0); - } - - /* Configure lane mapping for PHY0 and PHY1. */ - /* TODO: Add support for lane swapping. */ - max96712_write(priv, 0x8a3, 0xe4); - - /* Configure lane polarity for PHY0 and PHY1. */ - for (i = 0; i < priv->mipi.num_data_lanes + 1; i++) - if (priv->mipi.lane_polarities[i]) - phy5 |= BIT(i == 0 ? 5 : i < 3 ? i - 1 : i); - max96712_write(priv, 0x8a5, phy5); - - /* Set link frequency for PHY0 and PHY1. */ - max96712_update_bits(priv, 0x415, 0x3f, - ((priv->info->dpllfreq / 100) & 0x1f) | BIT(5)); - max96712_update_bits(priv, 0x418, 0x3f, - ((priv->info->dpllfreq / 100) & 0x1f) | BIT(5)); - - /* Enable PHY0 and PHY1 */ - max96712_update_bits(priv, 0x8a2, 0xf0, 0x30); -} - -static void max96712_pattern_enable(struct max96712_priv *priv, bool enable) -{ - const u32 h_active = 1920; - const u32 h_fp = 88; - const u32 h_sw = 44; - const u32 h_bp = 148; - const u32 h_tot = h_active + h_fp + h_sw + h_bp; - - const u32 v_active = 1080; - const u32 v_fp = 4; - const u32 v_sw = 5; - const u32 v_bp = 36; - const u32 v_tot = v_active + v_fp + v_sw + v_bp; - - if (!enable) { - max96712_write(priv, 0x1051, 0x00); - return; - } - - /* Set PCLK to 75MHz if device have DEBUG_EXTRA register. */ - if (priv->info->have_debug_extra) - max96712_write(priv, DEBUG_EXTRA_REG, DEBUG_EXTRA_PCLK_75MHZ); - - /* Configure Video Timing Generator for 1920x1080 @ 30 fps. */ - max96712_write_bulk_value(priv, 0x1052, 0, 3); - max96712_write_bulk_value(priv, 0x1055, v_sw * h_tot, 3); - max96712_write_bulk_value(priv, 0x1058, - (v_active + v_fp + + v_bp) * h_tot, 3); - max96712_write_bulk_value(priv, 0x105b, 0, 3); - max96712_write_bulk_value(priv, 0x105e, h_sw, 2); - max96712_write_bulk_value(priv, 0x1060, h_active + h_fp + h_bp, 2); - max96712_write_bulk_value(priv, 0x1062, v_tot, 2); - max96712_write_bulk_value(priv, 0x1064, - h_tot * (v_sw + v_bp) + (h_sw + h_bp), 3); - max96712_write_bulk_value(priv, 0x1067, h_active, 2); - max96712_write_bulk_value(priv, 0x1069, h_fp + h_sw + h_bp, 2); - max96712_write_bulk_value(priv, 0x106b, v_active, 2); - - /* Generate VS, HS and DE in free-running mode. */ - max96712_write(priv, 0x1050, 0xfb); - - /* Configure Video Pattern Generator. */ - if (priv->pattern == MAX96712_PATTERN_CHECKERBOARD) { - /* Set checkerboard pattern size. */ - max96712_write(priv, 0x1074, 0x3c); - max96712_write(priv, 0x1075, 0x3c); - max96712_write(priv, 0x1076, 0x3c); - - /* Set checkerboard pattern colors. */ - max96712_write_bulk_value(priv, 0x106e, 0xfecc00, 3); - max96712_write_bulk_value(priv, 0x1071, 0x006aa7, 3); - - /* Generate checkerboard pattern. */ - max96712_write(priv, 0x1051, 0x10); - } else { - /* Set gradient increment. */ - max96712_write(priv, 0x106d, 0x10); - - /* Generate gradient pattern. */ - max96712_write(priv, 0x1051, 0x20); - } -} - -static int max96712_s_stream(struct v4l2_subdev *sd, int enable) -{ - struct max96712_priv *priv = v4l2_get_subdevdata(sd); - - if (enable) { - max96712_pattern_enable(priv, true); - max96712_mipi_enable(priv, true); - } else { - max96712_mipi_enable(priv, false); - max96712_pattern_enable(priv, false); - } - - return 0; -} - -static const struct v4l2_subdev_video_ops max96712_video_ops = { - .s_stream = max96712_s_stream, -}; - -static int max96712_init_state(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state) -{ - static const struct v4l2_mbus_framefmt default_fmt = { - .width = 1920, - .height = 1080, - .code = MEDIA_BUS_FMT_RGB888_1X24, - .colorspace = V4L2_COLORSPACE_SRGB, - .field = V4L2_FIELD_NONE, - .ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT, - .quantization = V4L2_QUANTIZATION_DEFAULT, - .xfer_func = V4L2_XFER_FUNC_DEFAULT, - }; - struct v4l2_mbus_framefmt *fmt; - - fmt = v4l2_subdev_state_get_format(state, 0); - *fmt = default_fmt; - - return 0; -} - -static const struct v4l2_subdev_internal_ops max96712_internal_ops = { - .init_state = max96712_init_state, -}; - -static const struct v4l2_subdev_pad_ops max96712_pad_ops = { - .get_fmt = v4l2_subdev_get_fmt, - .set_fmt = v4l2_subdev_get_fmt, -}; - -static const struct v4l2_subdev_ops max96712_subdev_ops = { - .video = &max96712_video_ops, - .pad = &max96712_pad_ops, -}; - -static const char * const max96712_test_pattern[] = { - "Checkerboard", - "Gradient", -}; - -static int max96712_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct max96712_priv *priv = - container_of(ctrl->handler, struct max96712_priv, ctrl_handler); - - switch (ctrl->id) { - case V4L2_CID_TEST_PATTERN: - priv->pattern = ctrl->val ? - MAX96712_PATTERN_GRADIENT : - MAX96712_PATTERN_CHECKERBOARD; - break; - } - return 0; -} - -static const struct v4l2_ctrl_ops max96712_ctrl_ops = { - .s_ctrl = max96712_s_ctrl, -}; - -static int max96712_v4l2_register(struct max96712_priv *priv) -{ - long pixel_rate; - int ret; - - priv->sd.internal_ops = &max96712_internal_ops; - v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96712_subdev_ops); - priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; - priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; - - v4l2_ctrl_handler_init(&priv->ctrl_handler, 2); - - /* - * TODO: Once V4L2_CID_LINK_FREQ is changed from a menu control to an - * INT64 control it should be used here instead of V4L2_CID_PIXEL_RATE. - */ - pixel_rate = priv->info->dpllfreq / priv->mipi.num_data_lanes * 1000000; - v4l2_ctrl_new_std(&priv->ctrl_handler, NULL, V4L2_CID_PIXEL_RATE, - pixel_rate, pixel_rate, 1, pixel_rate); - - v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, &max96712_ctrl_ops, - V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(max96712_test_pattern) - 1, - 0, 0, max96712_test_pattern); - - priv->sd.ctrl_handler = &priv->ctrl_handler; - ret = priv->ctrl_handler.error; - if (ret) - goto error; - - priv->pads[0].flags = MEDIA_PAD_FL_SOURCE; - ret = media_entity_pads_init(&priv->sd.entity, 1, priv->pads); - if (ret) - goto error; - - v4l2_set_subdevdata(&priv->sd, priv); - - priv->sd.state_lock = priv->ctrl_handler.lock; - ret = v4l2_subdev_init_finalize(&priv->sd); - if (ret) - goto error; - - ret = v4l2_async_register_subdev(&priv->sd); - if (ret < 0) { - dev_err(&priv->client->dev, "Unable to register subdevice\n"); - goto error; - } - - return 0; -error: - v4l2_ctrl_handler_free(&priv->ctrl_handler); - - return ret; -} - -static int max96712_parse_dt(struct max96712_priv *priv) -{ - struct fwnode_handle *ep; - struct v4l2_fwnode_endpoint v4l2_ep = { - .bus_type = V4L2_MBUS_UNKNOWN, - }; - unsigned int supported_lanes; - int ret; - - ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(&priv->client->dev), 4, - 0, 0); - if (!ep) { - dev_err(&priv->client->dev, "Not connected to subdevice\n"); - return -EINVAL; - } - - ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep); - fwnode_handle_put(ep); - if (ret) { - dev_err(&priv->client->dev, "Could not parse v4l2 endpoint\n"); - return -EINVAL; - } - - switch (v4l2_ep.bus_type) { - case V4L2_MBUS_CSI2_DPHY: - supported_lanes = 4; - priv->cphy = false; - break; - case V4L2_MBUS_CSI2_CPHY: - supported_lanes = 3; - priv->cphy = true; - break; - default: - dev_err(&priv->client->dev, "Unsupported bus-type %u\n", - v4l2_ep.bus_type); - return -EINVAL; - } - - if (v4l2_ep.bus.mipi_csi2.num_data_lanes != supported_lanes) { - dev_err(&priv->client->dev, "Only %u data lanes supported\n", - supported_lanes); - return -EINVAL; - } - - priv->mipi = v4l2_ep.bus.mipi_csi2; - - return 0; -} - -static const struct regmap_config max96712_i2c_regmap = { - .reg_bits = 16, - .val_bits = 8, - .max_register = 0x1f00, -}; - -static int max96712_probe(struct i2c_client *client) -{ - struct max96712_priv *priv; - int ret; - - priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->info = of_device_get_match_data(&client->dev); - - priv->client = client; - - priv->regmap = devm_regmap_init_i2c(client, &max96712_i2c_regmap); - if (IS_ERR(priv->regmap)) - return PTR_ERR(priv->regmap); - - priv->gpiod_pwdn = devm_gpiod_get_optional(&client->dev, "enable", - GPIOD_OUT_HIGH); - if (IS_ERR(priv->gpiod_pwdn)) - return PTR_ERR(priv->gpiod_pwdn); - - gpiod_set_consumer_name(priv->gpiod_pwdn, "max96712-pwdn"); - gpiod_set_value_cansleep(priv->gpiod_pwdn, 1); - - if (priv->gpiod_pwdn) - usleep_range(4000, 5000); - - max96712_reset(priv); - - ret = max96712_parse_dt(priv); - if (ret) - return ret; - - max96712_mipi_configure(priv); - - return max96712_v4l2_register(priv); -} - -static void max96712_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct max96712_priv *priv = container_of(sd, struct max96712_priv, sd); - - v4l2_async_unregister_subdev(&priv->sd); - - gpiod_set_value_cansleep(priv->gpiod_pwdn, 0); -} - -static const struct max96712_info max96712_info_max96712 = { - .dpllfreq = 1000, - .have_debug_extra = true, -}; - -static const struct max96712_info max96712_info_max96724 = { - .dpllfreq = 1200, -}; - -static const struct of_device_id max96712_of_table[] = { - { .compatible = "maxim,max96712", .data = &max96712_info_max96712 }, - { .compatible = "maxim,max96724", .data = &max96712_info_max96724 }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, max96712_of_table); - -static struct i2c_driver max96712_i2c_driver = { - .driver = { - .name = "max96712", - .of_match_table = of_match_ptr(max96712_of_table), - }, - .probe = max96712_probe, - .remove = max96712_remove, -}; - -module_i2c_driver(max96712_i2c_driver); - -MODULE_DESCRIPTION("Maxim MAX96712 Quad GMSL2 Deserializer Driver"); -MODULE_AUTHOR("Niklas Söderlund "); -MODULE_LICENSE("GPL"); From patchwork Sat Mar 8 18:33:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 871779 Received: from mail-ed1-f44.google.com (mail-ed1-f44.google.com [209.85.208.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D43C01EFF90; Sat, 8 Mar 2025 18:36:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458971; cv=none; b=HKsyBpuV9aqw1FAUXzCZfY0uUrIWo6V9do3Hk/yu3llypaCau9eERULpgq6ILrvuLxKBxVgpWgL3Hca/U3Yw3Iu6UECacWg2dseUru81Z4dkbYt9s3B6mSw77jGoMgrDFKQX3opE1GWWcly0bGNZBNEDp63/PUkPpMg6QMmQ2Dc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458971; c=relaxed/simple; bh=N9tZtzB3JNubNQ21fGAy8Or2S5w0yK8XP6lJ6gm03FU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=N1Vl/Ny2t9BH+9ti7/1Xr5pzvH3Y8JYXQjXvaC5E3i3j2MehHVCoXOTsvkkVoRqXNypZQnuwYiMnHddrR17oUmnFaCpMZX41rdd5UbXBguUEDKoJC7xe3aCkk8Q9SQGuzKlWfJAkgCJVETsL/Uh8E+FYvUertFflPU2nNpfKhKU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kmnaqr7X; arc=none smtp.client-ip=209.85.208.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kmnaqr7X" Received: by mail-ed1-f44.google.com with SMTP id 4fb4d7f45d1cf-5dc89df7eccso4828775a12.3; Sat, 08 Mar 2025 10:36:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458966; x=1742063766; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=RnzBETPmS9JtJNsZIrqFeOhiDr5eXlybCWh27IOxDlo=; b=kmnaqr7XXgqwye47bzGMMrLJs/iiFedn+PYu4U+SoZQGoxgYOU2e1E4MJx52RophNb CUzi4O2nqCpJntd9sxpkgaCaZskfmDOy6gyi3LROljMjXYyGKGK/vK2rKcNRCqTZVhvb ymVkEig+oojYZo/FGig5T1wDxwXKRVq0CiRIk4/B9bla5RzdblLIYYL6vyAOodeeUug8 +lGXaROu/7FRnAeEVuavpOqDefuzHubwDYCUD1mgmhPt1JMUY4G8YLccgYp9D5ewwT4L CJ3TTAYbcmdh/EQWto26RmH8OiI168vSlBLgN7YLZVtKybe2frXH7hjgkg/YSuFhLjFO 1Qpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458966; x=1742063766; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RnzBETPmS9JtJNsZIrqFeOhiDr5eXlybCWh27IOxDlo=; b=rQf0Vn9py9ZGlXrDB4oOHeAzJGkL6b46tXCZBSARAnsGkbbMLm8WGgx4RZoVjQmocE jDGEJmDMm7cxYr5ovr3aj23GWwwV7OHj10labeHYx6NVaFgz64hTdlXnUJBxhyM/dVmD C4t9vcJqk79EbG48XdO3URPIz2WhItFEDOTNpIzRr/3ueAojwrbMkIGowJ00bsX/F2c6 ywUSjCjiqmWNmMjhnmE/JIkumvGaNc3kHPQfd87tB/VSbi8JJWe3kd3nvdltAQwJFQL9 k8OB2hXJkkHB1xQkeDo26tCoBG/GxXXvK8/LZEVV9b9pQFifuH2acKG9n5+xS4TfA4u7 fogg== X-Forwarded-Encrypted: i=1; AJvYcCUEJcM7yfd5q0Wrf1zr6WdHxLy2mn5brXp/WTfxo9FDRYAssuaHbF2cTh3M0ZvjEuMwmOkbaz6fqtp33g==@vger.kernel.org, AJvYcCWCR/T5UslcbrgYS3Wn5X1ePj9RgDc4IlYBkdh7RfNdo0NF/fAblk9zhJN15tNDnRT1nAwm6IQ/KYYz1Ot4@vger.kernel.org, AJvYcCWv+0XrTloPWwfnAxRIljGKzltKJPN0gIniKQWNi0xxm25Y8e01JxPOqQCttsnozwn8Mn4dMNzHWlgTZkw=@vger.kernel.org, AJvYcCXc7futqaNznTI3W1PTg3Qyvgv73grVE/kBCT5BFRBeIvMFKom91ZBNulUxsaactzheyNSgoE2NbXHc@vger.kernel.org X-Gm-Message-State: AOJu0YyffodAc0jY9zHu5NINDQAz3KzMLMaMBcpbyS/r1C/Z6U0jSBfQ sbulIpL79AQC3xumkBtknltj4NN0hJu5cvYgBvY7hdctecZKvi8ZCMTkwCep X-Gm-Gg: ASbGncsQFIS3JHyHrbbS+krbTdRSHHNimIFC+jhkmJct+Z2kcHojBs0Ai10b6cigNjY snbGGfamCJry1YdZfz2OFMiZfd/8mc0YXNypAG8VmRtKVKgcaf767ZnFIsxUcDKuPLrh5QEGkPP 3RSa1rzshTbl+Q5DqejV3FXDWGC3x+9//OOKyrsdQck16uUE/KOb1+18TZSKEltK6njMi/C5LYl SrEjqGYCfYJhp5744+oVGSLWdqsJec19pDlcEbzxDrPQGT/V0XmPyEGslLGXa+DGOxBPmViOUZF Rhg/iKBru6Q3bYFibUNOQewckjLqIpt9fhILD1vM4AVvjPtdca5VvAMXDlL4fyYGs2Bi X-Google-Smtp-Source: AGHT+IEaLD/4z0VjX5T4LQ02RirJxDRRBuuPd+JilneR+6AgjebhzHK9uAsmoggoR4SH+9tUfxXkLQ== X-Received: by 2002:a17:906:dc8e:b0:abf:439b:6ba5 with SMTP id a640c23a62f3a-ac252ba18e5mr811671266b.43.1741458965744; Sat, 08 Mar 2025 10:36:05 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.36.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:36:05 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 23/24] media: i2c: remove MAX96717 driver Date: Sat, 8 Mar 2025 20:33:52 +0200 Message-ID: <20250308183410.3013996-24-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The previous MAX96717 driver has been removed and its functionality has been moved to a MAX96717 driver which makes use of the Maxim GMSL2/3 serializer framework. Signed-off-by: Cosmin Tanislav --- MAINTAINERS | 1 - drivers/media/i2c/Kconfig | 17 - drivers/media/i2c/Makefile | 1 - drivers/media/i2c/max96717.c | 1103 ---------------------------------- 4 files changed, 1122 deletions(-) delete mode 100644 drivers/media/i2c/max96717.c diff --git a/MAINTAINERS b/MAINTAINERS index 7bc80ed9ba00..12078126f478 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14204,7 +14204,6 @@ L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/maxim,max96717-pinctrl.yaml F: Documentation/devicetree/bindings/media/i2c/maxim,max96717.yaml -F: drivers/media/i2c/max96717.c MAX9860 MONO AUDIO VOICE CODEC DRIVER M: Peter Rosin diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index e24c84962c92..6c595dffb280 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1636,23 +1636,6 @@ config VIDEO_MAX96714 To compile this driver as a module, choose M here: the module will be called max96714. -config VIDEO_MAX96717 - tristate "Maxim MAX96717 GMSL2 Serializer support" - depends on OF && I2C && VIDEO_DEV && COMMON_CLK - select I2C_MUX - select MEDIA_CONTROLLER - select GPIOLIB - select V4L2_CCI_I2C - select V4L2_FWNODE - select VIDEO_V4L2_SUBDEV_API - help - Device driver for the Maxim MAX96717 GMSL2 Serializer. - MAX96717 serializers convert video on a MIPI CSI-2 - input to a GMSL2 output. - - To compile this driver as a module, choose M here: the - module will be called max96717. - source "drivers/media/i2c/maxim-serdes/Kconfig" endmenu diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index b24e7cf7bb2f..de0680ebf190 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -69,7 +69,6 @@ obj-$(CONFIG_VIDEO_M52790) += m52790.o obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o obj-$(CONFIG_VIDEO_MAX9286) += max9286.o obj-$(CONFIG_VIDEO_MAX96714) += max96714.o -obj-$(CONFIG_VIDEO_MAX96717) += max96717.o obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim-serdes/ obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o diff --git a/drivers/media/i2c/max96717.c b/drivers/media/i2c/max96717.c deleted file mode 100644 index 9259d58ba734..000000000000 --- a/drivers/media/i2c/max96717.c +++ /dev/null @@ -1,1103 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim GMSL2 Serializer Driver - * - * Copyright (C) 2024 Collabora Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define MAX96717_DEVICE_ID 0xbf -#define MAX96717F_DEVICE_ID 0xc8 -#define MAX96717_PORTS 2 -#define MAX96717_PAD_SINK 0 -#define MAX96717_PAD_SOURCE 1 -#define MAX96717_CSI_NLANES 4 - -#define MAX96717_DEFAULT_CLKOUT_RATE 24000000UL - -/* DEV */ -#define MAX96717_REG3 CCI_REG8(0x3) -#define MAX96717_RCLKSEL GENMASK(1, 0) -#define RCLKSEL_REF_PLL CCI_REG8(0x3) -#define MAX96717_REG6 CCI_REG8(0x6) -#define RCLKEN BIT(5) -#define MAX96717_DEV_ID CCI_REG8(0xd) -#define MAX96717_DEV_REV CCI_REG8(0xe) -#define MAX96717_DEV_REV_MASK GENMASK(3, 0) - -/* VID_TX Z */ -#define MAX96717_VIDEO_TX0 CCI_REG8(0x110) -#define MAX96717_VIDEO_AUTO_BPP BIT(3) -#define MAX96717_VIDEO_TX2 CCI_REG8(0x112) -#define MAX96717_VIDEO_PCLKDET BIT(7) - -/* VTX_Z */ -#define MAX96717_VTX0 CCI_REG8(0x24e) -#define MAX96717_VTX1 CCI_REG8(0x24f) -#define MAX96717_PATTERN_CLK_FREQ GENMASK(3, 1) -#define MAX96717_VTX_VS_DLY CCI_REG24(0x250) -#define MAX96717_VTX_VS_HIGH CCI_REG24(0x253) -#define MAX96717_VTX_VS_LOW CCI_REG24(0x256) -#define MAX96717_VTX_V2H CCI_REG24(0x259) -#define MAX96717_VTX_HS_HIGH CCI_REG16(0x25c) -#define MAX96717_VTX_HS_LOW CCI_REG16(0x25e) -#define MAX96717_VTX_HS_CNT CCI_REG16(0x260) -#define MAX96717_VTX_V2D CCI_REG24(0x262) -#define MAX96717_VTX_DE_HIGH CCI_REG16(0x265) -#define MAX96717_VTX_DE_LOW CCI_REG16(0x267) -#define MAX96717_VTX_DE_CNT CCI_REG16(0x269) -#define MAX96717_VTX29 CCI_REG8(0x26b) -#define MAX96717_VTX_MODE GENMASK(1, 0) -#define MAX96717_VTX_GRAD_INC CCI_REG8(0x26c) -#define MAX96717_VTX_CHKB_COLOR_A CCI_REG24(0x26d) -#define MAX96717_VTX_CHKB_COLOR_B CCI_REG24(0x270) -#define MAX96717_VTX_CHKB_RPT_CNT_A CCI_REG8(0x273) -#define MAX96717_VTX_CHKB_RPT_CNT_B CCI_REG8(0x274) -#define MAX96717_VTX_CHKB_ALT CCI_REG8(0x275) - -/* GPIO */ -#define MAX96717_NUM_GPIO 11 -#define MAX96717_GPIO_REG_A(gpio) CCI_REG8(0x2be + (gpio) * 3) -#define MAX96717_GPIO_OUT BIT(4) -#define MAX96717_GPIO_IN BIT(3) -#define MAX96717_GPIO_RX_EN BIT(2) -#define MAX96717_GPIO_TX_EN BIT(1) -#define MAX96717_GPIO_OUT_DIS BIT(0) - -/* FRONTTOP */ -/* MAX96717 only have CSI port 'B' */ -#define MAX96717_FRONTOP0 CCI_REG8(0x308) -#define MAX96717_START_PORT_B BIT(5) - -/* MIPI_RX */ -#define MAX96717_MIPI_RX1 CCI_REG8(0x331) -#define MAX96717_MIPI_LANES_CNT GENMASK(5, 4) -#define MAX96717_MIPI_RX2 CCI_REG8(0x332) /* phy1 Lanes map */ -#define MAX96717_PHY2_LANES_MAP GENMASK(7, 4) -#define MAX96717_MIPI_RX3 CCI_REG8(0x333) /* phy2 Lanes map */ -#define MAX96717_PHY1_LANES_MAP GENMASK(3, 0) -#define MAX96717_MIPI_RX4 CCI_REG8(0x334) /* phy1 lane polarities */ -#define MAX96717_PHY1_LANES_POL GENMASK(6, 4) -#define MAX96717_MIPI_RX5 CCI_REG8(0x335) /* phy2 lane polarities */ -#define MAX96717_PHY2_LANES_POL GENMASK(2, 0) - -/* MIPI_RX_EXT */ -#define MAX96717_MIPI_RX_EXT11 CCI_REG8(0x383) -#define MAX96717_TUN_MODE BIT(7) - -/* REF_VTG */ -#define REF_VTG0 CCI_REG8(0x3f0) -#define REFGEN_PREDEF_EN BIT(6) -#define REFGEN_PREDEF_FREQ_MASK GENMASK(5, 4) -#define REFGEN_PREDEF_FREQ_ALT BIT(3) -#define REFGEN_RST BIT(1) -#define REFGEN_EN BIT(0) - -/* MISC */ -#define PIO_SLEW_1 CCI_REG8(0x570) - -enum max96717_vpg_mode { - MAX96717_VPG_DISABLED = 0, - MAX96717_VPG_CHECKERBOARD = 1, - MAX96717_VPG_GRADIENT = 2, -}; - -struct max96717_priv { - struct i2c_client *client; - struct regmap *regmap; - struct i2c_mux_core *mux; - struct v4l2_mbus_config_mipi_csi2 mipi_csi2; - struct v4l2_subdev sd; - struct media_pad pads[MAX96717_PORTS]; - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_async_notifier notifier; - struct v4l2_subdev *source_sd; - u16 source_sd_pad; - u64 enabled_source_streams; - u8 pll_predef_index; - struct clk_hw clk_hw; - struct gpio_chip gpio_chip; - enum max96717_vpg_mode pattern; -}; - -static inline struct max96717_priv *sd_to_max96717(struct v4l2_subdev *sd) -{ - return container_of(sd, struct max96717_priv, sd); -} - -static inline struct max96717_priv *clk_hw_to_max96717(struct clk_hw *hw) -{ - return container_of(hw, struct max96717_priv, clk_hw); -} - -static int max96717_i2c_mux_select(struct i2c_mux_core *mux, u32 chan) -{ - return 0; -} - -static int max96717_i2c_mux_init(struct max96717_priv *priv) -{ - priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev, - 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE, - max96717_i2c_mux_select, NULL); - if (!priv->mux) - return -ENOMEM; - - return i2c_mux_add_adapter(priv->mux, 0, 0); -} - -static inline int max96717_start_csi(struct max96717_priv *priv, bool start) -{ - return cci_update_bits(priv->regmap, MAX96717_FRONTOP0, - MAX96717_START_PORT_B, - start ? MAX96717_START_PORT_B : 0, NULL); -} - -static int max96717_apply_patgen_timing(struct max96717_priv *priv, - struct v4l2_subdev_state *state) -{ - struct v4l2_mbus_framefmt *fmt = - v4l2_subdev_state_get_format(state, MAX96717_PAD_SOURCE); - const u32 h_active = fmt->width; - const u32 h_fp = 88; - const u32 h_sw = 44; - const u32 h_bp = 148; - u32 h_tot; - const u32 v_active = fmt->height; - const u32 v_fp = 4; - const u32 v_sw = 5; - const u32 v_bp = 36; - u32 v_tot; - int ret = 0; - - h_tot = h_active + h_fp + h_sw + h_bp; - v_tot = v_active + v_fp + v_sw + v_bp; - - /* 75 Mhz pixel clock */ - cci_update_bits(priv->regmap, MAX96717_VTX1, - MAX96717_PATTERN_CLK_FREQ, 0xa, &ret); - - dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height, - fmt->width); - - cci_write(priv->regmap, MAX96717_VTX_VS_DLY, 0, &ret); - cci_write(priv->regmap, MAX96717_VTX_VS_HIGH, v_sw * h_tot, &ret); - cci_write(priv->regmap, MAX96717_VTX_VS_LOW, - (v_active + v_fp + v_bp) * h_tot, &ret); - cci_write(priv->regmap, MAX96717_VTX_HS_HIGH, h_sw, &ret); - cci_write(priv->regmap, MAX96717_VTX_HS_LOW, h_active + h_fp + h_bp, - &ret); - cci_write(priv->regmap, MAX96717_VTX_V2D, - h_tot * (v_sw + v_bp) + (h_sw + h_bp), &ret); - cci_write(priv->regmap, MAX96717_VTX_HS_CNT, v_tot, &ret); - cci_write(priv->regmap, MAX96717_VTX_DE_HIGH, h_active, &ret); - cci_write(priv->regmap, MAX96717_VTX_DE_LOW, h_fp + h_sw + h_bp, - &ret); - cci_write(priv->regmap, MAX96717_VTX_DE_CNT, v_active, &ret); - /* B G R */ - cci_write(priv->regmap, MAX96717_VTX_CHKB_COLOR_A, 0xfecc00, &ret); - /* B G R */ - cci_write(priv->regmap, MAX96717_VTX_CHKB_COLOR_B, 0x006aa7, &ret); - cci_write(priv->regmap, MAX96717_VTX_CHKB_RPT_CNT_A, 0x3c, &ret); - cci_write(priv->regmap, MAX96717_VTX_CHKB_RPT_CNT_B, 0x3c, &ret); - cci_write(priv->regmap, MAX96717_VTX_CHKB_ALT, 0x3c, &ret); - cci_write(priv->regmap, MAX96717_VTX_GRAD_INC, 0x10, &ret); - - return ret; -} - -static int max96717_apply_patgen(struct max96717_priv *priv, - struct v4l2_subdev_state *state) -{ - unsigned int val; - int ret = 0; - - if (priv->pattern) - ret = max96717_apply_patgen_timing(priv, state); - - cci_write(priv->regmap, MAX96717_VTX0, priv->pattern ? 0xfb : 0, - &ret); - - val = FIELD_PREP(MAX96717_VTX_MODE, priv->pattern); - cci_update_bits(priv->regmap, MAX96717_VTX29, MAX96717_VTX_MODE, - val, &ret); - return ret; -} - -static int max96717_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct max96717_priv *priv = - container_of(ctrl->handler, struct max96717_priv, ctrl_handler); - int ret; - - switch (ctrl->id) { - case V4L2_CID_TEST_PATTERN: - if (priv->enabled_source_streams) - return -EBUSY; - priv->pattern = ctrl->val; - break; - default: - return -EINVAL; - } - - /* Use bpp from bpp register */ - ret = cci_update_bits(priv->regmap, MAX96717_VIDEO_TX0, - MAX96717_VIDEO_AUTO_BPP, - priv->pattern ? 0 : MAX96717_VIDEO_AUTO_BPP, - NULL); - - /* - * Pattern generator doesn't work with tunnel mode. - * Needs RGB color format and deserializer tunnel mode must be disabled. - */ - return cci_update_bits(priv->regmap, MAX96717_MIPI_RX_EXT11, - MAX96717_TUN_MODE, - priv->pattern ? 0 : MAX96717_TUN_MODE, &ret); -} - -static const char * const max96717_test_pattern[] = { - "Disabled", - "Checkerboard", - "Gradient" -}; - -static const struct v4l2_ctrl_ops max96717_ctrl_ops = { - .s_ctrl = max96717_s_ctrl, -}; - -static int max96717_gpiochip_get(struct gpio_chip *gpiochip, - unsigned int offset) -{ - struct max96717_priv *priv = gpiochip_get_data(gpiochip); - u64 val; - int ret; - - ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset), - &val, NULL); - if (ret) - return ret; - - if (val & MAX96717_GPIO_OUT_DIS) - return !!(val & MAX96717_GPIO_IN); - else - return !!(val & MAX96717_GPIO_OUT); -} - -static void max96717_gpiochip_set(struct gpio_chip *gpiochip, - unsigned int offset, int value) -{ - struct max96717_priv *priv = gpiochip_get_data(gpiochip); - - cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset), - MAX96717_GPIO_OUT, MAX96717_GPIO_OUT, NULL); -} - -static int max96717_gpio_get_direction(struct gpio_chip *gpiochip, - unsigned int offset) -{ - struct max96717_priv *priv = gpiochip_get_data(gpiochip); - u64 val; - int ret; - - ret = cci_read(priv->regmap, MAX96717_GPIO_REG_A(offset), &val, NULL); - if (ret < 0) - return ret; - - return !!(val & MAX96717_GPIO_OUT_DIS); -} - -static int max96717_gpio_direction_out(struct gpio_chip *gpiochip, - unsigned int offset, int value) -{ - struct max96717_priv *priv = gpiochip_get_data(gpiochip); - - return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset), - MAX96717_GPIO_OUT_DIS | MAX96717_GPIO_OUT, - value ? MAX96717_GPIO_OUT : 0, NULL); -} - -static int max96717_gpio_direction_in(struct gpio_chip *gpiochip, - unsigned int offset) -{ - struct max96717_priv *priv = gpiochip_get_data(gpiochip); - - return cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(offset), - MAX96717_GPIO_OUT_DIS, MAX96717_GPIO_OUT_DIS, - NULL); -} - -static int max96717_gpiochip_probe(struct max96717_priv *priv) -{ - struct device *dev = &priv->client->dev; - struct gpio_chip *gc = &priv->gpio_chip; - int i, ret = 0; - - gc->label = dev_name(dev); - gc->parent = dev; - gc->owner = THIS_MODULE; - gc->ngpio = MAX96717_NUM_GPIO; - gc->base = -1; - gc->can_sleep = true; - gc->get_direction = max96717_gpio_get_direction; - gc->direction_input = max96717_gpio_direction_in; - gc->direction_output = max96717_gpio_direction_out; - gc->set = max96717_gpiochip_set; - gc->get = max96717_gpiochip_get; - gc->of_gpio_n_cells = 2; - - /* Disable GPIO forwarding */ - for (i = 0; i < gc->ngpio; i++) - cci_update_bits(priv->regmap, MAX96717_GPIO_REG_A(i), - MAX96717_GPIO_RX_EN | MAX96717_GPIO_TX_EN, - 0, &ret); - - if (ret) - return ret; - - ret = devm_gpiochip_add_data(dev, gc, priv); - if (ret) { - dev_err(dev, "Unable to create gpio_chip\n"); - return ret; - } - - return 0; -} - -static int _max96717_set_routing(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - struct v4l2_subdev_krouting *routing) -{ - static const struct v4l2_mbus_framefmt format = { - .width = 1280, - .height = 1080, - .code = MEDIA_BUS_FMT_Y8_1X8, - .field = V4L2_FIELD_NONE, - }; - int ret; - - ret = v4l2_subdev_routing_validate(sd, routing, - V4L2_SUBDEV_ROUTING_ONLY_1_TO_1); - if (ret) - return ret; - - ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format); - if (ret) - return ret; - - return 0; -} - -static int max96717_set_routing(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - enum v4l2_subdev_format_whence which, - struct v4l2_subdev_krouting *routing) -{ - struct max96717_priv *priv = sd_to_max96717(sd); - - if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams) - return -EBUSY; - - return _max96717_set_routing(sd, state, routing); -} - -static int max96717_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - struct v4l2_subdev_format *format) -{ - struct max96717_priv *priv = sd_to_max96717(sd); - struct v4l2_mbus_framefmt *fmt; - u64 stream_source_mask; - - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && - priv->enabled_source_streams) - return -EBUSY; - - /* No transcoding, source and sink formats must match. */ - if (format->pad == MAX96717_PAD_SOURCE) - return v4l2_subdev_get_fmt(sd, state, format); - - /* Set sink format */ - fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream); - if (!fmt) - return -EINVAL; - - *fmt = format->format; - - /* Propagate to source format */ - fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, - format->stream); - if (!fmt) - return -EINVAL; - *fmt = format->format; - - stream_source_mask = BIT(format->stream); - - return v4l2_subdev_state_xlate_streams(state, MAX96717_PAD_SOURCE, - MAX96717_PAD_SINK, - &stream_source_mask); -} - -static int max96717_init_state(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state) -{ - struct v4l2_subdev_route routes[] = { - { - .sink_pad = MAX96717_PAD_SINK, - .sink_stream = 0, - .source_pad = MAX96717_PAD_SOURCE, - .source_stream = 0, - .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, - }, - }; - struct v4l2_subdev_krouting routing = { - .num_routes = ARRAY_SIZE(routes), - .routes = routes, - }; - - return _max96717_set_routing(sd, state, &routing); -} - -static bool max96717_pipe_pclkdet(struct max96717_priv *priv) -{ - u64 val = 0; - - cci_read(priv->regmap, MAX96717_VIDEO_TX2, &val, NULL); - - return val & MAX96717_VIDEO_PCLKDET; -} - -static int max96717_log_status(struct v4l2_subdev *sd) -{ - struct max96717_priv *priv = sd_to_max96717(sd); - struct device *dev = &priv->client->dev; - - dev_info(dev, "Serializer: max96717\n"); - dev_info(dev, "Pipe: pclkdet:%d\n", max96717_pipe_pclkdet(priv)); - - return 0; -} - -static int max96717_enable_streams(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, u32 pad, - u64 streams_mask) -{ - struct max96717_priv *priv = sd_to_max96717(sd); - u64 sink_streams; - int ret; - - if (!priv->enabled_source_streams) - max96717_start_csi(priv, true); - - ret = max96717_apply_patgen(priv, state); - if (ret) - goto stop_csi; - - if (!priv->pattern) { - sink_streams = - v4l2_subdev_state_xlate_streams(state, - MAX96717_PAD_SOURCE, - MAX96717_PAD_SINK, - &streams_mask); - - ret = v4l2_subdev_enable_streams(priv->source_sd, - priv->source_sd_pad, - sink_streams); - if (ret) - goto stop_csi; - } - - priv->enabled_source_streams |= streams_mask; - - return 0; - -stop_csi: - if (!priv->enabled_source_streams) - max96717_start_csi(priv, false); - - return ret; -} - -static int max96717_disable_streams(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, u32 pad, - u64 streams_mask) -{ - struct max96717_priv *priv = sd_to_max96717(sd); - u64 sink_streams; - - /* - * Stop the CSI receiver first then the source, - * otherwise the device may become unresponsive - * while holding the I2C bus low. - */ - priv->enabled_source_streams &= ~streams_mask; - if (!priv->enabled_source_streams) - max96717_start_csi(priv, false); - - if (!priv->pattern) { - int ret; - - sink_streams = - v4l2_subdev_state_xlate_streams(state, - MAX96717_PAD_SOURCE, - MAX96717_PAD_SINK, - &streams_mask); - - ret = v4l2_subdev_disable_streams(priv->source_sd, - priv->source_sd_pad, - sink_streams); - if (ret) - return ret; - } - - return 0; -} - -static const struct v4l2_subdev_pad_ops max96717_pad_ops = { - .enable_streams = max96717_enable_streams, - .disable_streams = max96717_disable_streams, - .set_routing = max96717_set_routing, - .get_fmt = v4l2_subdev_get_fmt, - .set_fmt = max96717_set_fmt, -}; - -static const struct v4l2_subdev_core_ops max96717_subdev_core_ops = { - .log_status = max96717_log_status, -}; - -static const struct v4l2_subdev_internal_ops max96717_internal_ops = { - .init_state = max96717_init_state, -}; - -static const struct v4l2_subdev_ops max96717_subdev_ops = { - .core = &max96717_subdev_core_ops, - .pad = &max96717_pad_ops, -}; - -static const struct media_entity_operations max96717_entity_ops = { - .link_validate = v4l2_subdev_link_validate, -}; - -static int max96717_notify_bound(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *source_subdev, - struct v4l2_async_connection *asd) -{ - struct max96717_priv *priv = sd_to_max96717(notifier->sd); - struct device *dev = &priv->client->dev; - int ret; - - ret = media_entity_get_fwnode_pad(&source_subdev->entity, - source_subdev->fwnode, - MEDIA_PAD_FL_SOURCE); - if (ret < 0) { - dev_err(dev, "Failed to find pad for %s\n", - source_subdev->name); - return ret; - } - - priv->source_sd = source_subdev; - priv->source_sd_pad = ret; - - ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad, - &priv->sd.entity, 0, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - if (ret) { - dev_err(dev, "Unable to link %s:%u -> %s:0\n", - source_subdev->name, priv->source_sd_pad, - priv->sd.name); - return ret; - } - - return 0; -} - -static const struct v4l2_async_notifier_operations max96717_notify_ops = { - .bound = max96717_notify_bound, -}; - -static int max96717_v4l2_notifier_register(struct max96717_priv *priv) -{ - struct device *dev = &priv->client->dev; - struct v4l2_async_connection *asd; - struct fwnode_handle *ep_fwnode; - int ret; - - ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), - MAX96717_PAD_SINK, 0, 0); - if (!ep_fwnode) { - dev_err(dev, "No graph endpoint\n"); - return -ENODEV; - } - - v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd); - - asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode, - struct v4l2_async_connection); - - fwnode_handle_put(ep_fwnode); - - if (IS_ERR(asd)) { - dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd)); - v4l2_async_nf_cleanup(&priv->notifier); - return PTR_ERR(asd); - } - - priv->notifier.ops = &max96717_notify_ops; - - ret = v4l2_async_nf_register(&priv->notifier); - if (ret) { - dev_err(dev, "Failed to register subdev_notifier"); - v4l2_async_nf_cleanup(&priv->notifier); - return ret; - } - - return 0; -} - -static int max96717_subdev_init(struct max96717_priv *priv) -{ - struct device *dev = &priv->client->dev; - int ret; - - v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96717_subdev_ops); - priv->sd.internal_ops = &max96717_internal_ops; - - v4l2_ctrl_handler_init(&priv->ctrl_handler, 1); - priv->sd.ctrl_handler = &priv->ctrl_handler; - - v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, - &max96717_ctrl_ops, - V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(max96717_test_pattern) - 1, - 0, 0, max96717_test_pattern); - if (priv->ctrl_handler.error) { - ret = priv->ctrl_handler.error; - goto err_free_ctrl; - } - - priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS; - priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; - priv->sd.entity.ops = &max96717_entity_ops; - - priv->pads[MAX96717_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - priv->pads[MAX96717_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads); - if (ret) { - dev_err_probe(dev, ret, "Failed to init pads\n"); - goto err_free_ctrl; - } - - ret = v4l2_subdev_init_finalize(&priv->sd); - if (ret) { - dev_err_probe(dev, ret, - "v4l2 subdev init finalized failed\n"); - goto err_entity_cleanup; - } - ret = max96717_v4l2_notifier_register(priv); - if (ret) { - dev_err_probe(dev, ret, - "v4l2 subdev notifier register failed\n"); - goto err_free_state; - } - - ret = v4l2_async_register_subdev(&priv->sd); - if (ret) { - dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n"); - goto err_unreg_notif; - } - - return 0; - -err_unreg_notif: - v4l2_async_nf_unregister(&priv->notifier); - v4l2_async_nf_cleanup(&priv->notifier); -err_free_state: - v4l2_subdev_cleanup(&priv->sd); -err_entity_cleanup: - media_entity_cleanup(&priv->sd.entity); -err_free_ctrl: - v4l2_ctrl_handler_free(&priv->ctrl_handler); - - return ret; -} - -static void max96717_subdev_uninit(struct max96717_priv *priv) -{ - v4l2_async_unregister_subdev(&priv->sd); - v4l2_async_nf_unregister(&priv->notifier); - v4l2_async_nf_cleanup(&priv->notifier); - v4l2_subdev_cleanup(&priv->sd); - media_entity_cleanup(&priv->sd.entity); - v4l2_ctrl_handler_free(&priv->ctrl_handler); -} - -struct max96717_pll_predef_freq { - unsigned long freq; - bool is_alt; - u8 val; -}; - -static const struct max96717_pll_predef_freq max96717_predef_freqs[] = { - { 13500000, true, 0 }, { 19200000, false, 0 }, - { 24000000, true, 1 }, { 27000000, false, 1 }, - { 37125000, false, 2 }, { 74250000, false, 3 }, -}; - -static unsigned long -max96717_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -{ - struct max96717_priv *priv = clk_hw_to_max96717(hw); - - return max96717_predef_freqs[priv->pll_predef_index].freq; -} - -static unsigned int max96717_clk_find_best_index(struct max96717_priv *priv, - unsigned long rate) -{ - unsigned int i, idx = 0; - unsigned long diff_new, diff_old = U32_MAX; - - for (i = 0; i < ARRAY_SIZE(max96717_predef_freqs); i++) { - diff_new = abs(rate - max96717_predef_freqs[i].freq); - if (diff_new < diff_old) { - diff_old = diff_new; - idx = i; - } - } - - return idx; -} - -static long max96717_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct max96717_priv *priv = clk_hw_to_max96717(hw); - struct device *dev = &priv->client->dev; - unsigned int idx; - - idx = max96717_clk_find_best_index(priv, rate); - - if (rate != max96717_predef_freqs[idx].freq) { - dev_warn(dev, "Request CLK freq:%lu, found CLK freq:%lu\n", - rate, max96717_predef_freqs[idx].freq); - } - - return max96717_predef_freqs[idx].freq; -} - -static int max96717_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct max96717_priv *priv = clk_hw_to_max96717(hw); - unsigned int val, idx; - int ret = 0; - - idx = max96717_clk_find_best_index(priv, rate); - - val = FIELD_PREP(REFGEN_PREDEF_FREQ_MASK, - max96717_predef_freqs[idx].val); - - if (max96717_predef_freqs[idx].is_alt) - val |= REFGEN_PREDEF_FREQ_ALT; - - val |= REFGEN_RST | REFGEN_PREDEF_EN; - - cci_write(priv->regmap, REF_VTG0, val, &ret); - cci_update_bits(priv->regmap, REF_VTG0, REFGEN_RST | REFGEN_EN, - REFGEN_EN, &ret); - if (ret) - return ret; - - priv->pll_predef_index = idx; - - return 0; -} - -static int max96717_clk_prepare(struct clk_hw *hw) -{ - struct max96717_priv *priv = clk_hw_to_max96717(hw); - - return cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN, - RCLKEN, NULL); -} - -static void max96717_clk_unprepare(struct clk_hw *hw) -{ - struct max96717_priv *priv = clk_hw_to_max96717(hw); - - cci_update_bits(priv->regmap, MAX96717_REG6, RCLKEN, 0, NULL); -} - -static const struct clk_ops max96717_clk_ops = { - .prepare = max96717_clk_prepare, - .unprepare = max96717_clk_unprepare, - .set_rate = max96717_clk_set_rate, - .recalc_rate = max96717_clk_recalc_rate, - .round_rate = max96717_clk_round_rate, -}; - -static int max96717_register_clkout(struct max96717_priv *priv) -{ - struct device *dev = &priv->client->dev; - struct clk_init_data init = { .ops = &max96717_clk_ops }; - int ret; - - init.name = kasprintf(GFP_KERNEL, "max96717.%s.clk_out", dev_name(dev)); - if (!init.name) - return -ENOMEM; - - /* RCLKSEL Reference PLL output */ - ret = cci_update_bits(priv->regmap, MAX96717_REG3, MAX96717_RCLKSEL, - MAX96717_RCLKSEL, NULL); - /* MFP4 fastest slew rate */ - cci_update_bits(priv->regmap, PIO_SLEW_1, BIT(5) | BIT(4), 0, &ret); - if (ret) - goto free_init_name; - - priv->clk_hw.init = &init; - - /* Initialize to 24 MHz */ - ret = max96717_clk_set_rate(&priv->clk_hw, - MAX96717_DEFAULT_CLKOUT_RATE, 0); - if (ret < 0) - goto free_init_name; - - ret = devm_clk_hw_register(dev, &priv->clk_hw); - kfree(init.name); - if (ret) - return dev_err_probe(dev, ret, "Cannot register clock HW\n"); - - ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, - &priv->clk_hw); - if (ret) - return dev_err_probe(dev, ret, - "Cannot add OF clock provider\n"); - - return 0; - -free_init_name: - kfree(init.name); - return ret; -} - -static int max96717_init_csi_lanes(struct max96717_priv *priv) -{ - struct v4l2_mbus_config_mipi_csi2 *mipi = &priv->mipi_csi2; - unsigned long lanes_used = 0; - unsigned int nlanes, lane, val = 0; - int ret; - - nlanes = mipi->num_data_lanes; - - ret = cci_update_bits(priv->regmap, MAX96717_MIPI_RX1, - MAX96717_MIPI_LANES_CNT, - FIELD_PREP(MAX96717_MIPI_LANES_CNT, - nlanes - 1), NULL); - - /* lanes polarity */ - for (lane = 0; lane < nlanes + 1; lane++) { - if (!mipi->lane_polarities[lane]) - continue; - /* Clock lane */ - if (lane == 0) - val |= BIT(2); - else if (lane < 3) - val |= BIT(lane - 1); - else - val |= BIT(lane); - } - - cci_update_bits(priv->regmap, MAX96717_MIPI_RX5, - MAX96717_PHY2_LANES_POL, - FIELD_PREP(MAX96717_PHY2_LANES_POL, val), &ret); - - cci_update_bits(priv->regmap, MAX96717_MIPI_RX4, - MAX96717_PHY1_LANES_POL, - FIELD_PREP(MAX96717_PHY1_LANES_POL, - val >> 3), &ret); - /* lanes mapping */ - for (lane = 0, val = 0; lane < nlanes; lane++) { - val |= (mipi->data_lanes[lane] - 1) << (lane * 2); - lanes_used |= BIT(mipi->data_lanes[lane] - 1); - } - - /* - * Unused lanes need to be mapped as well to not have - * the same lanes mapped twice. - */ - for (; lane < MAX96717_CSI_NLANES; lane++) { - unsigned int idx = find_first_zero_bit(&lanes_used, - MAX96717_CSI_NLANES); - - val |= idx << (lane * 2); - lanes_used |= BIT(idx); - } - - cci_update_bits(priv->regmap, MAX96717_MIPI_RX3, - MAX96717_PHY1_LANES_MAP, - FIELD_PREP(MAX96717_PHY1_LANES_MAP, val), &ret); - - return cci_update_bits(priv->regmap, MAX96717_MIPI_RX2, - MAX96717_PHY2_LANES_MAP, - FIELD_PREP(MAX96717_PHY2_LANES_MAP, val >> 4), - &ret); -} - -static int max96717_hw_init(struct max96717_priv *priv) -{ - struct device *dev = &priv->client->dev; - u64 dev_id, val; - int ret; - - ret = cci_read(priv->regmap, MAX96717_DEV_ID, &dev_id, NULL); - if (ret) - return dev_err_probe(dev, ret, - "Fail to read the device id\n"); - - if (dev_id != MAX96717_DEVICE_ID && dev_id != MAX96717F_DEVICE_ID) - return dev_err_probe(dev, -EOPNOTSUPP, - "Unsupported device id got %x\n", (u8)dev_id); - - ret = cci_read(priv->regmap, MAX96717_DEV_REV, &val, NULL); - if (ret) - return dev_err_probe(dev, ret, - "Fail to read device revision"); - - dev_dbg(dev, "Found %x (rev %lx)\n", (u8)dev_id, - (u8)val & MAX96717_DEV_REV_MASK); - - ret = cci_read(priv->regmap, MAX96717_MIPI_RX_EXT11, &val, NULL); - if (ret) - return dev_err_probe(dev, ret, - "Fail to read mipi rx extension"); - - if (!(val & MAX96717_TUN_MODE)) - return dev_err_probe(dev, -EOPNOTSUPP, - "Only supporting tunnel mode"); - - return max96717_init_csi_lanes(priv); -} - -static int max96717_parse_dt(struct max96717_priv *priv) -{ - struct device *dev = &priv->client->dev; - struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - struct fwnode_handle *ep_fwnode; - unsigned char num_data_lanes; - int ret; - - ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), - MAX96717_PAD_SINK, 0, 0); - if (!ep_fwnode) - return dev_err_probe(dev, -ENOENT, "no endpoint found\n"); - - ret = v4l2_fwnode_endpoint_parse(ep_fwnode, &vep); - - fwnode_handle_put(ep_fwnode); - - if (ret < 0) - return dev_err_probe(dev, ret, "Failed to parse sink endpoint"); - - num_data_lanes = vep.bus.mipi_csi2.num_data_lanes; - if (num_data_lanes < 1 || num_data_lanes > MAX96717_CSI_NLANES) - return dev_err_probe(dev, -EINVAL, - "Invalid data lanes must be 1 to 4\n"); - - priv->mipi_csi2 = vep.bus.mipi_csi2; - - return 0; -} - -static int max96717_probe(struct i2c_client *client) -{ - struct device *dev = &client->dev; - struct max96717_priv *priv; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->client = client; - priv->regmap = devm_cci_regmap_init_i2c(client, 16); - if (IS_ERR(priv->regmap)) { - ret = PTR_ERR(priv->regmap); - return dev_err_probe(dev, ret, "Failed to init regmap\n"); - } - - ret = max96717_parse_dt(priv); - if (ret) - return dev_err_probe(dev, ret, "Failed to parse the dt\n"); - - ret = max96717_hw_init(priv); - if (ret) - return dev_err_probe(dev, ret, - "Failed to initialize the hardware\n"); - - ret = max96717_gpiochip_probe(priv); - if (ret) - return dev_err_probe(&client->dev, ret, - "Failed to init gpiochip\n"); - - ret = max96717_register_clkout(priv); - if (ret) - return dev_err_probe(dev, ret, "Failed to register clkout\n"); - - ret = max96717_subdev_init(priv); - if (ret) - return dev_err_probe(dev, ret, - "Failed to initialize v4l2 subdev\n"); - - ret = max96717_i2c_mux_init(priv); - if (ret) { - dev_err_probe(dev, ret, "failed to add remote i2c adapter\n"); - max96717_subdev_uninit(priv); - } - - return ret; -} - -static void max96717_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct max96717_priv *priv = sd_to_max96717(sd); - - max96717_subdev_uninit(priv); - i2c_mux_del_adapters(priv->mux); -} - -static const struct of_device_id max96717_of_ids[] = { - { .compatible = "maxim,max96717f" }, - { } -}; -MODULE_DEVICE_TABLE(of, max96717_of_ids); - -static struct i2c_driver max96717_i2c_driver = { - .driver = { - .name = "max96717", - .of_match_table = max96717_of_ids, - }, - .probe = max96717_probe, - .remove = max96717_remove, -}; - -module_i2c_driver(max96717_i2c_driver); - -MODULE_DESCRIPTION("Maxim GMSL2 MAX96717 Serializer Driver"); -MODULE_AUTHOR("Julien Massot "); -MODULE_LICENSE("GPL"); From patchwork Sat Mar 8 18:33:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cosmin Tanislav X-Patchwork-Id: 872049 Received: from mail-ed1-f43.google.com (mail-ed1-f43.google.com [209.85.208.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5763521C182; Sat, 8 Mar 2025 18:36:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458974; cv=none; b=idgAl5ABMHm4tME+MuIAPw7GIVEu0ncjCHT2aX9UfKUudVRqgN+NEJFWR6sASi5udDfyTmZ4R5Mi4r30wxG4PnbSK4Oh47ZU823qwWITAq6yyjjmagA3Xth6cCkgVxlFBJRluGbJvJ3TMs1Gfxs8WNgQ13GinPpxn3NKPNQJRGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741458974; c=relaxed/simple; bh=4/c4DEm7ejv6e7ePcNgYHWzZDLr0Qhklxu8nuooRNho=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MiWeYDVZWsHkDn6nIHR9hmbBCXGVMJqC58+ZCmd6RFimJY+17JmHFB08rQGMzsWEkKW6JgCjpofrGnVete4OWincy+aByhulgFNraZ9Oic/BuB/2/GhFcJfgRht3ftocSm7aEfEdhkdlOxNZmlTLIgyUcBxSJLwdKZ5HzO8TFVg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ZrdjRXAV; arc=none smtp.client-ip=209.85.208.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ZrdjRXAV" Received: by mail-ed1-f43.google.com with SMTP id 4fb4d7f45d1cf-5e56b229d60so7333567a12.0; Sat, 08 Mar 2025 10:36:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1741458970; x=1742063770; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0R6RfOcy7InAyYYn86bZjnTo14H/unc5oSoTfVShhcU=; b=ZrdjRXAVCz5SWzcnJsnb/jrYcUBUhtZRcF23zWgOpdBHBPPfGooX91edmBIELqp0K2 7rbuJ3jBhM6FnPIY8RMdREdfuCV3f81cAiizc3cwpvubhOpkuiW1GuG2r5Azr5TjYTAK xalpVBPzDFjoIPb8fZOZ2R0KYoeb8s3LzrXyow4eOQutJ4EyrCs7tg/l4nBhVnilLDf/ 8UmpuRbcJV0ohPWtR3NA/1w+2eYGQNzhE6TM5Tgz6XU9ytWETT6aB6Sj7Y3XS9/lLHOP 5IeM1sl1CJ7RliNgxAjVf4hQMXO0l2K+liwdTfTbhxO0XaVlTd7tDCFBr4wblJH1eueD FjHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741458970; x=1742063770; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0R6RfOcy7InAyYYn86bZjnTo14H/unc5oSoTfVShhcU=; b=rdzxmtkNczsRWUPKLrtWZIwc8b4ghaNlJjeSzsQZtXaJHxnmrafzxk3EGr7HmwCTBJ s+HmweSE7oNhPYSZGHiaPJugMzs6H4Z/220w79FCOtNEGFh7m1hNKNEsYJzEA/PHY0ak l1zrP3Lll8lQQ7NbR6k9hiATd/M2lXIVmPZInVwO9wZf9/vE+MxTVIimGxT2wyzstL+Q OvypG1I5P01svEgUcUjkDxXWcwFh02EkSvvmsYMfqtTgkH0/q1a6naQgydbkVChxzW6J +Uwby6b2ewbQx+edFolhwUc3dNAeE1I+KYDCMkR5RDjqwDImcqy9/l9+hM+gxlsBH7Jw BNkA== X-Forwarded-Encrypted: i=1; AJvYcCU0hWOm0MM13jhSK3Wa8cc/1W+lL7QKTMRg1m+vui4CqOU2TArZoBhhBraV+3JGTFGGvvAJTLl4UIx4W6kC@vger.kernel.org, AJvYcCUDgn9+ngeUJlWoeyjeYUTyaF9sl6ayBhD/yaPYVBgLA4Eny2LBxVsCWOdBIP80iY+DbQ+kccHzgScSIQ==@vger.kernel.org, AJvYcCW/K4M2y55dpC8lSzjsl23imamAd9G3S1vSiLopotjyMduRq9b1xs2S+Codxc+Kh/fZ/2xfosTEV0hO9jA=@vger.kernel.org, AJvYcCW2K33zgMbIKgZCva6FnkiStoMQUzhTbmcYQBh26kOZ9gmY7QtyEs1GqjOfxY7GACaudItve6RBTRtA@vger.kernel.org X-Gm-Message-State: AOJu0Yx+IB/GRJdaXJrXcDq0fAO8Mf4GpL/SWhFCsl6lNadpxfORBToW /I/AhWgZVtljVAEU6bIW2wRIyXi21FGueEWXTdtOggVZ1fmKNvHB X-Gm-Gg: ASbGnctE+pys4fuBZaqHnrlEw40ympf7stxRhYuZVHfhX0rBqZw392UXXYdDY6DiBPg mFGeeOdq1uKOYhROMpPEJn+VStRdTBPZmFGPs1nYzLKpgmqaMeXO/J1BDar2A1gaCZTBsqibFe0 tTntjp4MkKVMwKMNlae04P2Q2KcqOE7x/VO9RJuMyQvXYYNT60IoLkaey1JYMxdtaOrJt99JAp5 RqF8UeLiobbJLhgfAZYG8ke3Q/TjyY2XYOrfitrWNRStTbK2TnE8RW3AmhEg2mU25hqrRgcpYYO aIhNcF+GL5eDSc5o0WAUyLmrqLqQajau8bZ/Gy4gmADB/tZEyJAK3Eg8Bw== X-Google-Smtp-Source: AGHT+IEqYjN3KMPKIuLTjfA3GhIJEiIRGxQus5/t8hOwTWG4IAhMpLUMmCrUbS1punuvdLq2KC4iNg== X-Received: by 2002:a17:907:2d9f:b0:ac1:f247:69f5 with SMTP id a640c23a62f3a-ac26cc60472mr465173266b.28.1741458969493; Sat, 08 Mar 2025 10:36:09 -0800 (PST) Received: from demon-pc.localdomain ([188.27.130.21]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ac24a84397fsm379693666b.96.2025.03.08.10.36.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Mar 2025 10:36:09 -0800 (PST) From: Cosmin Tanislav To: Cc: Tomi Valkeinen , =?utf-8?q?Niklas_S?= =?utf-8?q?=C3=B6derlund?= , Cosmin Tanislav , Mauro Carvalho Chehab , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Julien Massot , Catalin Marinas , Will Deacon , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Linus Walleij , Bartosz Golaszewski , Bjorn Andersson , Geert Uytterhoeven , Dmitry Baryshkov , Heiko Stuebner , Biju Das , Taniya Das , =?utf-8?q?N=C3=ADcolas_F_=2E_R_=2E_A_?= =?utf-8?q?=2E_Prado?= , Eric Biggers , Javier Carrasco , Ross Burton , Sakari Ailus , Hans Verkuil , Laurent Pinchart , Umang Jain , Zhi Mao , Kieran Bingham , Dongcheng Yan , AngeloGioacchino Del Regno , Benjamin Mugnier , Tommaso Merciai , Dan Carpenter , Ricardo Ribalda , Ihor Matushchak , Laurentiu Palcu , linux-media@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-staging@lists.linux.dev, linux-gpio@vger.kernel.org, Cosmin Tanislav Subject: [RFC PATCH 24/24] media: i2c: remove MAX96714 driver Date: Sat, 8 Mar 2025 20:33:53 +0200 Message-ID: <20250308183410.3013996-25-demonsingur@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20250308183410.3013996-1-demonsingur@gmail.com> References: <20250308183410.3013996-1-demonsingur@gmail.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The previous MAX96714 driver has been removed and its functionality has been moved to the MAX9296A driver which makes use of the Maxim GMSL2/3 serializer framework. Signed-off-by: Cosmin Tanislav --- MAINTAINERS | 1 - drivers/media/i2c/Kconfig | 17 - drivers/media/i2c/Makefile | 1 - drivers/media/i2c/max96714.c | 1024 ---------------------------------- 4 files changed, 1043 deletions(-) delete mode 100644 drivers/media/i2c/max96714.c diff --git a/MAINTAINERS b/MAINTAINERS index 12078126f478..eae3a888e3fa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14195,7 +14195,6 @@ M: Cosmin Tanislav L: linux-media@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/media/i2c/maxim,max96714.yaml -F: drivers/media/i2c/max96714.c MAX96717 GMSL2 SERIALIZER DRIVER M: Julien Massot diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 6c595dffb280..aa0a67b7da47 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -1619,23 +1619,6 @@ config VIDEO_DS90UB960 Device driver for the Texas Instruments DS90UB960 FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer. -config VIDEO_MAX96714 - tristate "Maxim MAX96714 GMSL2 deserializer" - depends on OF && I2C && VIDEO_DEV - select I2C_MUX - select MEDIA_CONTROLLER - select GPIOLIB - select V4L2_CCI_I2C - select V4L2_FWNODE - select VIDEO_V4L2_SUBDEV_API - help - Device driver for the Maxim MAX96714 GMSL2 Deserializer. - MAX96714 deserializers convert a GMSL2 input to MIPI CSI-2 - output. - - To compile this driver as a module, choose M here: the - module will be called max96714. - source "drivers/media/i2c/maxim-serdes/Kconfig" endmenu diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index de0680ebf190..065e728f54ce 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -68,7 +68,6 @@ obj-$(CONFIG_VIDEO_LT6911UXE) += lt6911uxe.o obj-$(CONFIG_VIDEO_M52790) += m52790.o obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o obj-$(CONFIG_VIDEO_MAX9286) += max9286.o -obj-$(CONFIG_VIDEO_MAX96714) += max96714.o obj-$(CONFIG_VIDEO_MAXIM_SERDES) += maxim-serdes/ obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o diff --git a/drivers/media/i2c/max96714.c b/drivers/media/i2c/max96714.c deleted file mode 100644 index 159753b13777..000000000000 --- a/drivers/media/i2c/max96714.c +++ /dev/null @@ -1,1024 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Maxim GMSL2 Deserializer Driver - * - * Copyright (C) 2024 Collabora Ltd. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define MAX96714_DEVICE_ID 0xc9 -#define MAX96714F_DEVICE_ID 0xca -#define MAX96714_NPORTS 2 -#define MAX96714_PAD_SINK 0 -#define MAX96714_PAD_SOURCE 1 -#define MAX96714_CSI_NLANES 4 - -/* DEV */ -#define MAX96714_REG13 CCI_REG8(0x0d) -#define MAX96714_DEV_REV CCI_REG8(0x0e) -#define MAX96714_DEV_REV_MASK GENMASK(3, 0) -#define MAX96714_LINK_LOCK CCI_REG8(0x13) -#define MAX96714_LINK_LOCK_BIT BIT(3) -#define MAX96714_IO_CHK0 CCI_REG8(0x38) -#define MAX96714_PATTERN_CLK_FREQ GENMASK(1, 0) -/* VID_RX */ -#define MAX96714_VIDEO_RX8 CCI_REG8(0x11a) -#define MAX96714_VID_LOCK BIT(6) - -/* VRX_PATGEN_0 */ -#define MAX96714_PATGEN_0 CCI_REG8(0x240) -#define MAX96714_PATGEN_1 CCI_REG8(0x241) -#define MAX96714_PATGEN_MODE GENMASK(5, 4) -#define MAX96714_PATGEN_VS_DLY CCI_REG24(0x242) -#define MAX96714_PATGEN_VS_HIGH CCI_REG24(0x245) -#define MAX96714_PATGEN_VS_LOW CCI_REG24(0x248) -#define MAX96714_PATGEN_V2H CCI_REG24(0x24b) -#define MAX96714_PATGEN_HS_HIGH CCI_REG16(0x24e) -#define MAX96714_PATGEN_HS_LOW CCI_REG16(0x250) -#define MAX96714_PATGEN_HS_CNT CCI_REG16(0x252) -#define MAX96714_PATGEN_V2D CCI_REG24(0x254) -#define MAX96714_PATGEN_DE_HIGH CCI_REG16(0x257) -#define MAX96714_PATGEN_DE_LOW CCI_REG16(0x259) -#define MAX96714_PATGEN_DE_CNT CCI_REG16(0x25b) -#define MAX96714_PATGEN_GRAD_INC CCI_REG8(0x25d) -#define MAX96714_PATGEN_CHKB_COLOR_A CCI_REG24(0x25e) -#define MAX96714_PATGEN_CHKB_COLOR_B CCI_REG24(0x261) -#define MAX96714_PATGEN_CHKB_RPT_CNT_A CCI_REG8(0x264) -#define MAX96714_PATGEN_CHKB_RPT_CNT_B CCI_REG8(0x265) -#define MAX96714_PATGEN_CHKB_ALT CCI_REG8(0x266) -/* BACKTOP */ -#define MAX96714_BACKTOP25 CCI_REG8(0x320) -#define CSI_DPLL_FREQ_MASK GENMASK(4, 0) - -/* MIPI_PHY */ -#define MAX96714_MIPI_PHY0 CCI_REG8(0x330) -#define MAX96714_FORCE_CSI_OUT BIT(7) -#define MAX96714_MIPI_STDBY_N CCI_REG8(0x332) -#define MAX96714_MIPI_STDBY_MASK GENMASK(5, 4) -#define MAX96714_MIPI_LANE_MAP CCI_REG8(0x333) -#define MAX96714_MIPI_POLARITY CCI_REG8(0x335) -#define MAX96714_MIPI_POLARITY_MASK GENMASK(5, 0) - -/* MIPI_TX */ -#define MAX96714_MIPI_LANE_CNT CCI_REG8(0x44a) -#define MAX96714_CSI2_LANE_CNT_MASK GENMASK(7, 6) -#define MAX96714_MIPI_TX52 CCI_REG8(0x474) -#define MAX96714_TUN_EN BIT(0) - -#define MHZ(v) ((u32)((v) * 1000000U)) - -enum max96714_vpg_mode { - MAX96714_VPG_DISABLED = 0, - MAX96714_VPG_CHECKERBOARD = 1, - MAX96714_VPG_GRADIENT = 2, -}; - -struct max96714_rxport { - struct { - struct v4l2_subdev *sd; - u16 pad; - struct fwnode_handle *ep_fwnode; - } source; - struct regulator *poc; -}; - -struct max96714_txport { - struct v4l2_fwnode_endpoint vep; -}; - -struct max96714_priv { - struct i2c_client *client; - struct regmap *regmap; - struct gpio_desc *pd_gpio; - struct max96714_rxport rxport; - struct i2c_mux_core *mux; - u64 enabled_source_streams; - struct v4l2_subdev sd; - struct media_pad pads[MAX96714_NPORTS]; - struct v4l2_mbus_config_mipi_csi2 mipi_csi2; - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_async_notifier notifier; - s64 tx_link_freq; - enum max96714_vpg_mode pattern; -}; - -static inline struct max96714_priv *sd_to_max96714(struct v4l2_subdev *sd) -{ - return container_of(sd, struct max96714_priv, sd); -} - -static int max96714_enable_tx_port(struct max96714_priv *priv) -{ - return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N, - MAX96714_MIPI_STDBY_MASK, - MAX96714_MIPI_STDBY_MASK, NULL); -} - -static int max96714_disable_tx_port(struct max96714_priv *priv) -{ - return cci_update_bits(priv->regmap, MAX96714_MIPI_STDBY_N, - MAX96714_MIPI_STDBY_MASK, 0, NULL); -} - -static bool max96714_tx_port_enabled(struct max96714_priv *priv) -{ - u64 val; - - cci_read(priv->regmap, MAX96714_MIPI_STDBY_N, &val, NULL); - - return val & MAX96714_MIPI_STDBY_MASK; -} - -static int max96714_apply_patgen_timing(struct max96714_priv *priv, - struct v4l2_subdev_state *state) -{ - struct v4l2_mbus_framefmt *fmt = - v4l2_subdev_state_get_format(state, MAX96714_PAD_SOURCE); - const u32 h_active = fmt->width; - const u32 h_fp = 88; - const u32 h_sw = 44; - const u32 h_bp = 148; - u32 h_tot; - const u32 v_active = fmt->height; - const u32 v_fp = 4; - const u32 v_sw = 5; - const u32 v_bp = 36; - u32 v_tot; - int ret = 0; - - h_tot = h_active + h_fp + h_sw + h_bp; - v_tot = v_active + v_fp + v_sw + v_bp; - - /* 75 Mhz pixel clock */ - cci_update_bits(priv->regmap, MAX96714_IO_CHK0, - MAX96714_PATTERN_CLK_FREQ, 1, &ret); - - dev_info(&priv->client->dev, "height: %d width: %d\n", fmt->height, - fmt->width); - - cci_write(priv->regmap, MAX96714_PATGEN_VS_DLY, 0, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_VS_HIGH, v_sw * h_tot, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_VS_LOW, - (v_active + v_fp + v_bp) * h_tot, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_HS_HIGH, h_sw, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_HS_LOW, h_active + h_fp + h_bp, - &ret); - cci_write(priv->regmap, MAX96714_PATGEN_V2D, - h_tot * (v_sw + v_bp) + (h_sw + h_bp), &ret); - cci_write(priv->regmap, MAX96714_PATGEN_HS_CNT, v_tot, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_DE_HIGH, h_active, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_DE_LOW, h_fp + h_sw + h_bp, - &ret); - cci_write(priv->regmap, MAX96714_PATGEN_DE_CNT, v_active, &ret); - /* B G R */ - cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_A, 0xfecc00, &ret); - /* B G R */ - cci_write(priv->regmap, MAX96714_PATGEN_CHKB_COLOR_B, 0x006aa7, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_A, 0x3c, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_CHKB_RPT_CNT_B, 0x3c, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_CHKB_ALT, 0x3c, &ret); - cci_write(priv->regmap, MAX96714_PATGEN_GRAD_INC, 0x10, &ret); - - return ret; -} - -static int max96714_apply_patgen(struct max96714_priv *priv, - struct v4l2_subdev_state *state) -{ - unsigned int val; - int ret = 0; - - if (priv->pattern) - ret = max96714_apply_patgen_timing(priv, state); - - cci_write(priv->regmap, MAX96714_PATGEN_0, priv->pattern ? 0xfb : 0, - &ret); - - val = FIELD_PREP(MAX96714_PATGEN_MODE, priv->pattern); - cci_update_bits(priv->regmap, MAX96714_PATGEN_1, MAX96714_PATGEN_MODE, - val, &ret); - return ret; -} - -static int max96714_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct max96714_priv *priv = - container_of(ctrl->handler, struct max96714_priv, ctrl_handler); - int ret; - - switch (ctrl->id) { - case V4L2_CID_TEST_PATTERN: - if (priv->enabled_source_streams) - return -EBUSY; - priv->pattern = ctrl->val; - break; - default: - return -EINVAL; - } - - ret = cci_update_bits(priv->regmap, MAX96714_MIPI_PHY0, - MAX96714_FORCE_CSI_OUT, - priv->pattern ? MAX96714_FORCE_CSI_OUT : 0, NULL); - - /* Pattern generator doesn't work with tunnel mode */ - return cci_update_bits(priv->regmap, MAX96714_MIPI_TX52, - MAX96714_TUN_EN, - priv->pattern ? 0 : MAX96714_TUN_EN, &ret); -} - -static const char * const max96714_test_pattern[] = { - "Disabled", - "Checkerboard", - "Gradient" -}; - -static const struct v4l2_ctrl_ops max96714_ctrl_ops = { - .s_ctrl = max96714_s_ctrl, -}; - -static int max96714_enable_streams(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - u32 source_pad, u64 streams_mask) -{ - struct max96714_priv *priv = sd_to_max96714(sd); - u64 sink_streams; - int ret; - - if (!priv->enabled_source_streams) - max96714_enable_tx_port(priv); - - ret = max96714_apply_patgen(priv, state); - if (ret) - goto err; - - if (!priv->pattern) { - if (!priv->rxport.source.sd) { - ret = -ENODEV; - goto err; - } - - sink_streams = - v4l2_subdev_state_xlate_streams(state, - MAX96714_PAD_SOURCE, - MAX96714_PAD_SINK, - &streams_mask); - - ret = v4l2_subdev_enable_streams(priv->rxport.source.sd, - priv->rxport.source.pad, - sink_streams); - if (ret) - goto err; - } - - priv->enabled_source_streams |= streams_mask; - - return 0; - -err: - if (!priv->enabled_source_streams) - max96714_disable_tx_port(priv); - - return ret; -} - -static int max96714_disable_streams(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - u32 source_pad, u64 streams_mask) -{ - struct max96714_priv *priv = sd_to_max96714(sd); - u64 sink_streams; - - if (!priv->pattern) { - int ret; - - sink_streams = - v4l2_subdev_state_xlate_streams(state, - MAX96714_PAD_SOURCE, - MAX96714_PAD_SINK, - &streams_mask); - - ret = v4l2_subdev_disable_streams(priv->rxport.source.sd, - priv->rxport.source.pad, - sink_streams); - if (ret) - return ret; - } - - priv->enabled_source_streams &= ~streams_mask; - - if (!priv->enabled_source_streams) - max96714_disable_tx_port(priv); - - return 0; -} - -static int max96714_set_fmt(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - struct v4l2_subdev_format *format) -{ - struct max96714_priv *priv = sd_to_max96714(sd); - struct v4l2_mbus_framefmt *fmt; - - if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && - priv->enabled_source_streams) - return -EBUSY; - - /* No transcoding, source and sink formats must match. */ - if (format->pad == MAX96714_PAD_SOURCE) - return v4l2_subdev_get_fmt(sd, state, format); - - fmt = v4l2_subdev_state_get_format(state, format->pad, format->stream); - if (!fmt) - return -EINVAL; - - *fmt = format->format; - - fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad, - format->stream); - if (!fmt) - return -EINVAL; - - *fmt = format->format; - - return 0; -} - -static int _max96714_set_routing(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - enum v4l2_subdev_format_whence which, - struct v4l2_subdev_krouting *routing) -{ - static const struct v4l2_mbus_framefmt format = { - .width = 1280, - .height = 1080, - .code = MEDIA_BUS_FMT_Y8_1X8, - .field = V4L2_FIELD_NONE, - }; - int ret; - - /* - * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until - * frame desc is made dynamically allocated. - */ - if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX) - return -EINVAL; - - ret = v4l2_subdev_routing_validate(sd, routing, - V4L2_SUBDEV_ROUTING_ONLY_1_TO_1); - if (ret) - return ret; - - return v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format); -} - -static int max96714_set_routing(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state, - enum v4l2_subdev_format_whence which, - struct v4l2_subdev_krouting *routing) -{ - struct max96714_priv *priv = sd_to_max96714(sd); - - if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams) - return -EBUSY; - - return _max96714_set_routing(sd, state, which, routing); -} - -static int max96714_init_state(struct v4l2_subdev *sd, - struct v4l2_subdev_state *state) -{ - struct v4l2_subdev_route routes[] = { - { - .sink_pad = MAX96714_PAD_SINK, - .sink_stream = 0, - .source_pad = MAX96714_PAD_SOURCE, - .source_stream = 0, - .flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE, - } - }; - struct v4l2_subdev_krouting routing = { - .num_routes = ARRAY_SIZE(routes), - .routes = routes, - }; - - return _max96714_set_routing(sd, state, V4L2_SUBDEV_FORMAT_ACTIVE, - &routing); -} - -static const struct v4l2_subdev_pad_ops max96714_pad_ops = { - .enable_streams = max96714_enable_streams, - .disable_streams = max96714_disable_streams, - - .set_routing = max96714_set_routing, - .get_fmt = v4l2_subdev_get_fmt, - .set_fmt = max96714_set_fmt, -}; - -static bool max96714_link_locked(struct max96714_priv *priv) -{ - u64 val = 0; - - cci_read(priv->regmap, MAX96714_LINK_LOCK, &val, NULL); - - return val & MAX96714_LINK_LOCK_BIT; -} - -static void max96714_link_status(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - - dev_info(dev, "Link locked:%d\n", max96714_link_locked(priv)); -} - -static bool max96714_pipe_locked(struct max96714_priv *priv) -{ - u64 val; - - cci_read(priv->regmap, MAX96714_VIDEO_RX8, &val, NULL); - - return val & MAX96714_VID_LOCK; -} - -static void max96714_pipe_status(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - - dev_info(dev, "Pipe vidlock:%d\n", max96714_pipe_locked(priv)); -} - -static void max96714_csi_status(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - u64 freq = 0; - - cci_read(priv->regmap, MAX96714_BACKTOP25, &freq, NULL); - freq = FIELD_GET(CSI_DPLL_FREQ_MASK, freq); - - dev_info(dev, "CSI controller DPLL freq:%u00MHz CSIPHY enabled:%d\n", - (u8)freq, max96714_tx_port_enabled(priv)); -} - -static int max96714_log_status(struct v4l2_subdev *sd) -{ - struct max96714_priv *priv = sd_to_max96714(sd); - struct device *dev = &priv->client->dev; - - dev_info(dev, "Deserializer: max96714\n"); - - max96714_link_status(priv); - max96714_pipe_status(priv); - max96714_csi_status(priv); - - return 0; -} - -static const struct v4l2_subdev_core_ops max96714_subdev_core_ops = { - .log_status = max96714_log_status, -}; - -static const struct v4l2_subdev_video_ops max96714_video_ops = { - .s_stream = v4l2_subdev_s_stream_helper, -}; - -static const struct v4l2_subdev_internal_ops max96714_internal_ops = { - .init_state = max96714_init_state, -}; - -static const struct v4l2_subdev_ops max96714_subdev_ops = { - .video = &max96714_video_ops, - .core = &max96714_subdev_core_ops, - .pad = &max96714_pad_ops, -}; - -static const struct media_entity_operations max96714_entity_ops = { - .link_validate = v4l2_subdev_link_validate, -}; - -static int max96714_notify_bound(struct v4l2_async_notifier *notifier, - struct v4l2_subdev *subdev, - struct v4l2_async_connection *asd) -{ - struct max96714_priv *priv = sd_to_max96714(notifier->sd); - struct device *dev = &priv->client->dev; - int ret; - - ret = media_entity_get_fwnode_pad(&subdev->entity, - priv->rxport.source.ep_fwnode, - MEDIA_PAD_FL_SOURCE); - if (ret < 0) { - dev_err(dev, "Failed to find pad for %s\n", subdev->name); - return ret; - } - - priv->rxport.source.sd = subdev; - priv->rxport.source.pad = ret; - - ret = media_create_pad_link(&priv->rxport.source.sd->entity, - priv->rxport.source.pad, &priv->sd.entity, - MAX96714_PAD_SINK, - MEDIA_LNK_FL_ENABLED | - MEDIA_LNK_FL_IMMUTABLE); - if (ret) { - dev_err(dev, "Unable to link %s:%u -> %s:%u\n", - priv->rxport.source.sd->name, priv->rxport.source.pad, - priv->sd.name, MAX96714_PAD_SINK); - return ret; - } - - return 0; -} - -static const struct v4l2_async_notifier_operations max96714_notify_ops = { - .bound = max96714_notify_bound, -}; - -static int max96714_v4l2_notifier_register(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - struct max96714_rxport *rxport = &priv->rxport; - struct v4l2_async_connection *asd; - int ret; - - if (!rxport->source.ep_fwnode) - return 0; - - v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd); - - asd = v4l2_async_nf_add_fwnode(&priv->notifier, - rxport->source.ep_fwnode, - struct v4l2_async_connection); - if (IS_ERR(asd)) { - dev_err(dev, "Failed to add subdev: %pe", asd); - v4l2_async_nf_cleanup(&priv->notifier); - return PTR_ERR(asd); - } - - priv->notifier.ops = &max96714_notify_ops; - - ret = v4l2_async_nf_register(&priv->notifier); - if (ret) { - dev_err(dev, "Failed to register subdev_notifier"); - v4l2_async_nf_cleanup(&priv->notifier); - return ret; - } - - return 0; -} - -static int max96714_create_subdev(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - int ret; - - v4l2_i2c_subdev_init(&priv->sd, priv->client, &max96714_subdev_ops); - priv->sd.internal_ops = &max96714_internal_ops; - - v4l2_ctrl_handler_init(&priv->ctrl_handler, 1); - priv->sd.ctrl_handler = &priv->ctrl_handler; - - v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ, - 0, 0, &priv->tx_link_freq); - v4l2_ctrl_new_std_menu_items(&priv->ctrl_handler, - &max96714_ctrl_ops, - V4L2_CID_TEST_PATTERN, - ARRAY_SIZE(max96714_test_pattern) - 1, - 0, 0, max96714_test_pattern); - if (priv->ctrl_handler.error) { - ret = priv->ctrl_handler.error; - goto err_free_ctrl; - } - - priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS; - priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; - priv->sd.entity.ops = &max96714_entity_ops; - - priv->pads[MAX96714_PAD_SINK].flags = MEDIA_PAD_FL_SINK; - priv->pads[MAX96714_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; - - ret = media_entity_pads_init(&priv->sd.entity, - MAX96714_NPORTS, - priv->pads); - if (ret) - goto err_free_ctrl; - - priv->sd.state_lock = priv->sd.ctrl_handler->lock; - - ret = v4l2_subdev_init_finalize(&priv->sd); - if (ret) - goto err_entity_cleanup; - - ret = max96714_v4l2_notifier_register(priv); - if (ret) { - dev_err(dev, "v4l2 subdev notifier register failed: %d\n", ret); - goto err_subdev_cleanup; - } - - ret = v4l2_async_register_subdev(&priv->sd); - if (ret) { - dev_err(dev, "v4l2_async_register_subdev error: %d\n", ret); - goto err_unreg_notif; - } - - return 0; - -err_unreg_notif: - v4l2_async_nf_unregister(&priv->notifier); - v4l2_async_nf_cleanup(&priv->notifier); -err_subdev_cleanup: - v4l2_subdev_cleanup(&priv->sd); -err_entity_cleanup: - media_entity_cleanup(&priv->sd.entity); -err_free_ctrl: - v4l2_ctrl_handler_free(&priv->ctrl_handler); - - return ret; -}; - -static void max96714_destroy_subdev(struct max96714_priv *priv) -{ - v4l2_async_nf_unregister(&priv->notifier); - v4l2_async_nf_cleanup(&priv->notifier); - v4l2_async_unregister_subdev(&priv->sd); - - v4l2_subdev_cleanup(&priv->sd); - - media_entity_cleanup(&priv->sd.entity); - v4l2_ctrl_handler_free(&priv->ctrl_handler); -} - -static int max96714_i2c_mux_select(struct i2c_mux_core *mux, u32 chan) -{ - return 0; -} - -static int max96714_i2c_mux_init(struct max96714_priv *priv) -{ - priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev, - 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE, - max96714_i2c_mux_select, NULL); - if (!priv->mux) - return -ENOMEM; - - return i2c_mux_add_adapter(priv->mux, 0, 0); -} - -static int max96714_init_tx_port(struct max96714_priv *priv) -{ - struct v4l2_mbus_config_mipi_csi2 *mipi; - unsigned long lanes_used = 0; - unsigned int val, lane; - int ret; - - ret = max96714_disable_tx_port(priv); - - mipi = &priv->mipi_csi2; - val = div_u64(priv->tx_link_freq * 2, MHZ(100)); - - cci_update_bits(priv->regmap, MAX96714_BACKTOP25, - CSI_DPLL_FREQ_MASK, val, &ret); - - val = FIELD_PREP(MAX96714_CSI2_LANE_CNT_MASK, mipi->num_data_lanes - 1); - cci_update_bits(priv->regmap, MAX96714_MIPI_LANE_CNT, - MAX96714_CSI2_LANE_CNT_MASK, val, &ret); - - /* lanes polarity */ - val = 0; - for (lane = 0; lane < mipi->num_data_lanes + 1; lane++) { - if (!mipi->lane_polarities[lane]) - continue; - if (lane == 0) - /* clock lane */ - val |= BIT(5); - else if (lane < 3) - /* Lane D0 and D1 */ - val |= BIT(lane - 1); - else - /* D2 and D3 */ - val |= BIT(lane); - } - - cci_update_bits(priv->regmap, MAX96714_MIPI_POLARITY, - MAX96714_MIPI_POLARITY_MASK, val, &ret); - - /* lanes mapping */ - val = 0; - for (lane = 0; lane < mipi->num_data_lanes; lane++) { - val |= (mipi->data_lanes[lane] - 1) << (lane * 2); - lanes_used |= BIT(mipi->data_lanes[lane] - 1); - } - - /* - * Unused lanes need to be mapped as well to not have - * the same lanes mapped twice. - */ - for (; lane < MAX96714_CSI_NLANES; lane++) { - unsigned int idx = find_first_zero_bit(&lanes_used, - MAX96714_CSI_NLANES); - - val |= idx << (lane * 2); - lanes_used |= BIT(idx); - } - - return cci_write(priv->regmap, MAX96714_MIPI_LANE_MAP, val, &ret); -} - -static int max96714_rxport_enable_poc(struct max96714_priv *priv) -{ - struct max96714_rxport *rxport = &priv->rxport; - - if (!rxport->poc) - return 0; - - return regulator_enable(rxport->poc); -} - -static int max96714_rxport_disable_poc(struct max96714_priv *priv) -{ - struct max96714_rxport *rxport = &priv->rxport; - - if (!rxport->poc) - return 0; - - return regulator_disable(rxport->poc); -} - -static int max96714_parse_dt_txport(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - struct fwnode_handle *ep_fwnode; - u32 num_data_lanes; - int ret; - - ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), - MAX96714_PAD_SOURCE, 0, 0); - if (!ep_fwnode) - return -EINVAL; - - ret = v4l2_fwnode_endpoint_alloc_parse(ep_fwnode, &vep); - fwnode_handle_put(ep_fwnode); - if (ret) { - dev_err(dev, "tx: failed to parse endpoint data\n"); - return -EINVAL; - } - - if (vep.nr_of_link_frequencies != 1) { - ret = -EINVAL; - goto err_free_vep; - } - - priv->tx_link_freq = vep.link_frequencies[0]; - /* Min 50MHz, Max 1250MHz, 50MHz step */ - if (priv->tx_link_freq < MHZ(50) || priv->tx_link_freq > MHZ(1250) || - (u32)priv->tx_link_freq % MHZ(50)) { - dev_err(dev, "tx: invalid link frequency\n"); - ret = -EINVAL; - goto err_free_vep; - } - - num_data_lanes = vep.bus.mipi_csi2.num_data_lanes; - if (num_data_lanes < 1 || num_data_lanes > MAX96714_CSI_NLANES) { - dev_err(dev, - "tx: invalid number of data lanes must be 1 to 4\n"); - ret = -EINVAL; - goto err_free_vep; - } - - priv->mipi_csi2 = vep.bus.mipi_csi2; - -err_free_vep: - v4l2_fwnode_endpoint_free(&vep); - - return ret; -} - -static int max96714_parse_dt_rxport(struct max96714_priv *priv) -{ - static const char *poc_name = "port0-poc"; - struct max96714_rxport *rxport = &priv->rxport; - struct device *dev = &priv->client->dev; - struct fwnode_handle *ep_fwnode; - int ret; - - ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), - MAX96714_PAD_SINK, 0, 0); - if (!ep_fwnode) - return -ENOENT; - - rxport->source.ep_fwnode = fwnode_graph_get_remote_endpoint(ep_fwnode); - fwnode_handle_put(ep_fwnode); - - if (!rxport->source.ep_fwnode) { - dev_err(dev, "rx: no remote endpoint\n"); - return -EINVAL; - } - - rxport->poc = devm_regulator_get_optional(dev, poc_name); - if (IS_ERR(rxport->poc)) { - ret = PTR_ERR(rxport->poc); - if (ret == -ENODEV) { - rxport->poc = NULL; - } else { - dev_err(dev, "rx: failed to get POC supply: %d\n", ret); - goto err_put_source_ep_fwnode; - } - } - - return 0; - -err_put_source_ep_fwnode: - fwnode_handle_put(rxport->source.ep_fwnode); - return ret; -} - -static int max96714_parse_dt(struct max96714_priv *priv) -{ - int ret; - - ret = max96714_parse_dt_txport(priv); - if (ret) - return ret; - - ret = max96714_parse_dt_rxport(priv); - /* - * The deserializer can create a test pattern even if the - * rx port is not connected to a serializer. - */ - if (ret && ret == -ENOENT) - ret = 0; - - return ret; -} - -static int max96714_enable_core_hw(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - u64 val; - int ret; - - if (priv->pd_gpio) { - /* wait min 2 ms for reset to complete */ - gpiod_set_value_cansleep(priv->pd_gpio, 1); - fsleep(2000); - gpiod_set_value_cansleep(priv->pd_gpio, 0); - /* wait min 2 ms for power up to finish */ - fsleep(2000); - } - - ret = cci_read(priv->regmap, MAX96714_REG13, &val, NULL); - if (ret) { - dev_err_probe(dev, ret, "Cannot read first register, abort\n"); - goto err_pd_gpio; - } - - if (val != MAX96714_DEVICE_ID && val != MAX96714F_DEVICE_ID) { - dev_err(dev, "Unsupported device id expected %x got %x\n", - MAX96714F_DEVICE_ID, (u8)val); - ret = -EOPNOTSUPP; - goto err_pd_gpio; - } - - ret = cci_read(priv->regmap, MAX96714_DEV_REV, &val, NULL); - if (ret) - goto err_pd_gpio; - - dev_dbg(dev, "Found %x (rev %lx)\n", MAX96714F_DEVICE_ID, - (u8)val & MAX96714_DEV_REV_MASK); - - ret = cci_read(priv->regmap, MAX96714_MIPI_TX52, &val, NULL); - if (ret) - goto err_pd_gpio; - - if (!(val & MAX96714_TUN_EN)) { - dev_err(dev, "Only supporting tunnel mode"); - ret = -EOPNOTSUPP; - goto err_pd_gpio; - } - - return 0; - -err_pd_gpio: - gpiod_set_value_cansleep(priv->pd_gpio, 1); - return ret; -} - -static void max96714_disable_core_hw(struct max96714_priv *priv) -{ - gpiod_set_value_cansleep(priv->pd_gpio, 1); -} - -static int max96714_get_hw_resources(struct max96714_priv *priv) -{ - struct device *dev = &priv->client->dev; - - priv->regmap = devm_cci_regmap_init_i2c(priv->client, 16); - if (IS_ERR(priv->regmap)) - return PTR_ERR(priv->regmap); - - priv->pd_gpio = - devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH); - if (IS_ERR(priv->pd_gpio)) - return dev_err_probe(dev, PTR_ERR(priv->pd_gpio), - "Cannot get powerdown GPIO\n"); - return 0; -} - -static int max96714_probe(struct i2c_client *client) -{ - struct device *dev = &client->dev; - struct max96714_priv *priv; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->client = client; - - ret = max96714_get_hw_resources(priv); - if (ret) - return ret; - - ret = max96714_enable_core_hw(priv); - if (ret) - return ret; - - ret = max96714_parse_dt(priv); - if (ret) - goto err_disable_core_hw; - - max96714_init_tx_port(priv); - - ret = max96714_rxport_enable_poc(priv); - if (ret) - goto err_free_ports; - - ret = max96714_i2c_mux_init(priv); - if (ret) - goto err_disable_poc; - - ret = max96714_create_subdev(priv); - if (ret) - goto err_del_mux; - - return 0; - -err_del_mux: - i2c_mux_del_adapters(priv->mux); -err_disable_poc: - max96714_rxport_disable_poc(priv); -err_free_ports: - fwnode_handle_put(priv->rxport.source.ep_fwnode); -err_disable_core_hw: - max96714_disable_core_hw(priv); - - return ret; -} - -static void max96714_remove(struct i2c_client *client) -{ - struct v4l2_subdev *sd = i2c_get_clientdata(client); - struct max96714_priv *priv = sd_to_max96714(sd); - - max96714_destroy_subdev(priv); - i2c_mux_del_adapters(priv->mux); - max96714_rxport_disable_poc(priv); - fwnode_handle_put(priv->rxport.source.ep_fwnode); - max96714_disable_core_hw(priv); - gpiod_set_value_cansleep(priv->pd_gpio, 1); -} - -static const struct of_device_id max96714_of_ids[] = { - { .compatible = "maxim,max96714f" }, - { } -}; -MODULE_DEVICE_TABLE(of, max96714_of_ids); - -static struct i2c_driver max96714_i2c_driver = { - .driver = { - .name = "max96714", - .of_match_table = max96714_of_ids, - }, - .probe = max96714_probe, - .remove = max96714_remove, -}; - -module_i2c_driver(max96714_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Maxim Integrated GMSL2 Deserializers Driver"); -MODULE_AUTHOR("Julien Massot ");