[PATCH v1 3/7] video: tegra20: mipi: add Tegra K1 support

Svyatoslav Ryhel clamor95 at gmail.com
Mon Dec 23 08:06:34 CET 2024


Re-design MIPI calibration driver to fit T124.

Signed-off-by: Svyatoslav Ryhel <clamor95 at gmail.com>
---
 drivers/video/tegra20/tegra-dsi.c  |  11 ++-
 drivers/video/tegra20/tegra-mipi.c | 134 ++++++++++++++++++++++++++---
 2 files changed, 130 insertions(+), 15 deletions(-)

diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c
index b57df6b82bf..d066ffc8b9d 100644
--- a/drivers/video/tegra20/tegra-dsi.c
+++ b/drivers/video/tegra20/tegra-dsi.c
@@ -53,6 +53,7 @@ struct tegra_dsi_priv {
 	int video_fifo_depth;
 	int host_fifo_depth;
 
+	u32 calibration_pads;
 	u32 version;
 
 	/* for ganged-mode support */
@@ -550,7 +551,7 @@ static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv)
 		DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
 	writel(value, &pad->pad_ctrl_3);
 
-	ret = misc_write(priv->mipi, 0, NULL, 0);
+	ret = misc_write(priv->mipi, priv->calibration_pads, NULL, 0);
 	if (ret)
 		log_debug("%s: MIPI calibration failed %d\n", __func__, ret);
 }
@@ -1033,6 +1034,14 @@ static int tegra_dsi_bridge_probe(struct udevice *dev)
 			log_debug("%s: cannot get MIPI: error %d\n", __func__, ret);
 			return ret;
 		}
+
+		ret = dev_read_u32_index(dev, "nvidia,mipi-calibrate", 1,
+					 &priv->calibration_pads);
+		if (ret) {
+			log_debug("%s: cannot get calibration pads: error %d\n",
+				  __func__, ret);
+			return ret;
+		}
 	}
 
 	panel_get_display_timing(priv->panel, &priv->timing);
diff --git a/drivers/video/tegra20/tegra-mipi.c b/drivers/video/tegra20/tegra-mipi.c
index 2df3c1a9942..a4f4343d008 100644
--- a/drivers/video/tegra20/tegra-mipi.c
+++ b/drivers/video/tegra20/tegra-mipi.c
@@ -10,9 +10,10 @@
 #include <linux/delay.h>
 #include <linux/iopoll.h>
 
+#include <asm/arch/clock.h>
 #include <asm/io.h>
 
-/* MIPI control registers 0x00 ~ 0x60 */
+/* MIPI control registers 0x00 ~ 0x74 */
 struct mipi_ctlr {
 	uint mipi_cal_ctrl;
 	uint mipi_cal_autocal_ctrl;
@@ -38,8 +39,17 @@ struct mipi_ctlr {
 	uint mipi_cal_bias_pad_cfg0;
 	uint mipi_cal_bias_pad_cfg1;
 	uint mipi_cal_bias_pad_cfg2;
+
+	uint mipi_cal_dsia_config_2;
+	uint mipi_cal_dsib_config_2;
+	uint mipi_cal_cilc_config_2;
+	uint mipi_cal_cild_config_2;
+	uint mipi_cal_csie_config_2;
 };
 
+#define MIPI_DSIA_PADS			0x60
+#define MIPI_DSIB_PADS			0x180
+
 #define MIPI_CAL_CTRL_NOISE_FILTER(x)	(((x) & 0xf) << 26)
 #define MIPI_CAL_CTRL_PRESCALE(x)	(((x) & 0x3) << 24)
 #define MIPI_CAL_CTRL_CLKEN_OVR		BIT(4)
@@ -64,26 +74,25 @@ struct mipi_ctlr {
 #define MIPI_CAL_BIAS_PAD_VAUXP(x)	(((x) & 0x7) << 4)
 #define MIPI_CAL_BIAS_PAD_PDVREG	BIT(1)
 
+#define MIPI_CAL_HSCLKPDOSDSI(x)	(((x) & 0x1f) << 8)
+#define MIPI_CAL_HSCLKPUOSDSI(x)	(((x) & 0x1f) << 0)
+
 struct tegra_mipi_priv {
 	struct mipi_ctlr	*mipi;
 	struct clk		*mipi_cal;
+	u32 version;
 };
 
-static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf,
-				int size)
+enum {
+	T114,
+	T124,
+};
+
+static void tegra114_mipi_pads_cal(struct tegra_mipi_priv *priv,
+				   int calibration_pads)
 {
-	struct tegra_mipi_priv *priv = dev_get_priv(dev);
 	u32 value;
 
-	value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) |
-		MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0);
-	writel(value, &priv->mipi->mipi_cal_bias_pad_cfg1);
-
-	value = readl(&priv->mipi->mipi_cal_bias_pad_cfg2);
-	value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
-	value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
-	writel(value, &priv->mipi->mipi_cal_bias_pad_cfg2);
-
 	value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) |
 		MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x4) |
 		MIPI_CAL_TERMOS(0x5);
@@ -99,6 +108,95 @@ static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf
 	value = readl(&priv->mipi->mipi_cal_config_dsid);
 	value &= ~(MIPI_CAL_SEL(0x1));
 	writel(value, &priv->mipi->mipi_cal_config_dsid);
+}
+
+static void tegra124_mipi_pads_cal(struct tegra_mipi_priv *priv,
+				   int calibration_pads)
+{
+	u32 value;
+
+	/* Calibrate DSI-A */
+	if (calibration_pads == MIPI_DSIA_PADS) {
+		printf("Calibrating DSI-A pads\n");
+
+		value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) |
+			MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x0) |
+			MIPI_CAL_TERMOS(0x0);
+		writel(value, &priv->mipi->mipi_cal_config_dsia);
+		writel(value, &priv->mipi->mipi_cal_config_dsib);
+
+		value = MIPI_CAL_SEL(0x1) |
+			MIPI_CAL_HSCLKPDOSDSI(0x1) |
+			MIPI_CAL_HSCLKPUOSDSI(0x2);
+		writel(value, &priv->mipi->mipi_cal_dsia_config_2);
+		writel(value, &priv->mipi->mipi_cal_dsib_config_2);
+
+		/* Deselect PAD C */
+		value = readl(&priv->mipi->mipi_cal_cilc_config_2);
+		value &= ~(MIPI_CAL_SEL(0x1));
+		writel(value, &priv->mipi->mipi_cal_cilc_config_2);
+
+		/* Deselect PAD D */
+		value = readl(&priv->mipi->mipi_cal_cild_config_2);
+		value &= ~(MIPI_CAL_SEL(0x1));
+		writel(value, &priv->mipi->mipi_cal_cild_config_2);
+	}
+
+	/* Calibrate DSI-B */
+	if (calibration_pads == MIPI_DSIB_PADS) {
+		printf("Calibrating DSI-B pads\n");
+
+		value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) |
+			MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x0) |
+			MIPI_CAL_TERMOS(0x0);
+		writel(value, &priv->mipi->mipi_cal_config_csic);
+		writel(value, &priv->mipi->mipi_cal_config_csid);
+
+		value = MIPI_CAL_SEL(0x1) |
+			MIPI_CAL_HSCLKPDOSDSI(0x1) |
+			MIPI_CAL_HSCLKPUOSDSI(0x2);
+		writel(value, &priv->mipi->mipi_cal_cilc_config_2);
+		writel(value, &priv->mipi->mipi_cal_cild_config_2);
+
+		/* Deselect PAD A */
+		value = readl(&priv->mipi->mipi_cal_dsia_config_2);
+		value &= ~(MIPI_CAL_SEL(0x1));
+		writel(value, &priv->mipi->mipi_cal_dsia_config_2);
+
+		/* Deselect PAD B */
+		value = readl(&priv->mipi->mipi_cal_dsib_config_2);
+		value &= ~(MIPI_CAL_SEL(0x1));
+		writel(value, &priv->mipi->mipi_cal_dsib_config_2);
+	}
+}
+
+static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf,
+				int size)
+{
+	struct tegra_mipi_priv *priv = dev_get_priv(dev);
+	u32 value;
+
+	value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) |
+		MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0);
+	writel(value, &priv->mipi->mipi_cal_bias_pad_cfg1);
+
+	value = readl(&priv->mipi->mipi_cal_bias_pad_cfg2);
+	value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
+	value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
+	writel(value, &priv->mipi->mipi_cal_bias_pad_cfg2);
+
+	switch (priv->version) {
+	case T114:
+		tegra114_mipi_pads_cal(priv, offset);
+		break;
+
+	case T124:
+		tegra124_mipi_pads_cal(priv, offset);
+		break;
+
+	default:
+		return -EINVAL;
+	}
 
 	value = readl(&priv->mipi->mipi_cal_ctrl);
 	value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf);
@@ -134,6 +232,11 @@ static int tegra_mipi_enable(struct udevice *dev, bool val)
 	struct tegra_mipi_priv *priv = dev_get_priv(dev);
 	u32 value;
 
+	reset_set_enable(priv->mipi_cal->id, 1);
+	mdelay(100);
+	reset_set_enable(priv->mipi_cal->id, 0);
+	mdelay(1);
+
 	clk_enable(priv->mipi_cal);
 
 	value = readl(&priv->mipi->mipi_cal_bias_pad_cfg0);
@@ -157,6 +260,8 @@ static int tegra_mipi_probe(struct udevice *dev)
 {
 	struct tegra_mipi_priv *priv = dev_get_priv(dev);
 
+	priv->version = dev_get_driver_data(dev);
+
 	priv->mipi = (struct mipi_ctlr *)dev_read_addr_ptr(dev);
 	if (!priv->mipi) {
 		log_debug("%s: no MIPI controller address\n", __func__);
@@ -174,7 +279,8 @@ static int tegra_mipi_probe(struct udevice *dev)
 }
 
 static const struct udevice_id tegra_mipi_ids[] = {
-	{ .compatible = "nvidia,tegra114-mipi" },
+	{ .compatible = "nvidia,tegra114-mipi", .data = T114 },
+	{ .compatible = "nvidia,tegra124-mipi", .data = T124 },
 	{ }
 };
 
-- 
2.43.0



More information about the U-Boot mailing list