tegra-drm: add t210b01 dsi support
Signed-off-by: Thomas Makin <halorocker89@gmail.com>
This commit is contained in:
@@ -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", },
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user