From 7f1e672cff76f981bcab1a252a8df2c7e3082f01 Mon Sep 17 00:00:00 2001 From: Thomas Makin Date: Sun, 3 Aug 2025 23:27:17 -0500 Subject: [PATCH] tegra-drm: add t210b01 dsi support Signed-off-by: Thomas Makin --- drivers/gpu/drm/tegra/drm.c | 1 + drivers/gpu/drm/tegra/dsi.c | 175 ++++++++++++++++++++++++++++-------- drivers/gpu/drm/tegra/dsi.h | 18 ++++ 3 files changed, 157 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index f62b2b05f8d0..a9d7b003f886 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1378,6 +1378,7 @@ static const struct of_device_id host1x_drm_subdevs[] = { { .compatible = "nvidia,tegra132-dsi", }, { .compatible = "nvidia,tegra210-dc", }, { .compatible = "nvidia,tegra210-dsi", }, + { .compatible = "nvidia,tegra210b01-dsi", }, { .compatible = "nvidia,tegra210-sor", }, { .compatible = "nvidia,tegra210-sor1", }, { .compatible = "nvidia,tegra210-vic", }, diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index db606e151afc..b553c8fa5046 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -52,6 +52,21 @@ to_dsi_state(struct drm_connector_state *state) return container_of(state, struct tegra_dsi_state, base); } +/* + * remap of registers revised in Tegra210B01 + */ +struct dsi_regmap { + int init_seq_data_15; + int slew_impedance[4]; + int preemphasis; + int bias; + int ganged_mode_control; + int ganged_mode_start; + int ganged_mode_size; + int dbg_regs_cnt; + struct debugfs_reg32 dbg_regs_ext[16]; +}; + struct tegra_dsi { struct host1x_client client; struct tegra_output output; @@ -81,6 +96,8 @@ struct tegra_dsi { /* for ganged-mode support */ struct tegra_dsi *master; struct tegra_dsi *slave; + + const struct dsi_regmap *regmap; }; static inline struct tegra_dsi * @@ -122,7 +139,7 @@ static inline void tegra_dsi_writel(struct tegra_dsi *dsi, u32 value, #define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name } -static const struct debugfs_reg32 tegra_dsi_regs[] = { +static const struct debugfs_reg32 tegra_dsi_regs_common[] = { DEBUGFS_REG32(DSI_INCR_SYNCPT), DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL), DEBUGFS_REG32(DSI_INCR_SYNCPT_ERROR), @@ -181,19 +198,6 @@ static const struct debugfs_reg32 tegra_dsi_regs[] = { DEBUGFS_REG32(DSI_PAD_CONTROL_2), DEBUGFS_REG32(DSI_PAD_CONTROL_3), DEBUGFS_REG32(DSI_PAD_CONTROL_4), - DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL), - DEBUGFS_REG32(DSI_GANGED_MODE_START), - DEBUGFS_REG32(DSI_GANGED_MODE_SIZE), - DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT), - DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14), - DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15), }; static int tegra_dsi_show_regs(struct seq_file *s, void *data) @@ -212,10 +216,17 @@ static int tegra_dsi_show_regs(struct seq_file *s, void *data) goto unlock; } - for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs); i++) { - unsigned int offset = tegra_dsi_regs[i].offset; + for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs_common); i++) { + unsigned int offset = tegra_dsi_regs_common[i].offset; - seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs[i].name, + seq_printf(s, "%-32s %#05x %08x\n", tegra_dsi_regs_common[i].name, + offset, tegra_dsi_readl(dsi, offset)); + } + + for (i = 0; i < dsi->regmap->dbg_regs_cnt; i++) { + unsigned int offset = dsi->regmap->dbg_regs_ext[i].offset; + + seq_printf(s, "%-32s %#05x %08x\n", dsi->regmap->dbg_regs_ext[i].name, offset, tegra_dsi_readl(dsi, offset)); } @@ -446,11 +457,11 @@ static void tegra_dsi_ganged_enable(struct tegra_dsi *dsi, unsigned int start, { u32 value; - tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START); - tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE); + tegra_dsi_writel(dsi, start, dsi->regmap->ganged_mode_start); + tegra_dsi_writel(dsi, size << 16 | size, dsi->regmap->ganged_mode_size); value = DSI_GANGED_MODE_CONTROL_ENABLE; - tegra_dsi_writel(dsi, value, DSI_GANGED_MODE_CONTROL); + tegra_dsi_writel(dsi, value, dsi->regmap->ganged_mode_control); } static void tegra_dsi_enable(struct tegra_dsi *dsi) @@ -653,9 +664,9 @@ static void tegra_dsi_video_disable(struct tegra_dsi *dsi) static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi) { - tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_START); - tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE); - tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); + tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_start); + tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_size); + tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_control); } static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) @@ -671,7 +682,7 @@ static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) { u32 value; - int err; + int err, i; /* * XXX Is this still needed? The module reset is deasserted right @@ -679,21 +690,29 @@ static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) */ 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); + for (i = 0; i < ARRAY_SIZE(dsi->regmap->slew_impedance); i++) { + if (dsi->regmap->slew_impedance[i]) + tegra_dsi_writel(dsi, 0, dsi->regmap->slew_impedance[i]); + } /* 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); + /* do not set padctl 2 slew by default */ + if (of_property_read_bool(dsi->dev->of_node, "nvidia,slew-enable")) { + 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) | + value = tegra_dsi_readl(dsi, dsi->regmap->preemphasis); + + 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); + tegra_dsi_writel(dsi, value, dsi->regmap->preemphasis); + + tegra_dsi_writel(dsi, 0, dsi->regmap->bias); err = tegra_mipi_start_calibration(dsi->mipi); if (err < 0) @@ -1643,6 +1662,12 @@ static int tegra_dsi_probe(struct platform_device *pdev) goto remove; } + dsi->regmap = of_device_get_match_data(&pdev->dev); + if (IS_ERR(dsi->regmap)) { + err = PTR_ERR(dsi->regmap); + goto remove; + } + dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node); if (IS_ERR(dsi->mipi)) { err = PTR_ERR(dsi->mipi); @@ -1698,11 +1723,87 @@ static void tegra_dsi_remove(struct platform_device *pdev) tegra_mipi_free(dsi->mipi); } +static const struct dsi_regmap tegra_dsi_regmap = { + .init_seq_data_15 = DSI_INIT_SEQ_DATA_15, + .slew_impedance = { DSI_PAD_CONTROL_2 }, + .preemphasis = DSI_PAD_CONTROL_3, + .bias = DSI_PAD_CONTROL_4, + .ganged_mode_control = DSI_GANGED_MODE_CONTROL, + .ganged_mode_start = DSI_GANGED_MODE_START, + .ganged_mode_size = DSI_GANGED_MODE_SIZE, + .dbg_regs_cnt = 13, + .dbg_regs_ext = { + DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL), + DEBUGFS_REG32(DSI_GANGED_MODE_START), + DEBUGFS_REG32(DSI_GANGED_MODE_SIZE), + DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT), + DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15), + }, +}; + +static const struct dsi_regmap tegra_dsi_regmap_b01 = { + .init_seq_data_15 = DSI_INIT_SEQ_DATA_15_B01, + .slew_impedance = { + DSI_PAD_CONTROL_2, + DSI_PAD_CONTROL_3, + DSI_PAD_CONTROL_4, + DSI_PAD_CONTROL_5_B01, + }, + .preemphasis = DSI_PAD_CONTROL_6_B01, + .bias = DSI_PAD_CONTROL_7_B01, + .ganged_mode_control = DSI_GANGED_MODE_CONTROL_B01, + .ganged_mode_start = DSI_GANGED_MODE_START_B01, + .ganged_mode_size = DSI_GANGED_MODE_SIZE_B01, + .dbg_regs_cnt = 16, + .dbg_regs_ext = { + DEBUGFS_REG32(DSI_PAD_CONTROL_5_B01), + DEBUGFS_REG32(DSI_PAD_CONTROL_6_B01), + DEBUGFS_REG32(DSI_PAD_CONTROL_7_B01), + DEBUGFS_REG32(DSI_GANGED_MODE_CONTROL_B01), + DEBUGFS_REG32(DSI_GANGED_MODE_START_B01), + DEBUGFS_REG32(DSI_GANGED_MODE_SIZE_B01), + DEBUGFS_REG32(DSI_RAW_DATA_BYTE_COUNT_B01), + DEBUGFS_REG32(DSI_ULTRA_LOW_POWER_CONTROL_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_8_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_9_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_10_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_11_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_12_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_13_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_14_B01), + DEBUGFS_REG32(DSI_INIT_SEQ_DATA_15_B01), + }, +}; + static const struct of_device_id tegra_dsi_of_match[] = { - { .compatible = "nvidia,tegra210-dsi", }, - { .compatible = "nvidia,tegra132-dsi", }, - { .compatible = "nvidia,tegra124-dsi", }, - { .compatible = "nvidia,tegra114-dsi", }, + { + .compatible = "nvidia,tegra210b01-dsi", + .data = &tegra_dsi_regmap_b01 + }, + { + .compatible = "nvidia,tegra210-dsi", + .data = &tegra_dsi_regmap + }, + { + .compatible = "nvidia,tegra132-dsi", + .data = &tegra_dsi_regmap + }, + { + .compatible = "nvidia,tegra124-dsi", + .data = &tegra_dsi_regmap + }, + { + .compatible = "nvidia,tegra114-dsi", + .data = &tegra_dsi_regmap + }, { }, }; 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..218be926c602 100644 --- a/drivers/gpu/drm/tegra/dsi.h +++ b/drivers/gpu/drm/tegra/dsi.h @@ -130,6 +130,24 @@ #define DSI_INIT_SEQ_DATA_14 0x5e #define DSI_INIT_SEQ_DATA_15 0x5f +// Tegra210B01 has a revised set of regs +#define DSI_PAD_CONTROL_5_B01 0x53 +#define DSI_PAD_CONTROL_6_B01 0x54 +#define DSI_PAD_CONTROL_7_B01 0x55 +#define DSI_GANGED_MODE_CONTROL_B01 0x56 +#define DSI_GANGED_MODE_START_B01 0x57 +#define DSI_GANGED_MODE_SIZE_B01 0x58 +#define DSI_RAW_DATA_BYTE_COUNT_B01 0x59 +#define DSI_ULTRA_LOW_POWER_CONTROL_B01 0x5a +#define DSI_INIT_SEQ_DATA_8_B01 0x5b +#define DSI_INIT_SEQ_DATA_9_B01 0x5c +#define DSI_INIT_SEQ_DATA_10_B01 0x5d +#define DSI_INIT_SEQ_DATA_11_B01 0x5e +#define DSI_INIT_SEQ_DATA_12_B01 0x5f +#define DSI_INIT_SEQ_DATA_13_B01 0x60 +#define DSI_INIT_SEQ_DATA_14_B01 0x61 +#define DSI_INIT_SEQ_DATA_15_B01 0x62 + /* * pixel format as used in the DSI_CONTROL_FORMAT field */