[PATCH v1 0/5] gpu/drm: tegra: add DSI support for Tegra20/Tegra30

STALE429d SUPERSEDED

Revision v1 of 7 in this series.

18 messages, 3 authors, 2025-08-16 · open the first message on its own page

[PATCH v1 0/5] gpu/drm: tegra: add DSI support for Tegra20/Tegra30

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-17 14:22:03

Tegra20/Tegra30 DSI is quite similar to Tegra114+ apart MIPI calibration
logic and clocks. With a few minor tweaks, existing tegra DSI driver
should work on Tegra20/Tegra30 devices just fine. Tested on
Motorola Atrix 4G (T20) and ASUS VivoTab RT TF600T (T30).

Svyatoslav Ryhel (5):
  dt-bindings: display: tegra: document MIPI calibration for
    Tegra20/Tegra30
  clk: tegra20: reparent dsi clock to pll_d_out0
  gpu/drm: host1x: mipi: add Tegra20/Tegra30 MIPI calibration logic
  gpu/drm: tegra: dsi: add support for Tegra20/Tegra30
  ARM: tegra: add MIPI calibration binding for Tegra20/Tegra30

 .../display/tegra/nvidia,tegra114-mipi.yaml   | 41 ++++++++--
 arch/arm/boot/dts/nvidia/tegra20.dtsi         | 14 ++++
 arch/arm/boot/dts/nvidia/tegra30.dtsi         | 18 ++++
 drivers/clk/tegra/clk-tegra20.c               |  5 +-
 drivers/gpu/drm/tegra/drm.c                   |  2 +
 drivers/gpu/drm/tegra/dsi.c                   | 69 ++++++++++------
 drivers/gpu/drm/tegra/dsi.h                   | 10 +++
 drivers/gpu/host1x/mipi.c                     | 82 +++++++++++++++++++
 8 files changed, 206 insertions(+), 35 deletions(-)

-- 
2.48.1

[PATCH v1 1/5] dt-bindings: display: tegra: document MIPI calibration for Tegra20/Tegra30

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-17 14:22:04

Adjust Tegra114 MIPI calibration schema to include Tegra20/Tegra30 MIPI
calibration logic.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 .../display/tegra/nvidia,tegra114-mipi.yaml   | 41 ++++++++++++++++---
 1 file changed, 36 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
index 193ddb105283..ddf1b9fff085 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
@@ -16,6 +16,8 @@ properties:
 
   compatible:
     enum:
+      - nvidia,tegra20-mipi
+      - nvidia,tegra30-mipi
       - nvidia,tegra114-mipi
       - nvidia,tegra124-mipi
       - nvidia,tegra210-mipi
@@ -25,12 +27,12 @@ properties:
     maxItems: 1
 
   clocks:
-    items:
-      - description: module clock
+    minItems: 1
+    maxItems: 2
 
   clock-names:
-    items:
-      - const: mipi-cal
+    minItems: 1
+    maxItems: 2
 
   power-domains:
     maxItems: 1
@@ -42,7 +44,36 @@ properties:
     $ref: /schemas/types.yaml#/definitions/uint32
     const: 1
 
-additionalProperties: false
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - nvidia,tegra20-dsi
+              - nvidia,tegra30-dsi
+    then:
+      properties:
+        clocks:
+          items:
+            - description: VI module clock
+            - description: CSI module clock
+
+        clock-names:
+          items:
+            - const: vi
+            - const: csi
+    else:
+      properties:
+        clocks:
+          items:
+            - description: module clock
+
+        clock-names:
+          items:
+            - const: mipi-cal
+
+unevaluatedProperties: false
 
 required:
   - compatible
-- 
2.48.1

[PATCH v1 2/5] clk: tegra20: reparent dsi clock to pll_d_out0

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-17 14:22:05

Reparent DSI clock to PLLD_OUT0 instead of directly descend from PLLD.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 drivers/clk/tegra/clk-tegra20.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 2c58ce25af75..551ef0cf0c9a 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -802,9 +802,8 @@ static void __init tegra20_periph_clk_init(void)
 	clks[TEGRA20_CLK_MC] = clk;
 
 	/* dsi */
-	clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
-				    48, periph_clk_enb_refcnt);
-	clk_register_clkdev(clk, NULL, "dsi");
+	clk = tegra_clk_register_periph_gate("dsi", "pll_d_out0", 0, clk_base,
+				    0, 48, periph_clk_enb_refcnt);
 	clks[TEGRA20_CLK_DSI] = clk;
 
 	/* pex */
-- 
2.48.1

[PATCH v1 3/5] gpu/drm: host1x: mipi: add Tegra20/Tegra30 MIPI calibration logic

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-17 14:22:07

Tegra20/Tegra30 have no dedicated MIPI calibration device and calibration
registers are incorporated into CSI. Lets reuse Tegra114 calibration
framework and add Tegra20/Tegra30 as a special case.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 drivers/gpu/host1x/mipi.c | 82 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)
diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index e51b43dd15a3..cfaa27e0f892 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -61,6 +61,13 @@
 #define MIPI_CAL_CONFIG_DSID_CLK	0x1d
 #define MIPI_CAL_CONFIG_CSIE_CLK	0x1d
 
+/* DSI V0 controller */
+#define CSI_CIL_PAD_CONFIG		0x09
+#define CSI_CILA_MIPI_CAL_CONFIG	0x0a
+#define CSI_CILB_MIPI_CAL_CONFIG	0x0b
+#define CSI_DSI_MIPI_CAL_CONFIG		0x14
+#define CSI_MIPIBIAS_PAD_CONFIG		0x15
+
 /* for data and clock lanes */
 #define MIPI_CAL_CONFIG_SELECT		(1 << 21)
 
@@ -92,6 +99,8 @@ struct tegra_mipi_pad {
 };
 
 struct tegra_mipi_soc {
+	bool dsi_v0;
+
 	bool has_clk_lane;
 	const struct tegra_mipi_pad *pads;
 	unsigned int num_pads;
@@ -122,6 +131,7 @@ struct tegra_mipi {
 	void __iomem *regs;
 	struct mutex lock;
 	struct clk *clk;
+	struct clk *csi_clk;
 
 	unsigned long usage_count;
 };
@@ -265,6 +275,9 @@ int tegra_mipi_enable(struct tegra_mipi_device *dev)
 {
 	int err = 0;
 
+	if (dev->mipi->soc->dsi_v0)
+		return 0;
+
 	mutex_lock(&dev->mipi->lock);
 
 	if (dev->mipi->usage_count++ == 0)
@@ -281,6 +294,9 @@ int tegra_mipi_disable(struct tegra_mipi_device *dev)
 {
 	int err = 0;
 
+	if (dev->mipi->soc->dsi_v0)
+		return 0;
+
 	mutex_lock(&dev->mipi->lock);
 
 	if (--dev->mipi->usage_count == 0)
@@ -300,6 +316,9 @@ int tegra_mipi_finish_calibration(struct tegra_mipi_device *device)
 	u32 value;
 	int err;
 
+	if (mipi->soc->dsi_v0)
+		return 0;
+
 	err = readl_relaxed_poll_timeout(status_reg, value,
 					 !(value & MIPI_CAL_STATUS_ACTIVE) &&
 					 (value & MIPI_CAL_STATUS_DONE), 50,
@@ -311,6 +330,43 @@ int tegra_mipi_finish_calibration(struct tegra_mipi_device *device)
 }
 EXPORT_SYMBOL(tegra_mipi_finish_calibration);
 
+static int tegra20_mipi_calibration(struct tegra_mipi_device *device)
+{
+	struct tegra_mipi *mipi = device->mipi;
+	const struct tegra_mipi_soc *soc = mipi->soc;
+	u32 value;
+	int err;
+
+	err = clk_enable(mipi->csi_clk);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&mipi->lock);
+
+	value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+	tegra_mipi_writel(mipi, value, CSI_CILA_MIPI_CAL_CONFIG);
+
+	value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+	tegra_mipi_writel(mipi, value, CSI_CILB_MIPI_CAL_CONFIG);
+
+	value = MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
+		MIPI_CAL_CONFIG_HSPUOS(soc->hspuos);
+	tegra_mipi_writel(mipi, value, CSI_DSI_MIPI_CAL_CONFIG);
+
+	value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
+		MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
+	tegra_mipi_writel(mipi, value, CSI_MIPIBIAS_PAD_CONFIG);
+
+	tegra_mipi_writel(mipi, 0x0, CSI_CIL_PAD_CONFIG);
+
+	mutex_unlock(&mipi->lock);
+
+	clk_disable(mipi->csi_clk);
+	clk_disable(mipi->clk);
+
+	return 0;
+}
+
 int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
 {
 	const struct tegra_mipi_soc *soc = device->mipi->soc;
@@ -322,6 +378,9 @@ int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
 	if (err < 0)
 		return err;
 
+	if (soc->dsi_v0)
+		return tegra20_mipi_calibration(device);
+
 	mutex_lock(&device->mipi->lock);
 
 	value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
@@ -386,6 +445,15 @@ int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
 }
 EXPORT_SYMBOL(tegra_mipi_start_calibration);
 
+static const struct tegra_mipi_soc tegra20_mipi_soc = {
+	.dsi_v0 = true,
+	.pad_drive_down_ref = 0x5,
+	.pad_drive_up_ref = 0x7,
+	.hspdos = 0x4,
+	.hspuos = 0x3,
+	.termos = 0x4,
+};
+
 static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
 	{ .data = MIPI_CAL_CONFIG_CSIA },
 	{ .data = MIPI_CAL_CONFIG_CSIB },
@@ -399,6 +467,7 @@ static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
 };
 
 static const struct tegra_mipi_soc tegra114_mipi_soc = {
+	.dsi_v0 = false,
 	.has_clk_lane = false,
 	.pads = tegra114_mipi_pads,
 	.num_pads = ARRAY_SIZE(tegra114_mipi_pads),
@@ -426,6 +495,7 @@ static const struct tegra_mipi_pad tegra124_mipi_pads[] = {
 };
 
 static const struct tegra_mipi_soc tegra124_mipi_soc = {
+	.dsi_v0 = false,
 	.has_clk_lane = true,
 	.pads = tegra124_mipi_pads,
 	.num_pads = ARRAY_SIZE(tegra124_mipi_pads),
@@ -443,6 +513,7 @@ static const struct tegra_mipi_soc tegra124_mipi_soc = {
 };
 
 static const struct tegra_mipi_soc tegra132_mipi_soc = {
+	.dsi_v0 = false,
 	.has_clk_lane = true,
 	.pads = tegra124_mipi_pads,
 	.num_pads = ARRAY_SIZE(tegra124_mipi_pads),
@@ -473,6 +544,7 @@ static const struct tegra_mipi_pad tegra210_mipi_pads[] = {
 };
 
 static const struct tegra_mipi_soc tegra210_mipi_soc = {
+	.dsi_v0 = false,
 	.has_clk_lane = true,
 	.pads = tegra210_mipi_pads,
 	.num_pads = ARRAY_SIZE(tegra210_mipi_pads),
@@ -490,6 +562,8 @@ static const struct tegra_mipi_soc tegra210_mipi_soc = {
 };
 
 static const struct of_device_id tegra_mipi_of_match[] = {
+	{ .compatible = "nvidia,tegra20-mipi", .data = &tegra20_mipi_soc },
+	{ .compatible = "nvidia,tegra30-mipi", .data = &tegra20_mipi_soc },
 	{ .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc },
 	{ .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc },
 	{ .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc },
@@ -525,6 +599,14 @@ static int tegra_mipi_probe(struct platform_device *pdev)
 		return PTR_ERR(mipi->clk);
 	}
 
+	if (mipi->soc->dsi_v0) {
+		mipi->csi_clk = devm_clk_get_prepared(&pdev->dev, "csi");
+		if (IS_ERR(mipi->csi_clk)) {
+			dev_err(&pdev->dev, "failed to get CSI clock\n");
+			return PTR_ERR(mipi->csi_clk);
+		}
+	}
+
 	platform_set_drvdata(pdev, mipi);
 
 	return 0;
-- 
2.48.1

[PATCH v1 4/5] gpu/drm: tegra: dsi: add support for Tegra20/Tegra30

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-17 14:22:08

Tegra20/Tegra30 are fully compatible with existing tegra DSI driver apart
clock configuration and MIPI calibration which are addressed by this patch.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 drivers/gpu/drm/tegra/drm.c |  2 ++
 drivers/gpu/drm/tegra/dsi.c | 69 ++++++++++++++++++++++---------------
 drivers/gpu/drm/tegra/dsi.h | 10 ++++++
 3 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 4596073fe28f..5d64cd57e764 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1359,10 +1359,12 @@ static SIMPLE_DEV_PM_OPS(host1x_drm_pm_ops, host1x_drm_suspend,
 
 static const struct of_device_id host1x_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra20-dc", },
+	{ .compatible = "nvidia,tegra20-dsi", },
 	{ .compatible = "nvidia,tegra20-hdmi", },
 	{ .compatible = "nvidia,tegra20-gr2d", },
 	{ .compatible = "nvidia,tegra20-gr3d", },
 	{ .compatible = "nvidia,tegra30-dc", },
+	{ .compatible = "nvidia,tegra30-dsi", },
 	{ .compatible = "nvidia,tegra30-hdmi", },
 	{ .compatible = "nvidia,tegra30-gr2d", },
 	{ .compatible = "nvidia,tegra30-gr3d", },
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 3f91a24ebef2..85bcb8bee1ae 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -662,39 +662,48 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
 {
 	u32 value;
 
-	value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
-	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+	/* Tegra20/30 uses DSIv0 while Tegra114+ uses DSIv1 */
+	if (of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra20-dsi") ||
+	    of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra30-dsi")) {
+		value = DSI_PAD_CONTROL_LPUPADJ(0x1) | DSI_PAD_CONTROL_LPDNADJ(0x1) |
+			DSI_PAD_CONTROL_PREEMP_EN(0x1) | DSI_PAD_CONTROL_SLEWDNADJ(0x6) |
+			DSI_PAD_CONTROL_SLEWUPADJ(0x6) | DSI_PAD_CONTROL_PDIO(0) |
+			DSI_PAD_CONTROL_PDIO_CLK(0) | DSI_PAD_CONTROL_PULLDN_ENAB(0);
+		tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+	} else {
+		/*
+		 * XXX Is this still needed? The module reset is deasserted right
+		 * before this function is called.
+		 */
+		tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
+		tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
+		tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
+		tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
+		tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
+
+		value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
+		tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+
+		value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
+			DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
+			DSI_PAD_OUT_CLK(0x0);
+		tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
+
+		value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
+			DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
+		tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
+	}
 
 	return 0;
 }
 
 static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
 {
-	u32 value;
 	int err;
 
-	/*
-	 * XXX Is this still needed? The module reset is deasserted right
-	 * before this function is called.
-	 */
-	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
-	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
-	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
-	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
-	tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
-
 	/* start calibration */
 	tegra_dsi_pad_enable(dsi);
 
-	value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
-		DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
-		DSI_PAD_OUT_CLK(0x0);
-	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
-
-	value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
-		DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
-	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
-
 	err = tegra_mipi_start_calibration(dsi->mipi);
 	if (err < 0)
 		return err;
@@ -1615,7 +1624,7 @@ static int tegra_dsi_probe(struct platform_device *pdev)
 		goto remove;
 	}
 
-	dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
+	dsi->clk_lp = devm_clk_get_optional(&pdev->dev, "lp");
 	if (IS_ERR(dsi->clk_lp)) {
 		err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_lp),
 				    "cannot get low-power clock\n");
@@ -1636,10 +1645,14 @@ static int tegra_dsi_probe(struct platform_device *pdev)
 		goto remove;
 	}
 
-	err = tegra_dsi_setup_clocks(dsi);
-	if (err < 0) {
-		dev_err(&pdev->dev, "cannot setup clocks\n");
-		goto remove;
+	/* Tegra20/Tegra30 do not use DSI parent muxing */
+	if (!of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra20-dsi") &&
+	    !of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra30-dsi")) {
+		err = tegra_dsi_setup_clocks(dsi);
+		if (err < 0) {
+			dev_err(&pdev->dev, "cannot setup clocks\n");
+			return err;
+		}
 	}
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1709,6 +1722,8 @@ static const struct of_device_id tegra_dsi_of_match[] = {
 	{ .compatible = "nvidia,tegra132-dsi", },
 	{ .compatible = "nvidia,tegra124-dsi", },
 	{ .compatible = "nvidia,tegra114-dsi", },
+	{ .compatible = "nvidia,tegra30-dsi", },
+	{ .compatible = "nvidia,tegra20-dsi", },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
diff --git a/drivers/gpu/drm/tegra/dsi.h b/drivers/gpu/drm/tegra/dsi.h
index f39594e65e97..d834ac0c47ab 100644
--- a/drivers/gpu/drm/tegra/dsi.h
+++ b/drivers/gpu/drm/tegra/dsi.h
@@ -95,6 +95,16 @@
 #define DSI_TALLY_LRX(x)		(((x) & 0xff) <<  8)
 #define DSI_TALLY_HTX(x)		(((x) & 0xff) <<  0)
 #define DSI_PAD_CONTROL_0		0x4b
+/* Tegra20/Tegra30 */
+#define DSI_PAD_CONTROL_PULLDN_ENAB(x)	(((x) & 0x1) << 28)
+#define DSI_PAD_CONTROL_SLEWUPADJ(x)	(((x) & 0x7) << 24)
+#define DSI_PAD_CONTROL_SLEWDNADJ(x)	(((x) & 0x7) << 20)
+#define DSI_PAD_CONTROL_PREEMP_EN(x)	(((x) & 0x1) << 19)
+#define DSI_PAD_CONTROL_PDIO_CLK(x)	(((x) & 0x1) << 18)
+#define DSI_PAD_CONTROL_PDIO(x)		(((x) & 0x3) << 16)
+#define DSI_PAD_CONTROL_LPUPADJ(x)	(((x) & 0x3) << 14)
+#define DSI_PAD_CONTROL_LPDNADJ(x)	(((x) & 0x3) << 12)
+/* Tegra114+ */
 #define DSI_PAD_CONTROL_VS1_PDIO(x)	(((x) & 0xf) <<  0)
 #define DSI_PAD_CONTROL_VS1_PDIO_CLK	(1 <<  8)
 #define DSI_PAD_CONTROL_VS1_PULLDN(x)	(((x) & 0xf) << 16)
-- 
2.48.1

[PATCH v1 5/5] ARM: tegra: add MIPI calibration binding for Tegra20/Tegra30

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-17 14:22:10

Add MIPI calibration device node for Tegra20 and Tegra30.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 arch/arm/boot/dts/nvidia/tegra20.dtsi | 14 ++++++++++++++
 arch/arm/boot/dts/nvidia/tegra30.dtsi | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi b/arch/arm/boot/dts/nvidia/tegra20.dtsi
index 92d422f83ea4..521261045cc8 100644
--- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
@@ -74,6 +74,16 @@ vi@54080000 {
 			status = "disabled";
 		};
 
+		/* DSI MIPI calibration logic is a part of VI/CSI */
+		mipi: mipi@54080220 {
+			compatible = "nvidia,tegra20-mipi";
+			reg = <0x54080220 0x100>;
+			clocks = <&tegra_car TEGRA20_CLK_VI>,
+				 <&tegra_car TEGRA20_CLK_CSI>;
+			clock-names = "vi", "csi";
+			#nvidia,mipi-calibrate-cells = <1>;
+		};
+
 		epp@540c0000 {
 			compatible = "nvidia,tegra20-epp";
 			reg = <0x540c0000 0x00040000>;
@@ -219,9 +229,13 @@ dsi@54300000 {
 			clock-names = "dsi", "parent";
 			resets = <&tegra_car 48>;
 			reset-names = "dsi";
+			nvidia,mipi-calibrate = <&mipi 0>;
 			power-domains = <&pd_core>;
 			operating-points-v2 = <&dsi_dvfs_opp_table>;
 			status = "disabled";
+
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/nvidia/tegra30.dtsi b/arch/arm/boot/dts/nvidia/tegra30.dtsi
index 50b0446f43fc..c52ad3715505 100644
--- a/arch/arm/boot/dts/nvidia/tegra30.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30.dtsi
@@ -164,6 +164,16 @@ vi@54080000 {
 			status = "disabled";
 		};
 
+		/* DSI MIPI calibration logic is a part of VI/CSI */
+		mipi: mipi@54080220 {
+			compatible = "nvidia,tegra30-mipi";
+			reg = <0x54080220 0x100>;
+			clocks = <&tegra_car TEGRA30_CLK_VI>,
+				 <&tegra_car TEGRA30_CLK_CSI>;
+			clock-names = "vi", "csi";
+			#nvidia,mipi-calibrate-cells = <1>;
+		};
+
 		epp@540c0000 {
 			compatible = "nvidia,tegra30-epp";
 			reg = <0x540c0000 0x00040000>;
@@ -321,9 +331,13 @@ dsi@54300000 {
 			clock-names = "dsi", "parent";
 			resets = <&tegra_car 48>;
 			reset-names = "dsi";
+			nvidia,mipi-calibrate = <&mipi 0>;
 			power-domains = <&pd_core>;
 			operating-points-v2 = <&dsia_dvfs_opp_table>;
 			status = "disabled";
+
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 
 		dsi@54400000 {
@@ -334,9 +348,13 @@ dsi@54400000 {
 			clock-names = "dsi", "parent";
 			resets = <&tegra_car 84>;
 			reset-names = "dsi";
+			nvidia,mipi-calibrate = <&mipi 0>;
 			power-domains = <&pd_core>;
 			operating-points-v2 = <&dsib_dvfs_opp_table>;
 			status = "disabled";
+
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 	};
 
-- 
2.48.1

Re: [PATCH v1 5/5] ARM: tegra: add MIPI calibration binding for Tegra20/Tegra30

From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2025-07-18 09:01:46

On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted hunk
Add MIPI calibration device node for Tegra20 and Tegra30.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 arch/arm/boot/dts/nvidia/tegra20.dtsi | 14 ++++++++++++++
 arch/arm/boot/dts/nvidia/tegra30.dtsi | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi
b/arch/arm/boot/dts/nvidia/tegra20.dtsi index 92d422f83ea4..521261045cc8
100644
--- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
@@ -74,6 +74,16 @@ vi@54080000 {
 			status = "disabled";
 		};

+		/* DSI MIPI calibration logic is a part of VI/CSI */
+		mipi: mipi@54080220 {
+			compatible = "nvidia,tegra20-mipi";
+			reg = <0x54080220 0x100>;
+			clocks = <&tegra_car TEGRA20_CLK_VI>,
+				 <&tegra_car TEGRA20_CLK_CSI>;
+			clock-names = "vi", "csi";
+			#nvidia,mipi-calibrate-cells = <1>;
+		};
+
As you say in the comment, MIPI calibration on Tegra20/30 is part of VI/CSI. 
We can't add a "mipi" device here since such a device doesn't exist in the 
hardware hierarchy. We already have the VI device in the device tree, so we 
need to use that.

A driver for tegra20-vi already exists in staging/drivers/media/tegra-video. 
We should aim not to break it. Perhaps bring it out of staging? (At least 
partially, but then why not the whole thing.)

Thanks,
Mikko



Re: [PATCH v1 3/5] gpu/drm: host1x: mipi: add Tegra20/Tegra30 MIPI calibration logic

From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2025-07-18 09:11:16

On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted hunk
...
@@ -311,6 +330,43 @@ int tegra_mipi_finish_calibration(struct
tegra_mipi_device *device) }
 EXPORT_SYMBOL(tegra_mipi_finish_calibration);

+static int tegra20_mipi_calibration(struct tegra_mipi_device *device)
+{
+	struct tegra_mipi *mipi = device->mipi;
+	const struct tegra_mipi_soc *soc = mipi->soc;
+	u32 value;
+	int err;
+
+	err = clk_enable(mipi->csi_clk);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&mipi->lock);
+
+	value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+	tegra_mipi_writel(mipi, value, CSI_CILA_MIPI_CAL_CONFIG);
+
+	value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+	tegra_mipi_writel(mipi, value, CSI_CILB_MIPI_CAL_CONFIG);
+
+	value = MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
+		MIPI_CAL_CONFIG_HSPUOS(soc->hspuos);
+	tegra_mipi_writel(mipi, value, CSI_DSI_MIPI_CAL_CONFIG);
+
+	value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
+		MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
+	tegra_mipi_writel(mipi, value, CSI_MIPIBIAS_PAD_CONFIG);
+
+	tegra_mipi_writel(mipi, 0x0, CSI_CIL_PAD_CONFIG);
+
+	mutex_unlock(&mipi->lock);
+
+	clk_disable(mipi->csi_clk);
+	clk_disable(mipi->clk);
+
+	return 0;
+}
+
Where does this sequence come from? It looks a bit strange to me, since it 
doesn't trigger calibration at all. It would be useful to mention the source 
in the commit message.

Mikko


Re: [PATCH v1 4/5] gpu/drm: tegra: dsi: add support for Tegra20/Tegra30

From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2025-07-18 09:15:16

On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
Tegra20/Tegra30 are fully compatible with existing tegra DSI driver apart
'apart from'
quoted hunk
clock configuration and MIPI calibration which are addressed by this patch.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 drivers/gpu/drm/tegra/drm.c |  2 ++
 drivers/gpu/drm/tegra/dsi.c | 69 ++++++++++++++++++++++---------------
 drivers/gpu/drm/tegra/dsi.h | 10 ++++++
 3 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 4596073fe28f..5d64cd57e764 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1359,10 +1359,12 @@ static SIMPLE_DEV_PM_OPS(host1x_drm_pm_ops,
host1x_drm_suspend,

 static const struct of_device_id host1x_drm_subdevs[] = {
 	{ .compatible = "nvidia,tegra20-dc", },
+	{ .compatible = "nvidia,tegra20-dsi", },
 	{ .compatible = "nvidia,tegra20-hdmi", },
 	{ .compatible = "nvidia,tegra20-gr2d", },
 	{ .compatible = "nvidia,tegra20-gr3d", },
 	{ .compatible = "nvidia,tegra30-dc", },
+	{ .compatible = "nvidia,tegra30-dsi", },
 	{ .compatible = "nvidia,tegra30-hdmi", },
 	{ .compatible = "nvidia,tegra30-gr2d", },
 	{ .compatible = "nvidia,tegra30-gr3d", },
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 3f91a24ebef2..85bcb8bee1ae 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -662,39 +662,48 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
{
 	u32 value;

-	value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
-	tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+	/* Tegra20/30 uses DSIv0 while Tegra114+ uses DSIv1 */
+	if (of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra20-dsi") 
||
+	    of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra30-dsi"))
You need to add "soc data" structures to the of_match table instead of 
checking for compatible string in the code itself.

Thanks,
Mikko



Re: [PATCH v1 5/5] ARM: tegra: add MIPI calibration binding for Tegra20/Tegra30

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-18 09:15:36

пт, 18 лип. 2025 р. о 12:01 Mikko Perttunen [off-list ref] пише:
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
Add MIPI calibration device node for Tegra20 and Tegra30.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 arch/arm/boot/dts/nvidia/tegra20.dtsi | 14 ++++++++++++++
 arch/arm/boot/dts/nvidia/tegra30.dtsi | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi
b/arch/arm/boot/dts/nvidia/tegra20.dtsi index 92d422f83ea4..521261045cc8
100644
--- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
@@ -74,6 +74,16 @@ vi@54080000 {
                      status = "disabled";
              };

+             /* DSI MIPI calibration logic is a part of VI/CSI */
+             mipi: mipi@54080220 {
+                     compatible = "nvidia,tegra20-mipi";
+                     reg = <0x54080220 0x100>;
+                     clocks = <&tegra_car TEGRA20_CLK_VI>,
+                              <&tegra_car TEGRA20_CLK_CSI>;
+                     clock-names = "vi", "csi";
+                     #nvidia,mipi-calibrate-cells = <1>;
+             };
+
As you say in the comment, MIPI calibration on Tegra20/30 is part of VI/CSI.
We can't add a "mipi" device here since such a device doesn't exist in the
hardware hierarchy. We already have the VI device in the device tree, so we
need to use that.
I understand your point, but embedding MIPI calibration logic into
VI/CSI driver will bring up another lever of unnecessary complexity
and excessive coding. While approach I have proposed preserves
separation between CSI and DSI and reuses already existing MIPI
calibration framework.
A driver for tegra20-vi already exists in staging/drivers/media/tegra-video.
We should aim not to break it. Perhaps bring it out of staging? (At least
partially, but then why not the whole thing.)
It does not break VI/CSI, I have a WIP CSI implementation for
Tegra20/Tegra30 which I hope to submit soon.
Thanks,
Mikko


Re: [PATCH v1 3/5] gpu/drm: host1x: mipi: add Tegra20/Tegra30 MIPI calibration logic

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-18 09:18:07

пт, 18 лип. 2025 р. о 12:11 Mikko Perttunen [off-list ref] пише:
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
...
@@ -311,6 +330,43 @@ int tegra_mipi_finish_calibration(struct
tegra_mipi_device *device) }
 EXPORT_SYMBOL(tegra_mipi_finish_calibration);

+static int tegra20_mipi_calibration(struct tegra_mipi_device *device)
+{
+     struct tegra_mipi *mipi = device->mipi;
+     const struct tegra_mipi_soc *soc = mipi->soc;
+     u32 value;
+     int err;
+
+     err = clk_enable(mipi->csi_clk);
+     if (err < 0)
+             return err;
+
+     mutex_lock(&mipi->lock);
+
+     value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+     tegra_mipi_writel(mipi, value, CSI_CILA_MIPI_CAL_CONFIG);
+
+     value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+     tegra_mipi_writel(mipi, value, CSI_CILB_MIPI_CAL_CONFIG);
+
+     value = MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
+             MIPI_CAL_CONFIG_HSPUOS(soc->hspuos);
+     tegra_mipi_writel(mipi, value, CSI_DSI_MIPI_CAL_CONFIG);
+
+     value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
+             MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
+     tegra_mipi_writel(mipi, value, CSI_MIPIBIAS_PAD_CONFIG);
+
+     tegra_mipi_writel(mipi, 0x0, CSI_CIL_PAD_CONFIG);
+
+     mutex_unlock(&mipi->lock);
+
+     clk_disable(mipi->csi_clk);
+     clk_disable(mipi->clk);
+
+     return 0;
+}
+
Where does this sequence come from? It looks a bit strange to me, since it
doesn't trigger calibration at all. It would be useful to mention the source
in the commit message.

Mikko
Downstream nvidia sources, 3.1.10 and 3.4, dsi driver, function
tegra_dsi_pad_calibration

Re: [PATCH v1 4/5] gpu/drm: tegra: dsi: add support for Tegra20/Tegra30

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-18 09:19:37

пт, 18 лип. 2025 р. о 12:15 Mikko Perttunen [off-list ref] пише:
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
Tegra20/Tegra30 are fully compatible with existing tegra DSI driver apart
'apart from'
quoted
clock configuration and MIPI calibration which are addressed by this patch.

Signed-off-by: Svyatoslav Ryhel <redacted>
---
 drivers/gpu/drm/tegra/drm.c |  2 ++
 drivers/gpu/drm/tegra/dsi.c | 69 ++++++++++++++++++++++---------------
 drivers/gpu/drm/tegra/dsi.h | 10 ++++++
 3 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 4596073fe28f..5d64cd57e764 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1359,10 +1359,12 @@ static SIMPLE_DEV_PM_OPS(host1x_drm_pm_ops,
host1x_drm_suspend,

 static const struct of_device_id host1x_drm_subdevs[] = {
      { .compatible = "nvidia,tegra20-dc", },
+     { .compatible = "nvidia,tegra20-dsi", },
      { .compatible = "nvidia,tegra20-hdmi", },
      { .compatible = "nvidia,tegra20-gr2d", },
      { .compatible = "nvidia,tegra20-gr3d", },
      { .compatible = "nvidia,tegra30-dc", },
+     { .compatible = "nvidia,tegra30-dsi", },
      { .compatible = "nvidia,tegra30-hdmi", },
      { .compatible = "nvidia,tegra30-gr2d", },
      { .compatible = "nvidia,tegra30-gr3d", },
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 3f91a24ebef2..85bcb8bee1ae 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -662,39 +662,48 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
{
      u32 value;

-     value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
-     tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+     /* Tegra20/30 uses DSIv0 while Tegra114+ uses DSIv1 */
+     if (of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra20-dsi")
||
quoted
+         of_device_is_compatible(dsi->dev->of_node, "nvidia,tegra30-dsi"))
You need to add "soc data" structures to the of_match table instead of
checking for compatible string in the code itself.
I assumed that introducing "soc data" for 2 occurrences would be excessive.
Thanks,
Mikko


Re: [PATCH v1 5/5] ARM: tegra: add MIPI calibration binding for Tegra20/Tegra30

From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2025-07-18 09:22:51

On Friday, July 18, 2025 6:15 PM Svyatoslav Ryhel wrote:
пт, 18 лип. 2025 р. о 12:01 Mikko Perttunen [off-list ref] пише:
quoted
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
Add MIPI calibration device node for Tegra20 and Tegra30.

Signed-off-by: Svyatoslav Ryhel <redacted>
---

 arch/arm/boot/dts/nvidia/tegra20.dtsi | 14 ++++++++++++++
 arch/arm/boot/dts/nvidia/tegra30.dtsi | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi
b/arch/arm/boot/dts/nvidia/tegra20.dtsi index 92d422f83ea4..521261045cc8
100644
--- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
@@ -74,6 +74,16 @@ vi@54080000 {

                      status = "disabled";
              
              };

+             /* DSI MIPI calibration logic is a part of VI/CSI */
+             mipi: mipi@54080220 {
+                     compatible = "nvidia,tegra20-mipi";
+                     reg = <0x54080220 0x100>;
+                     clocks = <&tegra_car TEGRA20_CLK_VI>,
+                              <&tegra_car TEGRA20_CLK_CSI>;
+                     clock-names = "vi", "csi";
+                     #nvidia,mipi-calibrate-cells = <1>;
+             };
+
As you say in the comment, MIPI calibration on Tegra20/30 is part of
VI/CSI. We can't add a "mipi" device here since such a device doesn't
exist in the hardware hierarchy. We already have the VI device in the
device tree, so we need to use that.
I understand your point, but embedding MIPI calibration logic into
VI/CSI driver will bring up another lever of unnecessary complexity
and excessive coding. While approach I have proposed preserves
separation between CSI and DSI and reuses already existing MIPI
calibration framework.
We can consider different driver architectures to simplify things, but the 
device tree has to conform to hardware. The host1x bus has no 'mipi' device on 
it so we can't put one in the device tree.
quoted
A driver for tegra20-vi already exists in
staging/drivers/media/tegra-video. We should aim not to break it. Perhaps
bring it out of staging? (At least partially, but then why not the whole
thing.)
It does not break VI/CSI, I have a WIP CSI implementation for
Tegra20/Tegra30 which I hope to submit soon.
We have to use the tegra20-vi node as that matches hardware, and each node can 
only be probed to one device, hence the issue.

Great to see a CSI driver!

Mikko
quoted
Thanks,
Mikko


Re: [PATCH v1 4/5] gpu/drm: tegra: dsi: add support for Tegra20/Tegra30

From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2025-07-18 09:25:51

On Friday, July 18, 2025 6:19 PM Svyatoslav Ryhel wrote:
пт, 18 лип. 2025 р. о 12:15 Mikko Perttunen [off-list ref] пише:
quoted
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
Tegra20/Tegra30 are fully compatible with existing tegra DSI driver
apart
'apart from'
quoted
clock configuration and MIPI calibration which are addressed by this
patch.

Signed-off-by: Svyatoslav Ryhel <redacted>
---

 drivers/gpu/drm/tegra/drm.c |  2 ++
 drivers/gpu/drm/tegra/dsi.c | 69 ++++++++++++++++++++++---------------
 drivers/gpu/drm/tegra/dsi.h | 10 ++++++
 3 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 4596073fe28f..5d64cd57e764 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1359,10 +1359,12 @@ static SIMPLE_DEV_PM_OPS(host1x_drm_pm_ops,
host1x_drm_suspend,

 static const struct of_device_id host1x_drm_subdevs[] = {
 
      { .compatible = "nvidia,tegra20-dc", },

+     { .compatible = "nvidia,tegra20-dsi", },

      { .compatible = "nvidia,tegra20-hdmi", },
      { .compatible = "nvidia,tegra20-gr2d", },
      { .compatible = "nvidia,tegra20-gr3d", },
      { .compatible = "nvidia,tegra30-dc", },

+     { .compatible = "nvidia,tegra30-dsi", },

      { .compatible = "nvidia,tegra30-hdmi", },
      { .compatible = "nvidia,tegra30-gr2d", },
      { .compatible = "nvidia,tegra30-gr3d", },
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 3f91a24ebef2..85bcb8bee1ae 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -662,39 +662,48 @@ static int tegra_dsi_pad_enable(struct tegra_dsi
*dsi) {

      u32 value;

-     value = DSI_PAD_CONTROL_VS1_PULLDN(0) |
DSI_PAD_CONTROL_VS1_PDIO(0);
-     tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
+     /* Tegra20/30 uses DSIv0 while Tegra114+ uses DSIv1 */
+     if (of_device_is_compatible(dsi->dev->of_node,
"nvidia,tegra20-dsi")

+         of_device_is_compatible(dsi->dev->of_node,
"nvidia,tegra30-dsi"))
You need to add "soc data" structures to the of_match table instead of
checking for compatible string in the code itself.
I assumed that introducing "soc data" for 2 occurrences would be excessive.
Even one occurrence is enough :) No device tree properties should be accessed 
after probe.

Cheers,
Mikko
quoted
Thanks,
Mikko


Re: [PATCH v1 5/5] ARM: tegra: add MIPI calibration binding for Tegra20/Tegra30

From: Svyatoslav Ryhel <hidden>
Date: 2025-07-18 09:26:19

пт, 18 лип. 2025 р. о 12:22 Mikko Perttunen [off-list ref] пише:
On Friday, July 18, 2025 6:15 PM Svyatoslav Ryhel wrote:
quoted
пт, 18 лип. 2025 р. о 12:01 Mikko Perttunen [off-list ref] пише:
quoted
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
Add MIPI calibration device node for Tegra20 and Tegra30.

Signed-off-by: Svyatoslav Ryhel <redacted>
---

 arch/arm/boot/dts/nvidia/tegra20.dtsi | 14 ++++++++++++++
 arch/arm/boot/dts/nvidia/tegra30.dtsi | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi
b/arch/arm/boot/dts/nvidia/tegra20.dtsi index 92d422f83ea4..521261045cc8
100644
--- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
@@ -74,6 +74,16 @@ vi@54080000 {

                      status = "disabled";

              };

+             /* DSI MIPI calibration logic is a part of VI/CSI */
+             mipi: mipi@54080220 {
+                     compatible = "nvidia,tegra20-mipi";
+                     reg = <0x54080220 0x100>;
+                     clocks = <&tegra_car TEGRA20_CLK_VI>,
+                              <&tegra_car TEGRA20_CLK_CSI>;
+                     clock-names = "vi", "csi";
+                     #nvidia,mipi-calibrate-cells = <1>;
+             };
+
As you say in the comment, MIPI calibration on Tegra20/30 is part of
VI/CSI. We can't add a "mipi" device here since such a device doesn't
exist in the hardware hierarchy. We already have the VI device in the
device tree, so we need to use that.
I understand your point, but embedding MIPI calibration logic into
VI/CSI driver will bring up another lever of unnecessary complexity
and excessive coding. While approach I have proposed preserves
separation between CSI and DSI and reuses already existing MIPI
calibration framework.
We can consider different driver architectures to simplify things, but the
device tree has to conform to hardware. The host1x bus has no 'mipi' device on
it so we can't put one in the device tree.
I assume then placing mipi node as CSI or VI child would resolve your concern?
quoted
quoted
A driver for tegra20-vi already exists in
staging/drivers/media/tegra-video. We should aim not to break it. Perhaps
bring it out of staging? (At least partially, but then why not the whole
thing.)
It does not break VI/CSI, I have a WIP CSI implementation for
Tegra20/Tegra30 which I hope to submit soon.
We have to use the tegra20-vi node as that matches hardware, and each node can
only be probed to one device, hence the issue.

Great to see a CSI driver!

Mikko
quoted
quoted
Thanks,
Mikko

Re: [PATCH v1 3/5] gpu/drm: host1x: mipi: add Tegra20/Tegra30 MIPI calibration logic

From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2025-07-23 01:36:34

On Friday, July 18, 2025 6:17 PM Svyatoslav Ryhel wrote:
пт, 18 лип. 2025 р. о 12:11 Mikko Perttunen [off-list ref] пише:
quoted
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
...
@@ -311,6 +330,43 @@ int tegra_mipi_finish_calibration(struct
tegra_mipi_device *device) }

 EXPORT_SYMBOL(tegra_mipi_finish_calibration);

+static int tegra20_mipi_calibration(struct tegra_mipi_device *device)
+{
+     struct tegra_mipi *mipi = device->mipi;
+     const struct tegra_mipi_soc *soc = mipi->soc;
+     u32 value;
+     int err;
+
+     err = clk_enable(mipi->csi_clk);
+     if (err < 0)
+             return err;
+
+     mutex_lock(&mipi->lock);
+
+     value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+     tegra_mipi_writel(mipi, value, CSI_CILA_MIPI_CAL_CONFIG);
+
+     value = MIPI_CAL_CONFIG_TERMOS(soc->termos);
+     tegra_mipi_writel(mipi, value, CSI_CILB_MIPI_CAL_CONFIG);
+
+     value = MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
+             MIPI_CAL_CONFIG_HSPUOS(soc->hspuos);
+     tegra_mipi_writel(mipi, value, CSI_DSI_MIPI_CAL_CONFIG);
+
+     value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
+             MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
+     tegra_mipi_writel(mipi, value, CSI_MIPIBIAS_PAD_CONFIG);
+
+     tegra_mipi_writel(mipi, 0x0, CSI_CIL_PAD_CONFIG);
+
+     mutex_unlock(&mipi->lock);
+
+     clk_disable(mipi->csi_clk);
+     clk_disable(mipi->clk);
+
+     return 0;
+}
+
Where does this sequence come from? It looks a bit strange to me, since it
doesn't trigger calibration at all. It would be useful to mention the
source in the commit message.

Mikko
Downstream nvidia sources, 3.1.10 and 3.4, dsi driver, function
tegra_dsi_pad_calibration
Thanks!

Indeed, looks like for DSI calibration, the HW calibration is never triggered. 
However, for CSI pads, it is. We should take this into account in the device 
tree binding (and driver when CSI support is added) -- the parameter in 
nvidia,mipi-calibrate should specify we're calibrating DSI (probably with an 
enumeration defined in a header file).

Another thing -- the commit subject prefix for gpu/host1x is "gpu: host1x: ", 
and for gpu/drm/tegra "drm/tegra: ".

Cheers,
Mikko


Re: [PATCH v1 5/5] ARM: tegra: add MIPI calibration binding for Tegra20/Tegra30

From: Mikko Perttunen <mperttunen@nvidia.com>
Date: 2025-07-23 01:57:46

On Friday, July 18, 2025 6:26 PM Svyatoslav Ryhel wrote:
пт, 18 лип. 2025 р. о 12:22 Mikko Perttunen [off-list ref] пише:
quoted
On Friday, July 18, 2025 6:15 PM Svyatoslav Ryhel wrote:
quoted
пт, 18 лип. 2025 р. о 12:01 Mikko Perttunen [off-list ref] 
пише:
quoted
quoted
quoted
On Thursday, July 17, 2025 11:21 PM Svyatoslav Ryhel wrote:
quoted
Add MIPI calibration device node for Tegra20 and Tegra30.

Signed-off-by: Svyatoslav Ryhel <redacted>
---

 arch/arm/boot/dts/nvidia/tegra20.dtsi | 14 ++++++++++++++
 arch/arm/boot/dts/nvidia/tegra30.dtsi | 18 ++++++++++++++++++
 2 files changed, 32 insertions(+)
diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi
b/arch/arm/boot/dts/nvidia/tegra20.dtsi index
92d422f83ea4..521261045cc8
100644
--- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
@@ -74,6 +74,16 @@ vi@54080000 {

                      status = "disabled";
              
              };

+             /* DSI MIPI calibration logic is a part of VI/CSI */
+             mipi: mipi@54080220 {
+                     compatible = "nvidia,tegra20-mipi";
+                     reg = <0x54080220 0x100>;
+                     clocks = <&tegra_car TEGRA20_CLK_VI>,
+                              <&tegra_car TEGRA20_CLK_CSI>;
+                     clock-names = "vi", "csi";
+                     #nvidia,mipi-calibrate-cells = <1>;
+             };
+
As you say in the comment, MIPI calibration on Tegra20/30 is part of
VI/CSI. We can't add a "mipi" device here since such a device doesn't
exist in the hardware hierarchy. We already have the VI device in the
device tree, so we need to use that.
I understand your point, but embedding MIPI calibration logic into
VI/CSI driver will bring up another lever of unnecessary complexity
and excessive coding. While approach I have proposed preserves
separation between CSI and DSI and reuses already existing MIPI
calibration framework.
We can consider different driver architectures to simplify things, but the
device tree has to conform to hardware. The host1x bus has no 'mipi'
device on it so we can't put one in the device tree.
I assume then placing mipi node as CSI or VI child would resolve your
concern?
The device tree is not intended to follow software architecture. Having a 
separate device node implies some sort of bus / parent-child hierarchy in 
hardware. So it seems a little difficult to justify.

In this case, it seems to me that it would be pretty easy to add/partially 
copy a small VI driver while integrating with the staging driver, based on how 
simple its probe function is. And given that you're planning on adding CSI 
support as well, utilizing the tegra-video driver seems like it's in the cards 
anyway.

Thanks,
Mikko
quoted
quoted
quoted
A driver for tegra20-vi already exists in
staging/drivers/media/tegra-video. We should aim not to break it.
Perhaps
bring it out of staging? (At least partially, but then why not the
whole
thing.)
It does not break VI/CSI, I have a WIP CSI implementation for
Tegra20/Tegra30 which I hope to submit soon.
We have to use the tegra20-vi node as that matches hardware, and each node
can only be probed to one device, hence the issue.

Great to see a CSI driver!

Mikko
quoted
quoted
Thanks,
Mikko


Re: [PATCH v1 3/5] gpu/drm: host1x: mipi: add Tegra20/Tegra30 MIPI calibration logic

From: Dmitry Osipenko <digetx@gmail.com>
Date: 2025-08-16 14:37:03

17.07.2025 17:21, Svyatoslav Ryhel пишет:
quoted hunk
@@ -525,6 +599,14 @@ static int tegra_mipi_probe(struct platform_device *pdev)
 		return PTR_ERR(mipi->clk);
 	}
 
+	if (mipi->soc->dsi_v0) {
+		mipi->csi_clk = devm_clk_get_prepared(&pdev->dev, "csi");
+		if (IS_ERR(mipi->csi_clk)) {
Doesn't look like the clock needs to be prepared. Normally, you would
need to have clock prepared if clock is enabled/disabled from a context
that can't sleep, like under spinlock or in IRQ handler. AFAICT, this
not the case here.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help