#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;
int dsi_clk;
int video_fifo_depth;
int host_fifo_depth;
+
+ u32 version;
};
static void tegra_dc_enable_controller(struct udevice *dev)
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)
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);
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__);
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);
};
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 },
{ }
};
* 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>
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 */
#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
*/
#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 */