video: tegra20: dsi: add T114 support

Existing Tegra DSI driver mostly fits T114 apart MIPI calibration
which on T114 has dedicated driver. To resolve this MIPI calibration
logic was split for pre-T114 and T114+ devices.

Tested-by: Ion Agorria <ion@agorria.com> # HTC One X
Tested-by: Svyatoslav Ryhel <clamor95@gmail.com> # Nvidia Tegratab T114
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Svyatoslav Ryhel 2024-01-23 19:16:29 +02:00 committed by Anatolij Gustschin
parent c68d08be49
commit f1b1f5e61d
2 changed files with 96 additions and 6 deletions

View file

@ -20,17 +20,24 @@
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch-tegra30/dsi.h>
#include "tegra-dc.h"
#include "tegra-dsi.h"
#include "mipi-phy.h"
/* List of supported DSI bridges */
enum {
DSI_V0,
DSI_V1,
};
struct tegra_dsi_priv {
struct mipi_dsi_host host;
struct mipi_dsi_device device;
struct mipi_dphy_timing dphy_timing;
struct udevice *panel;
struct udevice *mipi;
struct display_timing timing;
struct dsi_ctlr *dsi;
@ -41,6 +48,8 @@ struct tegra_dsi_priv {
int dsi_clk;
int video_fifo_depth;
int host_fifo_depth;
u32 version;
};
static void tegra_dc_enable_controller(struct udevice *dev)
@ -501,6 +510,41 @@ static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad)
writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2));
}
static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv)
{
struct dsi_pad_ctrl_reg *pad = &priv->dsi->pad;
u32 value;
int ret;
ret = misc_set_enabled(priv->mipi, true);
if (ret)
log_debug("%s: failed to enable MIPI calibration: %d\n",
__func__, ret);
writel(0, &pad->pad_ctrl);
writel(0, &pad->pad_ctrl_1);
writel(0, &pad->pad_ctrl_2);
writel(0, &pad->pad_ctrl_3);
writel(0, &pad->pad_ctrl_4);
/* DSI pad enable */
value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
writel(value, &pad->pad_ctrl);
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);
writel(value, &pad->pad_ctrl_2);
value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
writel(value, &pad->pad_ctrl_3);
ret = misc_write(priv->mipi, 0, NULL, 0);
if (ret)
log_debug("%s: MIPI calibration failed %d\n", __func__, ret);
}
static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout,
unsigned long bclk,
unsigned int vrefresh)
@ -664,10 +708,25 @@ static int tegra_dsi_encoder_enable(struct udevice *dev)
u32 value;
int ret;
/* If for some reasone DSI is enabled then it needs to
* be disabled in order for the panel initialization
* commands to be properly sent.
*/
value = readl(&misc->dsi_pwr_ctrl);
if (value & DSI_POWER_CONTROL_ENABLE) {
value = readl(&misc->dsi_pwr_ctrl);
value &= ~DSI_POWER_CONTROL_ENABLE;
writel(value, &misc->dsi_pwr_ctrl);
}
/* Disable interrupt */
writel(0, &misc->int_enable);
tegra_dsi_pad_calibrate(&priv->dsi->pad);
if (priv->version)
tegra_dsi_mipi_calibrate(priv);
else
tegra_dsi_pad_calibrate(&priv->dsi->pad);
tegra_dsi_get_muldiv(device->format, &mul, &div);
@ -806,6 +865,8 @@ static int tegra_dsi_bridge_probe(struct udevice *dev)
struct mipi_dsi_panel_plat *mipi_plat;
int ret;
priv->version = dev_get_driver_data(dev);
priv->dsi = (struct dsi_ctlr *)dev_read_addr_ptr(dev);
if (!priv->dsi) {
printf("%s: No display controller address\n", __func__);
@ -828,6 +889,16 @@ static int tegra_dsi_bridge_probe(struct udevice *dev)
return log_ret(ret);
}
if (priv->version) {
ret = uclass_get_device_by_phandle(UCLASS_MISC, dev,
"nvidia,mipi-calibrate",
&priv->mipi);
if (ret) {
log_debug("%s: cannot get MIPI: error %d\n", __func__, ret);
return ret;
}
}
panel_get_display_timing(priv->panel, &priv->timing);
mipi_plat = dev_get_plat(priv->panel);
@ -859,7 +930,8 @@ static const struct panel_ops tegra_dsi_bridge_ops = {
};
static const struct udevice_id tegra_dsi_bridge_ids[] = {
{ .compatible = "nvidia,tegra30-dsi" },
{ .compatible = "nvidia,tegra30-dsi", .data = DSI_V0 },
{ .compatible = "nvidia,tegra114-dsi", .data = DSI_V1 },
{ }
};

View file

@ -4,8 +4,8 @@
* NVIDIA Corporation <www.nvidia.com>
*/
#ifndef __ASM_ARCH_TEGRA_DSI_H
#define __ASM_ARCH_TEGRA_DSI_H
#ifndef _TEGRA_DSI_H
#define _TEGRA_DSI_H
#ifndef __ASSEMBLY__
#include <linux/bitops.h>
@ -105,6 +105,10 @@ struct dsi_pad_ctrl_reg {
uint pad_ctrl_cd; /* _PAD_CONTROL_CD_0 */
uint pad_cd_status; /* _PAD_CD_STATUS_0 */
uint dsi_vid_mode_control; /* _DSI_VID_MODE_CONTROL_0 */
uint pad_ctrl_1; /* _PAD_CONTROL_1 */
uint pad_ctrl_2; /* _PAD_CONTROL_2 */
uint pad_ctrl_3; /* _PAD_CONTROL_3 */
uint pad_ctrl_4; /* _PAD_CONTROL_4 */
};
/* Display Serial Interface (DSI_) regs */
@ -184,6 +188,20 @@ struct dsi_ctlr {
#define DSI_PAD_CONTROL_PAD_LPUPADJ(x) (((x) & 0x3) << 14)
#define DSI_PAD_CONTROL_PAD_LPDNADJ(x) (((x) & 0x3) << 12)
#define DSI_PAD_CONTROL_VS1_PDIO(x) (((x) & 0xf) << 0)
#define DSI_PAD_CONTROL_VS1_PULLDN(x) (((x) & 0xf) << 16)
#define DSI_PAD_OUT_CLK(x) (((x) & 0x7) << 0)
#define DSI_PAD_LP_DN(x) (((x) & 0x7) << 4)
#define DSI_PAD_LP_UP(x) (((x) & 0x7) << 8)
#define DSI_PAD_SLEW_DN(x) (((x) & 0x7) << 12)
#define DSI_PAD_SLEW_UP(x) (((x) & 0x7) << 16)
#define DSI_PAD_PREEMP_PD_CLK(x) (((x) & 0x3) << 12)
#define DSI_PAD_PREEMP_PU_CLK(x) (((x) & 0x3) << 8)
#define DSI_PAD_PREEMP_PD(x) (((x) & 0x3) << 4)
#define DSI_PAD_PREEMP_PU(x) (((x) & 0x3) << 0)
/*
* pixel format as used in the DSI_CONTROL_FORMAT field
*/
@ -214,4 +232,4 @@ enum tegra_dsi_format {
#define PAD_DRIV_DN_REF(x) (((x) & 0x7) << 16)
#define PAD_DRIV_UP_REF(x) (((x) & 0x7) << 8)
#endif /* __ASM_ARCH_TEGRA_DSI_H */
#endif /* _TEGRA_DSI_H */