tegra-drm: add t210b01 dsi support

This commit is contained in:
2025-08-03 23:27:17 -05:00
parent 0cfaac1068
commit ce2360d366
3 changed files with 157 additions and 37 deletions

View File

@@ -1378,6 +1378,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra132-dsi", }, { .compatible = "nvidia,tegra132-dsi", },
{ .compatible = "nvidia,tegra210-dc", }, { .compatible = "nvidia,tegra210-dc", },
{ .compatible = "nvidia,tegra210-dsi", }, { .compatible = "nvidia,tegra210-dsi", },
{ .compatible = "nvidia,tegra210b01-dsi", },
{ .compatible = "nvidia,tegra210-sor", }, { .compatible = "nvidia,tegra210-sor", },
{ .compatible = "nvidia,tegra210-sor1", }, { .compatible = "nvidia,tegra210-sor1", },
{ .compatible = "nvidia,tegra210-vic", }, { .compatible = "nvidia,tegra210-vic", },

View File

@@ -52,6 +52,21 @@ to_dsi_state(struct drm_connector_state *state)
return container_of(state, struct tegra_dsi_state, base); 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 tegra_dsi {
struct host1x_client client; struct host1x_client client;
struct tegra_output output; struct tegra_output output;
@@ -81,6 +96,8 @@ struct tegra_dsi {
/* for ganged-mode support */ /* for ganged-mode support */
struct tegra_dsi *master; struct tegra_dsi *master;
struct tegra_dsi *slave; struct tegra_dsi *slave;
const struct dsi_regmap *regmap;
}; };
static inline struct tegra_dsi * 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 } #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),
DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL), DEBUGFS_REG32(DSI_INCR_SYNCPT_CONTROL),
DEBUGFS_REG32(DSI_INCR_SYNCPT_ERROR), 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_2),
DEBUGFS_REG32(DSI_PAD_CONTROL_3), DEBUGFS_REG32(DSI_PAD_CONTROL_3),
DEBUGFS_REG32(DSI_PAD_CONTROL_4), 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) 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; goto unlock;
} }
for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs); i++) { for (i = 0; i < ARRAY_SIZE(tegra_dsi_regs_common); i++) {
unsigned int offset = tegra_dsi_regs[i].offset; 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)); 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; u32 value;
tegra_dsi_writel(dsi, start, DSI_GANGED_MODE_START); tegra_dsi_writel(dsi, start, dsi->regmap->ganged_mode_start);
tegra_dsi_writel(dsi, size << 16 | size, DSI_GANGED_MODE_SIZE); tegra_dsi_writel(dsi, size << 16 | size, dsi->regmap->ganged_mode_size);
value = DSI_GANGED_MODE_CONTROL_ENABLE; 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) 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) 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->regmap->ganged_mode_start);
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_SIZE); tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_size);
tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); tegra_dsi_writel(dsi, 0, dsi->regmap->ganged_mode_control);
} }
static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) 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) static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
{ {
u32 value; u32 value;
int err; int err, i;
/* /*
* XXX Is this still needed? The module reset is deasserted right * 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_0);
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); for (i = 0; i < ARRAY_SIZE(dsi->regmap->slew_impedance); i++) {
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); if (dsi->regmap->slew_impedance[i])
tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); tegra_dsi_writel(dsi, 0, dsi->regmap->slew_impedance[i]);
}
/* start calibration */ /* start calibration */
tegra_dsi_pad_enable(dsi); tegra_dsi_pad_enable(dsi);
value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | /* do not set padctl 2 slew by default */
DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | if (of_property_read_bool(dsi->dev->of_node, "nvidia,slew-enable")) {
DSI_PAD_OUT_CLK(0x0); value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); 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); 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); err = tegra_mipi_start_calibration(dsi->mipi);
if (err < 0) if (err < 0)
@@ -1643,6 +1662,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
goto remove; 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); dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
if (IS_ERR(dsi->mipi)) { if (IS_ERR(dsi->mipi)) {
err = PTR_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); 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[] = { static const struct of_device_id tegra_dsi_of_match[] = {
{ .compatible = "nvidia,tegra210-dsi", }, {
{ .compatible = "nvidia,tegra132-dsi", }, .compatible = "nvidia,tegra210b01-dsi",
{ .compatible = "nvidia,tegra124-dsi", }, .data = &tegra_dsi_regmap_b01
{ .compatible = "nvidia,tegra114-dsi", }, },
{
.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); MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);

View File

@@ -130,6 +130,24 @@
#define DSI_INIT_SEQ_DATA_14 0x5e #define DSI_INIT_SEQ_DATA_14 0x5e
#define DSI_INIT_SEQ_DATA_15 0x5f #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 * pixel format as used in the DSI_CONTROL_FORMAT field
*/ */