mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-16 18:04:48 +00:00
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:
parent
c68d08be49
commit
f1b1f5e61d
2 changed files with 96 additions and 6 deletions
|
@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
Loading…
Add table
Reference in a new issue