summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Huang <lhuang@nvidia.com>2011-01-27 13:14:44 -0800
committerVarun Colbert <vcolbert@nvidia.com>2011-03-16 09:49:10 -0800
commit1c3b9bd9adf9343a0612ba0bfcd6c7cfef77a999 (patch)
tree72339757afdd1809f25bf2e7cd10f79e492b901b
parent53a0bb517d6e14d8cee3a9ee71405da56e8ce8c9 (diff)
video: tegra: dsi: Added dsi support.
Bug 793366 Bug 794499 Change-Id: Id49d86dd7760b75ef4947f5bdab9e37f0333391d Reviewed-on: http://git-master/r/#change,18950 Reviewed-on: http://git-master/r/22508 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/include/mach/dc.h123
-rw-r--r--arch/arm/mach-tegra/include/mach/iomap.h3
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c19
-rw-r--r--drivers/video/tegra/Kconfig7
-rw-r--r--drivers/video/tegra/dc/Makefile1
-rw-r--r--drivers/video/tegra/dc/dc.c21
-rw-r--r--drivers/video/tegra/dc/dc_priv.h1
-rw-r--r--drivers/video/tegra/dc/dc_reg.h13
-rw-r--r--drivers/video/tegra/dc/dsi.c1468
-rw-r--r--drivers/video/tegra/dc/dsi.h272
-rw-r--r--drivers/video/tegra/dc/dsi_regs.h336
11 files changed, 2262 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h
index d6c8d2494296..8d43c3814925 100644
--- a/arch/arm/mach-tegra/include/mach/dc.h
+++ b/arch/arm/mach-tegra/include/mach/dc.h
@@ -25,6 +25,126 @@
#define TEGRA_MAX_DC 2
#define DC_N_WINDOWS 3
+
+/* DSI pixel data format */
+enum {
+ TEGRA_DSI_PIXEL_FORMAT_16BIT_P,
+ TEGRA_DSI_PIXEL_FORMAT_18BIT_P,
+ TEGRA_DSI_PIXEL_FORMAT_18BIT_NP,
+ TEGRA_DSI_PIXEL_FORMAT_24BIT_P,
+};
+
+/* DSI virtual channel number */
+enum {
+ TEGRA_DSI_VIRTUAL_CHANNEL_0,
+ TEGRA_DSI_VIRTUAL_CHANNEL_1,
+ TEGRA_DSI_VIRTUAL_CHANNEL_2,
+ TEGRA_DSI_VIRTUAL_CHANNEL_3,
+};
+
+/* DSI transmit method for video data */
+enum {
+ TEGRA_DSI_VIDEO_TYPE_VIDEO_MODE,
+ TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE,
+};
+
+/* DSI HS clock mode */
+enum {
+ TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS,
+ TEGRA_DSI_VIDEO_CLOCK_TX_ONLY,
+};
+
+/* DSI burst mode setting in video mode */
+enum {
+ TEGRA_DSI_VIDEO_NONE_BURST_MODE,
+ TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END,
+ TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED,
+ TEGRA_DSI_VIDEO_BURST_MODE_LOW_SPEED,
+ TEGRA_DSI_VIDEO_BURST_MODE_MEDIUM_SPEED,
+ TEGRA_DSI_VIDEO_BURST_MODE_FAST_SPEED,
+ TEGRA_DSI_VIDEO_BURST_MODE_FASTEST_SPEED,
+ TEGRA_DSI_VIDEO_BURST_MODE_MANUAL,
+};
+
+enum {
+ TEGRA_DSI_PACKET_CMD,
+ TEGRA_DSI_DELAY_MS,
+};
+
+struct tegra_dsi_cmd {
+ u8 cmd_type;
+ u8 data_id;
+ union {
+ u16 data_len;
+ u16 delay_ms;
+ struct{
+ u8 data0;
+ u8 data1;
+ }sp;
+ }sp_len_dly;
+ u8 *pdata;
+};
+
+#define DSI_CMD_SHORT(di, p0, p1) { \
+ .cmd_type = TEGRA_DSI_PACKET_CMD, \
+ .data_id = di, \
+ .sp_len_dly.sp.data0 = p0, \
+ .sp_len_dly.sp.data1 = p1, \
+ }
+#define DSI_DLY_MS(ms) { \
+ .cmd_type = TEGRA_DSI_DELAY_MS, \
+ .sp_len_dly.delay_ms = ms, \
+ }
+
+#define DSI_CMD_LONG(di, ptr) { \
+ .cmd_type = TEGRA_DSI_PACKET_CMD, \
+ .data_id = di, \
+ .sp_len_dly.data_len = ARRAY_SIZE(ptr), \
+ .pdata = ptr, \
+ }
+
+struct dsi_phy_timing_ns {
+ u16 t_hsdexit_ns;
+ u16 t_hstrail_ns;
+ u16 t_hsprepr_ns;
+ u16 t_datzero_ns;
+
+ u16 t_clktrail_ns;
+ u16 t_clkpost_ns;
+ u16 t_clkzero_ns;
+ u16 t_tlpx_ns;
+};
+
+struct tegra_dsi_out {
+ u8 n_data_lanes; /* required*/
+ u8 pixel_format; /* required*/
+ u8 refresh_rate; /* required*/
+ u8 virtual_channel; /* required*/
+
+ bool panel_has_frame_buffer; /* required*/
+
+ struct tegra_dsi_cmd* dsi_init_cmd; /* required*/
+ u16 n_init_cmd; /* required*/
+
+ u8 video_data_type; /* required*/
+ u8 video_clock_mode;
+ u8 video_burst_mode;
+
+ u16 panel_buffer_size_byte;
+ u16 panel_reset_timeout_msec;
+
+ bool hs_cmd_mode_supported;
+ bool hs_cmd_mode_on_blank_supported;
+ bool enable_hs_clock_on_lp_cmd_mode;
+
+ u32 max_panel_freq_khz;
+ u32 lp_cmd_mode_freq_khz;
+ u32 hs_clk_in_lp_cmd_mode_freq_khz;
+ u32 burst_mode_freq_khz;
+
+ struct dsi_phy_timing_ns phy_timing;
+};
+
struct tegra_dc_mode {
int pclk;
int h_ref_to_sync;
@@ -47,6 +167,7 @@ struct tegra_dc_mode {
enum {
TEGRA_DC_OUT_RGB,
TEGRA_DC_OUT_HDMI,
+ TEGRA_DC_OUT_DSI,
};
struct tegra_dc_out_pin {
@@ -111,6 +232,8 @@ struct tegra_dc_out {
struct tegra_dc_mode *modes;
int n_modes;
+ struct tegra_dsi_out *dsi;
+
struct tegra_dc_out_pin *out_pins;
unsigned n_out_pins;
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
index e77176e7c87e..0f86c746dfdc 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -56,6 +56,9 @@
#define TEGRA_HDMI_BASE 0x54280000
#define TEGRA_HDMI_SIZE SZ_256K
+#define TEGRA_DSI_BASE 0x54300000
+#define TEGRA_DSI_SIZE SZ_256K
+
#define TEGRA_GART_BASE 0x58000000
#define TEGRA_GART_SIZE SZ_32M
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 27bd8ba95d29..6a4cd99f88bf 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -627,6 +627,12 @@ static int tegra2_pll_clk_enable(struct clk *c)
val |= PLL_BASE_ENABLE;
clk_writel(val, c->reg + PLL_BASE);
+ if (c->flags & PLLD) {
+ val = clk_readl(c->reg + PLL_MISC(c) + PLL_BASE);
+ val |= PLLD_MISC_CLKENABLE;
+ clk_writel(val, c->reg + PLL_MISC(c) + PLL_BASE);
+ }
+
tegra2_pll_clk_wait_for_lock(c);
return 0;
@@ -640,6 +646,12 @@ static void tegra2_pll_clk_disable(struct clk *c)
val = clk_readl(c->reg);
val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
clk_writel(val, c->reg);
+
+ if (c->flags & PLLD) {
+ val = clk_readl(c->reg + PLL_MISC(c) + PLL_BASE);
+ val &= ~PLLD_MISC_CLKENABLE;
+ clk_writel(val, c->reg + PLL_MISC(c) + PLL_BASE);
+ }
}
static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
@@ -1496,6 +1508,11 @@ static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
{ 19200000, 216000000, 135, 12, 1, 3},
{ 26000000, 216000000, 216, 26, 1, 4},
+ { 12000000, 5000000, 10, 24, 1, 4},
+ { 12000000, 10000000, 10, 12, 1, 4},
+ { 12000000, 161500000, 323, 24, 1, 4},
+ { 12000000, 162000000, 162, 12, 1, 4},
+
{ 12000000, 594000000, 594, 12, 1, 8},
{ 13000000, 594000000, 594, 13, 1, 8},
{ 19200000, 594000000, 495, 16, 1, 8},
@@ -2057,6 +2074,8 @@ struct clk_duplicate tegra_clk_duplicates[] = {
CLK_DUPLICATE("usbd", "tegra-otg", NULL),
CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
+ CLK_DUPLICATE("dsi", "tegradc.0", "dsi"),
+ CLK_DUPLICATE("dsi", "tegradc.1", "dsi"),
CLK_DUPLICATE("pwm", "tegra_pwm.0", NULL),
CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL),
CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL),
diff --git a/drivers/video/tegra/Kconfig b/drivers/video/tegra/Kconfig
index a4b74299c76f..dd2ac9dc67c0 100644
--- a/drivers/video/tegra/Kconfig
+++ b/drivers/video/tegra/Kconfig
@@ -101,8 +101,13 @@ config TEGRA_ENABLE_SUPPORT_FOR_1080p_30HZ
bool "Enable support for 1080p @ 30Hz"
default n
help
- Say Y here to Enable 1080p@30Hz instead of 1080p@60Hz
+ Say Y here to Enable 1080p@30Hz instead of 1080p@60Hz
If unsure, say N.
+config TEGRA_DSI
+ bool "Enable DSI panel."
+ default n
+ help
+ Say Y here to enable the DSI panel.
endif
diff --git a/drivers/video/tegra/dc/Makefile b/drivers/video/tegra/dc/Makefile
index 8ab906465976..db675fd82e76 100644
--- a/drivers/video/tegra/dc/Makefile
+++ b/drivers/video/tegra/dc/Makefile
@@ -3,4 +3,5 @@ obj-y += rgb.o
obj-y += hdmi.o
obj-y += nvhdcp.o
obj-y += edid.o
+obj-$(CONFIG_TEGRA_DSI) += dsi.o
obj-$(CONFIG_TEGRA_OVERLAY) += overlay.o
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index 085ab037fc9e..68681aefce12 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -725,6 +725,21 @@ void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk)
clk_set_parent(clk, pll_d_out0_clk);
}
+ if (dc->out->type == TEGRA_DC_OUT_DSI) {
+ unsigned long rate;
+ struct clk *pll_d_out0_clk =
+ clk_get_sys(NULL, "pll_d_out0");
+ struct clk *pll_d_clk =
+ clk_get_sys(NULL, "pll_d");
+
+ rate = dc->mode.pclk;
+ if (rate != clk_get_rate(pll_d_clk))
+ clk_set_rate(pll_d_clk, rate);
+
+ if (clk_get_parent(clk) != pll_d_out0_clk)
+ clk_set_parent(clk, pll_d_out0_clk);
+ }
+
pclk = tegra_dc_pclk_round_rate(dc, dc->mode.pclk);
tegra_dvfs_set_rate(clk, pclk);
}
@@ -920,7 +935,11 @@ static void tegra_dc_set_out(struct tegra_dc *dc, struct tegra_dc_out *out)
case TEGRA_DC_OUT_HDMI:
dc->out_ops = &tegra_dc_hdmi_ops;
break;
-
+#ifdef CONFIG_TEGRA_DSI
+ case TEGRA_DC_OUT_DSI:
+ dc->out_ops = &tegra_dc_dsi_ops;
+ break;
+#endif
default:
dc->out_ops = NULL;
break;
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h
index 75561402167e..10a8d50cd80e 100644
--- a/drivers/video/tegra/dc/dc_priv.h
+++ b/drivers/video/tegra/dc/dc_priv.h
@@ -144,5 +144,6 @@ void tegra_dc_setup_clk(struct tegra_dc *dc, struct clk *clk);
extern struct tegra_dc_out_ops tegra_dc_rgb_ops;
extern struct tegra_dc_out_ops tegra_dc_hdmi_ops;
+extern struct tegra_dc_out_ops tegra_dc_dsi_ops;
#endif
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
index 65a9217c15a3..29f98c1c4da7 100644
--- a/drivers/video/tegra/dc/dc_reg.h
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -32,6 +32,14 @@
#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a
#define DC_CMD_CONT_SYNCPT_VSYNC 0x028
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
+#define MSF_POLARITY_HIGH (0 << 0)
+#define MSF_POLARITY_LOW (1 << 0)
+#define MSF_DISABLE (0 << 1)
+#define MSF_ENABLE (1 << 1)
+#define MSF_LSPI (0 << 2)
+#define MSF_LDC (1 << 2)
+#define MSF_LSDI (2 << 2)
+
#define DC_CMD_DISPLAY_COMMAND 0x032
#define DISP_COMMAND_RAISE (1 << 0)
#define DISP_CTRL_MODE_STOP (0 << 5)
@@ -93,6 +101,7 @@
#define WIN_A_UPDATE (1 << 9)
#define WIN_B_UPDATE (1 << 10)
#define WIN_C_UPDATE (1 << 11)
+#define NC_HOST_TRIG (1 << 24)
#define DC_CMD_DISPLAY_WINDOW_HEADER 0x042
#define WINDOW_A_SELECT (1 << 4)
@@ -107,6 +116,8 @@
#define DC_COM_PIN_OUTPUT_ENABLE1 0x303
#define DC_COM_PIN_OUTPUT_ENABLE2 0x304
#define DC_COM_PIN_OUTPUT_ENABLE3 0x305
+#define PIN_OUTPUT_LSPI_OUTPUT_EN (1 << 8)
+#define PIN_OUTPUT_LSPI_OUTPUT_DIS (1 << 8)
#define DC_COM_PIN_OUTPUT_POLARITY0 0x306
#define DC_COM_PIN_OUTPUT_POLARITY1 0x307
@@ -127,6 +138,8 @@
#define DC_COM_PIN_INPUT_ENABLE1 0x30f
#define DC_COM_PIN_INPUT_ENABLE2 0x310
#define DC_COM_PIN_INPUT_ENABLE3 0x311
+#define PIN_INPUT_LSPI_INPUT_EN (1 << 8)
+#define PIN_INPUT_LSPI_INPUT_DIS (1 << 8)
#define DC_COM_PIN_INPUT_DATA0 0x312
#define DC_COM_PIN_INPUT_DATA1 0x313
#define DC_COM_PIN_OUTPUT_SELECT0 0x314
diff --git a/drivers/video/tegra/dc/dsi.c b/drivers/video/tegra/dc/dsi.c
new file mode 100644
index 000000000000..e0e9ed9f1083
--- /dev/null
+++ b/drivers/video/tegra/dc/dsi.c
@@ -0,0 +1,1468 @@
+/*
+ * drivers/video/tegra/dc/dsi.c
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/wakelock.h>
+#include <linux/switch.h>
+#include <linux/workqueue.h>
+
+#include <mach/clk.h>
+#include <mach/dc.h>
+#include <mach/fb.h>
+#include <mach/nvhost.h>
+#include <../gpio-names.h>
+
+#include "dc_reg.h"
+#include "dc_priv.h"
+#include "dsi_regs.h"
+#include "dsi.h"
+
+#define DSI_USE_SYNC_POINTS 0
+
+
+#define DSI_MODULE_NOT_INIT 0x0
+#define DSI_MODULE_INIT 0x1
+
+#define DSI_LPHS_NOT_INIT 0x0
+#define DSI_LPHS_IN_LP_MODE 0x1
+#define DSI_LPHS_IN_HS_MODE 0x2
+
+#define DSI_VIDEO_TYPE_NOT_INIT 0x0
+#define DSI_VIDEO_TYPE_VIDEO_MODE 0x1
+#define DSI_VIDEO_TYPE_CMD_MODE 0x2
+
+#define DSI_DRIVEN_MODE_NOT_INIT 0x0
+#define DSI_DRIVEN_MODE_DC 0x1
+#define DSI_DRIVEN_MODE_HOST 0x2
+
+#define DSI_PHYCLK_OUT_DIS 0x0
+#define DSI_PHYCLK_OUT_EN 0x1
+
+#define DSI_PHYCLK_NOT_INIT 0x0
+#define DSI_PHYCLK_CONTINUOUS 0x1
+#define DSI_PHYCLK_TX_ONLY 0x2
+
+#define DSI_CLK_BURST_NOT_INIT 0x0
+#define DSI_CLK_BURST_NONE_BURST 0x1
+#define DSI_CLK_BURST_BURST_MODE 0x2
+
+struct dsi_status {
+ unsigned init:2;
+
+ unsigned lphs:2;
+
+ unsigned vtype:2;
+ unsigned driven:2;
+
+ unsigned clk_out:2;
+ unsigned clk_mode:2;
+ unsigned clk_burst:2;
+};
+
+/* source of video data */
+enum{
+ TEGRA_DSI_DRIVEN_BY_DC,
+ TEGRA_DSI_DRIVEN_BY_HOST,
+};
+
+struct tegra_dc_dsi_data {
+ struct tegra_dc *dc;
+ void __iomem *base;
+ struct resource *base_res;
+
+ struct clk *dc_clk;
+ struct clk *dsi_clk;
+
+ struct mutex lock;
+
+ /* data from board info */
+ struct tegra_dsi_out info;
+
+ struct dsi_status status;
+
+ u8 driven_mode;
+ u8 controller_index;
+
+ u8 pixel_scaler_mul;
+ u8 pixel_scaler_div;
+
+ u32 default_pixel_clk_khz;
+ u32 default_hs_clk_khz;
+
+ u32 target_hs_clk_khz;
+ u32 target_lp_clk_khz;
+
+ u16 current_bit_clk_ns;
+ u32 current_dsi_clk_khz;
+
+ u32 dsi_control_val;
+};
+
+const u32 dsi_pkt_seq_reg[NUMOF_PKT_SEQ] = {
+ DSI_PKT_SEQ_0_LO,
+ DSI_PKT_SEQ_0_HI,
+ DSI_PKT_SEQ_1_LO,
+ DSI_PKT_SEQ_1_HI,
+ DSI_PKT_SEQ_2_LO,
+ DSI_PKT_SEQ_2_HI,
+ DSI_PKT_SEQ_3_LO,
+ DSI_PKT_SEQ_3_HI,
+ DSI_PKT_SEQ_4_LO,
+ DSI_PKT_SEQ_4_HI,
+ DSI_PKT_SEQ_5_LO,
+ DSI_PKT_SEQ_5_HI,
+};
+
+const u32 dsi_pkt_seq_video_non_burst_syne[NUMOF_PKT_SEQ] = {
+ PKT_ID0(CMD_VS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_VE) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+ PKT_ID2(CMD_HE) | PKT_LEN2(0),
+ PKT_ID3(CMD_BLNK) | PKT_LEN3(2) | PKT_ID4(CMD_RGB) | PKT_LEN4(3) |
+ PKT_ID5(CMD_BLNK) | PKT_LEN5(4),
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(1) |
+ PKT_ID2(CMD_HE) | PKT_LEN2(0),
+ PKT_ID3(CMD_BLNK) | PKT_LEN3(2) | PKT_ID4(CMD_RGB) | PKT_LEN4(3) |
+ PKT_ID5(CMD_BLNK) | PKT_LEN5(4),
+};
+
+const u32 dsi_pkt_seq_video_non_burst[NUMOF_PKT_SEQ] = {
+ PKT_ID0(CMD_VS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2) |
+ PKT_ID2(CMD_RGB) | PKT_LEN2(3),
+ PKT_ID3(CMD_BLNK) | PKT_LEN3(4),
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_EOT) | PKT_LEN1(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_HS) | PKT_LEN0(0) | PKT_ID1(CMD_BLNK) | PKT_LEN1(2) |
+ PKT_ID2(CMD_RGB) | PKT_LEN2(3),
+ PKT_ID3(CMD_BLNK) | PKT_LEN3(4),
+};
+
+static const u32 dsi_pkt_seq_video_burst[NUMOF_PKT_SEQ] = {
+ PKT_ID0(CMD_NULL) | PKT_LEN0(4) | PKT_ID1(CMD_VS) | PKT_LEN1(0) |
+ PKT_ID2(CMD_EOT) | PKT_LEN2(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_NULL) | PKT_LEN0(4) | PKT_ID1(CMD_HS) | PKT_LEN1(0) |
+ PKT_ID2(CMD_EOT) | PKT_LEN2(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_NULL) | PKT_LEN0(4) | PKT_ID1(CMD_HS) | PKT_LEN1(0) |
+ PKT_ID2(CMD_EOT) | PKT_LEN2(0) | PKT_LP,
+ PKT_ID0(CMD_BLNK) | PKT_LEN0(4) | PKT_ID1(CMD_HS) | PKT_LEN1(0) |
+ PKT_ID2(CMD_BLNK) | PKT_LEN2(2),
+ PKT_ID3(CMD_RGB) | PKT_LEN3(3) | PKT_ID4(CMD_EOT) | PKT_LEN4(0),
+ PKT_ID0(CMD_NULL) | PKT_LEN0(4) | PKT_ID1(CMD_HS) | PKT_LEN1(0) |
+ PKT_ID2(CMD_EOT) | PKT_LEN2(0) | PKT_LP,
+ 0,
+ PKT_ID0(CMD_BLNK) | PKT_LEN0(4) | PKT_ID1(CMD_HS) | PKT_LEN1(0) |
+ PKT_ID2(CMD_BLNK) | PKT_LEN2(2),
+ PKT_ID3(CMD_RGB) | PKT_LEN3(3) | PKT_ID4(CMD_EOT) | PKT_LEN4(0),
+};
+
+/* TODO: verify with hw about this format */
+const u32 dsi_pkt_seq_cmd_mode [NUMOF_PKT_SEQ] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ PKT_ID0(CMD_LONGW) | PKT_LEN0(3) | PKT_ID1(CMD_EOT) | PKT_LEN1(7),
+ 0,
+ 0,
+ 0,
+ PKT_ID0(CMD_LONGW) | PKT_LEN0(3) | PKT_ID1(CMD_EOT) | PKT_LEN1(7),
+ 0,
+};
+
+const u32 init_reg[] = {
+ DSI_WR_DATA,
+ DSI_INT_ENABLE,
+ DSI_INT_STATUS,
+ DSI_INT_MASK,
+ DSI_INIT_SEQ_DATA_0,
+ DSI_INIT_SEQ_DATA_1,
+ DSI_INIT_SEQ_DATA_2,
+ DSI_INIT_SEQ_DATA_3,
+ DSI_DCS_CMDS,
+ DSI_PKT_SEQ_0_LO,
+ DSI_PKT_SEQ_1_LO,
+ DSI_PKT_SEQ_2_LO,
+ DSI_PKT_SEQ_3_LO,
+ DSI_PKT_SEQ_4_LO,
+ DSI_PKT_SEQ_5_LO,
+ DSI_PKT_SEQ_0_HI,
+ DSI_PKT_SEQ_1_HI,
+ DSI_PKT_SEQ_2_HI,
+ DSI_PKT_SEQ_3_HI,
+ DSI_PKT_SEQ_4_HI,
+ DSI_PKT_SEQ_5_HI,
+ DSI_CONTROL,
+ DSI_HOST_DSI_CONTROL,
+ DSI_PAD_CONTROL,
+ DSI_PAD_CONTROL_CD,
+ DSI_SOL_DELAY,
+ DSI_MAX_THRESHOLD,
+ DSI_TRIGGER,
+ DSI_TX_CRC,
+ DSI_INIT_SEQ_CONTROL,
+ DSI_PKT_LEN_0_1,
+ DSI_PKT_LEN_2_3,
+ DSI_PKT_LEN_4_5,
+ DSI_PKT_LEN_6_7,
+};
+
+static inline unsigned long tegra_dsi_readl(struct tegra_dc_dsi_data *dsi,
+ u32 reg)
+{
+ return readl(dsi->base + reg * 4);
+}
+
+static inline void tegra_dsi_writel(struct tegra_dc_dsi_data *dsi,u32 val,
+ u32 reg)
+{
+ writel(val, dsi->base + reg * 4);
+}
+
+static u32 tegra_dsi_get_hs_clk_rate(struct tegra_dc_dsi_data *dsi)
+{
+ u32 dsi_clock_rate_khz;
+
+ switch (dsi->info.video_burst_mode) {
+ case TEGRA_DSI_VIDEO_BURST_MODE_LOW_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_MEDIUM_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_FAST_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_FASTEST_SPEED:
+ /* TODO: implement algo for these speed rate */
+
+ case TEGRA_DSI_VIDEO_BURST_MODE_MANUAL:
+ if (dsi->info.burst_mode_freq_khz) {
+ dsi_clock_rate_khz = dsi->info.burst_mode_freq_khz;
+ break;
+ }
+ case TEGRA_DSI_VIDEO_NONE_BURST_MODE:
+ case TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END:
+ case TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED:
+ default:
+ dsi_clock_rate_khz = dsi->default_hs_clk_khz;
+ break;
+ }
+
+ return dsi_clock_rate_khz;
+}
+
+static u32 tegra_dsi_get_lp_clk_rate(struct tegra_dc_dsi_data *dsi)
+{
+ u32 dsi_clock_rate_khz;
+
+ if (dsi->info.enable_hs_clock_on_lp_cmd_mode)
+ if (dsi->info.hs_clk_in_lp_cmd_mode_freq_khz)
+ dsi_clock_rate_khz =
+ dsi->info.hs_clk_in_lp_cmd_mode_freq_khz;
+ else
+ dsi_clock_rate_khz = tegra_dsi_get_hs_clk_rate(dsi);
+ else
+ dsi_clock_rate_khz = dsi->info.lp_cmd_mode_freq_khz;
+
+ return dsi_clock_rate_khz;
+}
+
+static void tegra_dsi_init_sw(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 h_width_pixels;
+ u32 v_width_lines;
+ u32 pixel_clk_hz;
+ u32 byte_clk_hz;
+
+ switch (dsi->info.pixel_format) {
+ case TEGRA_DSI_PIXEL_FORMAT_16BIT_P:
+ /* 2 bytes per pixel */
+ dsi->pixel_scaler_mul = 2;
+ dsi->pixel_scaler_div = 1;
+ break;
+ case TEGRA_DSI_PIXEL_FORMAT_18BIT_P:
+ /* 2.25 bytes per pixel */
+ dsi->pixel_scaler_mul = 9;
+ dsi->pixel_scaler_div = 4;
+ break;
+ case TEGRA_DSI_PIXEL_FORMAT_18BIT_NP:
+ case TEGRA_DSI_PIXEL_FORMAT_24BIT_P:
+ /* 3 bytes per pixel */
+ dsi->pixel_scaler_mul = 3;
+ dsi->pixel_scaler_div = 1;
+ break;
+ default:
+ break;
+ }
+
+ h_width_pixels = dc->mode.h_back_porch + dc->mode.h_front_porch +
+ dc->mode.h_sync_width + dc->mode.h_active;
+ v_width_lines = dc->mode.v_back_porch + dc->mode.v_front_porch +
+ dc->mode.v_sync_width + dc->mode.v_active;
+
+ /* The slowest pixel rate that is required */
+ /* for the given display timing */
+ pixel_clk_hz = h_width_pixels * v_width_lines * dsi->info.refresh_rate;
+
+ /* Pixel byte rate on DSI interface */
+ byte_clk_hz = (pixel_clk_hz * dsi->pixel_scaler_mul) /
+ (dsi->pixel_scaler_div * dsi->info.n_data_lanes);
+
+ dsi->default_pixel_clk_khz = pixel_clk_hz / 1000;
+
+ printk("dsi: default pixel rate %d khz\n", dsi->default_pixel_clk_khz);
+
+ /*
+ * Pixel bit rate on DSI. Since DSI interface is double data rate (
+ * transferring data on both rising and falling edge of clk), div by 2
+ * to get the actual clock rate.
+ */
+ dsi->default_hs_clk_khz =
+ (byte_clk_hz * NUMOF_BIT_PER_BYTE) / (1000 * 2);
+
+ dsi->dsi_control_val =
+ DSI_CONTROL_VIRTUAL_CHANNEL(dsi->info.virtual_channel) |
+ DSI_CONTROL_NUM_DATA_LANES(dsi->info.n_data_lanes - 1) |
+ DSI_CONTROL_VID_SOURCE(dsi->controller_index) |
+ DSI_CONTROL_DATA_FORMAT(dsi->info.pixel_format);
+
+ dsi->target_lp_clk_khz = tegra_dsi_get_lp_clk_rate(dsi);
+ dsi->target_hs_clk_khz = tegra_dsi_get_hs_clk_rate(dsi);
+
+ /*
+ * Force video clock to be continuous mode if
+ * enable_hs_clock_on_lp_cmd_mode is set
+ */
+ if (dsi->info.enable_hs_clock_on_lp_cmd_mode) {
+ if (dsi->info.video_clock_mode != TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS)
+ printk("Force to clock continuous mode\n");
+
+ dsi->info.video_clock_mode = TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS;
+ }
+
+}
+
+static void tegra_dsi_get_phy_timing(struct tegra_dc_dsi_data *dsi,
+ struct dsi_phy_timing_inclk *phy_timing_clk,
+ u32 clk_ns)
+{
+
+ phy_timing_clk->t_hsdexit = dsi->info.phy_timing.t_hsdexit_ns ?
+ (dsi->info.phy_timing.t_hsdexit_ns / clk_ns) :
+ (T_HSEXIT_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_hstrail = dsi->info.phy_timing.t_hstrail_ns ?
+ (dsi->info.phy_timing.t_hstrail_ns / clk_ns) :
+ (T_HSTRAIL_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_datzero = dsi->info.phy_timing.t_datzero_ns ?
+ (dsi->info.phy_timing.t_datzero_ns / clk_ns) :
+ (T_DATZERO_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_hsprepr = dsi->info.phy_timing.t_hsprepr_ns ?
+ (dsi->info.phy_timing.t_hsprepr_ns / clk_ns) :
+ (T_HSPREPR_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_clktrail = dsi->info.phy_timing.t_clktrail_ns ?
+ (dsi->info.phy_timing.t_clktrail_ns / clk_ns) :
+ (T_CLKTRAIL_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_clkpost = dsi->info.phy_timing.t_clkpost_ns ?
+ (dsi->info.phy_timing.t_clkpost_ns / clk_ns) :
+ (T_CLKPOST_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_clkzero = dsi->info.phy_timing.t_clkzero_ns ?
+ (dsi->info.phy_timing.t_clkzero_ns / clk_ns) :
+ (T_CLKZERO_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_tlpx = dsi->info.phy_timing.t_tlpx_ns ?
+ (dsi->info.phy_timing.t_tlpx_ns / clk_ns) :
+ (T_TLPX_DEFAULT(clk_ns));
+
+ phy_timing_clk->t_clkpre = T_CLKPRE_DEFAULT(clk_ns);
+ phy_timing_clk->t_clkprepare = T_CLKPREPARE_DEFAULT(clk_ns);
+ phy_timing_clk->t_wakeup = T_WAKEUP_DEFAULT(clk_ns);
+
+ phy_timing_clk->t_taget = 5 * phy_timing_clk->t_tlpx;
+ phy_timing_clk->t_tasure = 2 * phy_timing_clk->t_tlpx;
+ phy_timing_clk->t_tago = 4 * phy_timing_clk->t_tlpx;
+}
+
+static void tegra_dsi_set_phy_timing(struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+ struct dsi_phy_timing_inclk phy_timing;
+
+ tegra_dsi_get_phy_timing(dsi, &phy_timing, dsi->current_bit_clk_ns);
+
+ val = DSI_PHY_TIMING_0_THSDEXIT(phy_timing.t_hsdexit) |
+ DSI_PHY_TIMING_0_THSTRAIL(phy_timing.t_hstrail) |
+ DSI_PHY_TIMING_0_TDATZERO(phy_timing.t_datzero) |
+ DSI_PHY_TIMING_0_THSPREPR(phy_timing.t_hsprepr);
+ tegra_dsi_writel(dsi, val, DSI_PHY_TIMING_0);
+
+ val = DSI_PHY_TIMING_1_TCLKTRAIL(phy_timing.t_clktrail) |
+ DSI_PHY_TIMING_1_TCLKPOST(phy_timing.t_clkpost) |
+ DSI_PHY_TIMING_1_TCLKZERO(phy_timing.t_clkzero) |
+ DSI_PHY_TIMING_1_TTLPX(phy_timing.t_tlpx);
+ tegra_dsi_writel(dsi, val, DSI_PHY_TIMING_1);
+
+ val = DSI_PHY_TIMING_2_TCLKPREPARE(phy_timing.t_clkprepare) |
+ DSI_PHY_TIMING_2_TCLKPRE(phy_timing.t_clkpre) |
+ DSI_PHY_TIMING_2_TWAKEUP(phy_timing.t_wakeup);
+ tegra_dsi_writel(dsi, val, DSI_PHY_TIMING_2);
+
+ val = DSI_BTA_TIMING_TTAGET(phy_timing.t_taget) |
+ DSI_BTA_TIMING_TTASURE(phy_timing.t_tasure) |
+ DSI_BTA_TIMING_TTAGO(phy_timing.t_tago);
+ tegra_dsi_writel(dsi, val, DSI_BTA_TIMING);
+}
+
+static u32 tegra_dsi_sol_delay_burst(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 dsi_to_pixel_clk_ratio;
+ u32 temp;
+ u32 temp1;
+ u32 mipi_clk_adj_kHz;
+ u32 sol_delay;
+ struct tegra_dc_mode *dc_modes = &dc->mode;
+
+ /* Get Fdsi/Fpixel ration (note: Fdsi si in bit format) */
+ dsi_to_pixel_clk_ratio = (dsi->current_dsi_clk_khz * 2 +
+ dsi->default_pixel_clk_khz - 1) / dsi->default_pixel_clk_khz;
+
+ /* Convert Fdsi to byte format */
+ dsi_to_pixel_clk_ratio *= 1000/8;
+
+ /* Multiplying by 1000 so that we don't loose the fraction part */
+ temp = dc_modes->h_active * 1000;
+ temp1 = dc_modes->h_active + dc_modes->h_back_porch +
+ dc_modes->h_sync_width;
+
+ sol_delay = temp1 * dsi_to_pixel_clk_ratio -
+ temp * dsi->pixel_scaler_mul /
+ (dsi->pixel_scaler_div * dsi->info.n_data_lanes);
+
+ /* Do rounding on sol delay */
+ sol_delay = (sol_delay + 1000 - 1)/1000;
+
+ /* TODO:
+ * 1. find out the correct sol fifo depth to use
+ * 2. verify with hw about the clamping function
+ */
+ if (sol_delay > (480 * 4)) {
+ sol_delay = (480 * 4);
+ mipi_clk_adj_kHz = sol_delay +
+ (dc_modes->h_active * dsi->pixel_scaler_mul) /
+ (dsi->info.n_data_lanes * dsi->pixel_scaler_div);
+
+ mipi_clk_adj_kHz *= (dsi->default_pixel_clk_khz / temp1);
+
+ mipi_clk_adj_kHz *= 4;
+ }
+
+ dsi->target_hs_clk_khz = mipi_clk_adj_kHz;
+
+ return sol_delay;
+}
+
+static void tegra_dsi_set_sol_delay(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 sol_delay;
+
+ if (dsi->info.video_burst_mode == TEGRA_DSI_VIDEO_NONE_BURST_MODE ||
+ dsi->info.video_burst_mode ==
+ TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END) {
+ sol_delay = NUMOF_BIT_PER_BYTE * dsi->pixel_scaler_mul /
+ (dsi->pixel_scaler_div * dsi->info.n_data_lanes);
+ dsi->status.clk_burst = DSI_CLK_BURST_NONE_BURST;
+ } else {
+ sol_delay = tegra_dsi_sol_delay_burst(dc, dsi);
+ dsi->status.clk_burst = DSI_CLK_BURST_BURST_MODE;
+ }
+
+ tegra_dsi_writel(dsi, DSI_SOL_DELAY_SOL_DELAY(sol_delay),
+ DSI_SOL_DELAY);
+}
+
+static void tegra_dsi_set_timeout(struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+ u32 bytes_per_frame;
+ u32 timeout = 0;
+
+ /* TODO: verify the following eq */
+ bytes_per_frame = dsi->current_dsi_clk_khz * 1000 * 2 /
+ (dsi->info.refresh_rate * 8);
+ timeout = bytes_per_frame / DSI_CYCLE_COUNTER_VALUE;
+ timeout = (timeout + DSI_HTX_TO_MARGIN) & 0xffff;
+
+ val = DSI_TIMEOUT_0_LRXH_TO(DSI_LRXH_TO_VALUE) |
+ DSI_TIMEOUT_0_HTX_TO(timeout);
+ tegra_dsi_writel(dsi, val, DSI_TIMEOUT_0);
+
+ if (dsi->info.panel_reset_timeout_msec)
+ timeout = (dsi->info.panel_reset_timeout_msec * 1000*1000)
+ / dsi->current_bit_clk_ns;
+ else
+ timeout = DSI_PR_TO_VALUE;
+
+ val = DSI_TIMEOUT_1_PR_TO(timeout) |
+ DSI_TIMEOUT_1_TA_TO(DSI_TA_TO_VALUE);
+ tegra_dsi_writel(dsi, val, DSI_TIMEOUT_1);
+
+ val = DSI_TO_TALLY_P_RESET_STATUS(IN_RESET) |
+ DSI_TO_TALLY_TA_TALLY(DSI_TA_TALLY_VALUE)|
+ DSI_TO_TALLY_LRXH_TALLY(DSI_LRXH_TALLY_VALUE)|
+ DSI_TO_TALLY_HTX_TALLY(DSI_HTX_TALLY_VALUE);
+ tegra_dsi_writel(dsi, val, DSI_TO_TALLY);
+}
+
+static void tegra_dsi_setup_video_mode_pkt_length(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+ u32 hact_pkt_len;
+ u32 hsa_pkt_len;
+ u32 hbp_pkt_len;
+ u32 hfp_pkt_len;
+
+ hact_pkt_len = dc->mode.h_active * dsi->pixel_scaler_mul /
+ dsi->pixel_scaler_div;
+ hsa_pkt_len = dc->mode.h_sync_width * dsi->pixel_scaler_mul /
+ dsi->pixel_scaler_div;
+ hbp_pkt_len = dc->mode.h_back_porch * dsi->pixel_scaler_mul /
+ dsi->pixel_scaler_div;
+ hfp_pkt_len = dc->mode.h_front_porch * dsi->pixel_scaler_mul /
+ dsi->pixel_scaler_div;
+
+ if (dsi->info.video_burst_mode !=
+ TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END)
+ hbp_pkt_len += hsa_pkt_len;
+
+ hsa_pkt_len -= DSI_HSYNC_BLNK_PKT_OVERHEAD;
+ hbp_pkt_len -= DSI_HBACK_PORCH_PKT_OVERHEAD;
+ hfp_pkt_len -= DSI_HFRONT_PORCH_PKT_OVERHEAD;
+
+ val = DSI_PKT_LEN_0_1_LENGTH_0(0) | DSI_PKT_LEN_0_1_LENGTH_1(hsa_pkt_len);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_0_1);
+
+ val = DSI_PKT_LEN_2_3_LENGTH_2(hbp_pkt_len) |
+ DSI_PKT_LEN_2_3_LENGTH_3(hact_pkt_len);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_2_3);
+
+ val = DSI_PKT_LEN_4_5_LENGTH_4(hfp_pkt_len) | DSI_PKT_LEN_4_5_LENGTH_5(0);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_4_5);
+
+ val = DSI_PKT_LEN_6_7_LENGTH_6(0) | DSI_PKT_LEN_6_7_LENGTH_7(0);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_6_7);
+}
+
+static void tegra_dsi_setup_cmd_mode_pkt_length(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ unsigned long val;
+ unsigned long act_bytes;
+
+ act_bytes = dc->mode.h_active * dsi->pixel_scaler_mul /
+ dsi->pixel_scaler_div + 1;
+
+ val = DSI_PKT_LEN_0_1_LENGTH_0(0) | DSI_PKT_LEN_0_1_LENGTH_1(0);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_0_1);
+
+ val = DSI_PKT_LEN_2_3_LENGTH_2(0) | DSI_PKT_LEN_2_3_LENGTH_3(act_bytes);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_2_3);
+
+ val = DSI_PKT_LEN_4_5_LENGTH_4(0) | DSI_PKT_LEN_4_5_LENGTH_5(act_bytes);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_4_5);
+
+ val = DSI_PKT_LEN_6_7_LENGTH_6(0) | DSI_PKT_LEN_6_7_LENGTH_7(0x0f0f);
+ tegra_dsi_writel(dsi, val, DSI_PKT_LEN_6_7);
+}
+
+static void tegra_dsi_set_pkt_length(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_HOST)
+ return;
+
+ if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_VIDEO_MODE)
+ tegra_dsi_setup_video_mode_pkt_length(dc, dsi);
+ else
+ tegra_dsi_setup_cmd_mode_pkt_length(dc, dsi);
+}
+
+static void tegra_dsi_set_pkt_seq(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ const u32 *pkt_seq;
+ u32 rgb_info;
+ u32 pkt_seq_3_5_rgb_lo;
+ u32 pkt_seq_3_5_rgb_hi;
+ u32 val;
+ u32 reg;
+ u8 i;
+
+ if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_HOST)
+ return;
+
+ switch(dsi->info.pixel_format) {
+ case TEGRA_DSI_PIXEL_FORMAT_16BIT_P:
+ rgb_info = CMD_RGB_16BPP;
+ break;
+ case TEGRA_DSI_PIXEL_FORMAT_18BIT_P:
+ rgb_info = CMD_RGB_18BPP;
+ break;
+ case TEGRA_DSI_PIXEL_FORMAT_18BIT_NP:
+ rgb_info = CMD_RGB_18BPPNP;
+ break;
+ case TEGRA_DSI_PIXEL_FORMAT_24BIT_P:
+ default:
+ rgb_info = CMD_RGB_24BPP;
+ break;
+ }
+
+ pkt_seq_3_5_rgb_lo = 0;
+ pkt_seq_3_5_rgb_hi = 0;
+ if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE)
+ pkt_seq = dsi_pkt_seq_cmd_mode;
+ else {
+ switch (dsi->info.video_burst_mode) {
+ case TEGRA_DSI_VIDEO_BURST_MODE_LOWEST_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_LOW_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_MEDIUM_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_FAST_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_FASTEST_SPEED:
+ case TEGRA_DSI_VIDEO_BURST_MODE_MANUAL:
+ pkt_seq_3_5_rgb_hi = DSI_PKT_SEQ_3_HI_PKT_33_ID(rgb_info);
+ pkt_seq = dsi_pkt_seq_video_burst;
+ break;
+ case TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END:
+ pkt_seq_3_5_rgb_hi = DSI_PKT_SEQ_3_HI_PKT_34_ID(rgb_info);
+ pkt_seq = dsi_pkt_seq_video_non_burst_syne;
+ break;
+ case TEGRA_DSI_VIDEO_NONE_BURST_MODE:
+ default:
+ pkt_seq_3_5_rgb_lo = DSI_PKT_SEQ_3_LO_PKT_32_ID(rgb_info);
+ pkt_seq = dsi_pkt_seq_video_non_burst;
+ break;
+ }
+ }
+
+ for (i = 0; i < NUMOF_PKT_SEQ; i++) {
+ val = pkt_seq[i];
+ reg = dsi_pkt_seq_reg[i];
+ if ((reg == DSI_PKT_SEQ_3_LO) || (reg == DSI_PKT_SEQ_5_LO))
+ val |= pkt_seq_3_5_rgb_lo;
+ if ((reg == DSI_PKT_SEQ_3_HI) || (reg == DSI_PKT_SEQ_5_HI))
+ val |= pkt_seq_3_5_rgb_hi;
+ tegra_dsi_writel(dsi, val, reg);
+ }
+}
+
+static void tegra_dsi_stop_dc_stream(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ /*
+ * TODO: It is possible that we are in the middle of video stream,
+ * Add code to wait for vsync and then stop DC from sending data to dsi
+ */
+ tegra_dc_writel(dc, 0, DC_DISP_DISP_WIN_OPTIONS);
+}
+
+static void tegra_dsi_start_dc_stream(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+ tegra_dc_writel(dc, DSI_ENABLE, DC_DISP_DISP_WIN_OPTIONS);
+
+ /* TODO: clean up */
+ val = PIN_INPUT_LSPI_INPUT_EN;
+ tegra_dc_writel(dc, val, DC_COM_PIN_INPUT_ENABLE3);
+
+ val = PIN_OUTPUT_LSPI_OUTPUT_DIS;
+ tegra_dc_writel(dc, val, DC_COM_PIN_OUTPUT_ENABLE3);
+
+ tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
+ PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
+ DC_CMD_DISPLAY_POWER_CONTROL);
+
+ val = MSF_POLARITY_HIGH | MSF_ENABLE | MSF_LSPI;
+ tegra_dc_writel(dc, val, DC_CMD_DISPLAY_COMMAND_OPTION0);
+
+
+ /* TODO: using continuous video mode for now */
+ /* if (dsi->info.panel_has_frame_buffer) {*/
+ if (0) {
+ tegra_dc_writel(dc, DISP_CTRL_MODE_NC_DISPLAY, DC_CMD_DISPLAY_COMMAND);
+ tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
+ val = GENERAL_ACT_REQ | NC_HOST_TRIG;
+ tegra_dc_writel(dc, val, DC_CMD_STATE_CONTROL);
+ } else {
+ tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);
+ tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
+ }
+}
+
+static void tegra_dsi_set_dc_clk(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 shift_clk_div;
+ u32 val;
+
+ if (dsi->info.video_burst_mode == TEGRA_DSI_VIDEO_NONE_BURST_MODE ||
+ dsi->info.video_burst_mode ==
+ TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END)
+ shift_clk_div = NUMOF_BIT_PER_BYTE * dsi->pixel_scaler_mul /
+ (dsi->pixel_scaler_div * dsi->info.n_data_lanes) - 2;
+ else
+ shift_clk_div = (dsi->current_dsi_clk_khz * 2 +
+ dsi->default_hs_clk_khz - 1) /
+ (dsi->default_hs_clk_khz) - 2;
+
+#ifdef CONFIG_TEGRA_FPGA_PLATFORM
+ shift_clk_div = 1;
+#endif
+
+ /* TODO: find out if PCD3 option is required */
+ val = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(shift_clk_div);
+ tegra_dc_writel(dc, val, DC_DISP_DISP_CLOCK_CONTROL);
+
+ clk_enable(dsi->dc_clk);
+}
+
+static void tegra_dsi_set_dsi_clk(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi, u32 clk)
+{
+ u32 rm;
+
+ rm = clk % 100;
+ if (rm != 0)
+ clk -= rm;
+
+ clk *= 2; /* Value for PLLD routine is required to be twice as */
+ /* the desired clock rate */
+
+ dc->mode.pclk = clk*1000;
+ tegra_dc_setup_clk(dc, dsi->dsi_clk);
+ clk_enable(dsi->dsi_clk);
+ tegra_periph_reset_deassert(dsi->dsi_clk);
+
+ dsi->current_dsi_clk_khz = clk_get_rate(dsi->dsi_clk) / 1000;
+
+ dsi->current_bit_clk_ns = 1000*1000 / (dsi->current_dsi_clk_khz * 2);
+}
+
+static void tegra_dsi_hs_clk_out_enable(struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+
+ val = tegra_dsi_readl(dsi, DSI_CONTROL);
+ val &= ~DSI_CONTROL_HS_CLK_CTRL(1);
+
+ if (dsi->info.video_clock_mode == TEGRA_DSI_VIDEO_CLOCK_CONTINUOUS) {
+ val |= DSI_CONTROL_HS_CLK_CTRL(CONTINUOUS);
+ dsi->status.clk_mode = DSI_PHYCLK_CONTINUOUS;
+ } else {
+ val |= DSI_CONTROL_HS_CLK_CTRL(TX_ONLY);
+ dsi->status.clk_mode = DSI_PHYCLK_TX_ONLY;
+ }
+ tegra_dsi_writel(dsi, val, DSI_CONTROL);
+
+ val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
+ val &= ~DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(1);
+ val |= DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_HIGH);
+ tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
+
+ dsi->status.clk_out = DSI_PHYCLK_OUT_EN;
+}
+
+static void tegra_dsi_hs_clk_out_enable_in_lp(struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+ tegra_dsi_hs_clk_out_enable(dsi);
+
+ val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
+ val &= ~DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(1);
+ val |= DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_LOW);
+ tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
+}
+
+static void tegra_dsi_hs_clk_out_disable(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+
+ if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
+ tegra_dsi_stop_dc_stream(dc, dsi);
+
+ val = tegra_dsi_readl(dsi, DSI_CONTROL);
+ val &= ~DSI_CONTROL_HS_CLK_CTRL(1);
+ val |= DSI_CONTROL_HS_CLK_CTRL(TX_ONLY);
+ tegra_dsi_writel(dsi, val, DSI_CONTROL);
+
+ /* TODO: issue a cmd */
+
+ val = tegra_dsi_readl(dsi, DSI_HOST_DSI_CONTROL);
+ val &= ~DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(1);
+ val |= DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_LOW);
+ tegra_dsi_writel(dsi, val, DSI_HOST_DSI_CONTROL);
+
+ dsi->status.clk_mode = DSI_PHYCLK_NOT_INIT;
+ dsi->status.clk_out = DSI_PHYCLK_OUT_DIS;
+}
+
+static void tegra_dsi_set_control_reg_lp(struct tegra_dc_dsi_data *dsi)
+{
+ u32 dsi_control;
+ u32 host_dsi_control;
+ u32 max_threshold;
+
+ dsi_control = dsi->dsi_control_val | DSI_CTRL_HOST_DRIVEN;
+ host_dsi_control = HOST_DSI_CTRL_COMMON |
+ HOST_DSI_CTRL_HOST_DRIVEN |
+ DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(TEGRA_DSI_LOW);
+ max_threshold = DSI_MAX_THRESHOLD_MAX_THRESHOLD(DSI_HOST_FIFO_DEPTH);
+
+ tegra_dsi_writel(dsi, max_threshold, DSI_MAX_THRESHOLD);
+ tegra_dsi_writel(dsi, dsi_control, DSI_CONTROL);
+ tegra_dsi_writel(dsi, host_dsi_control, DSI_HOST_DSI_CONTROL);
+
+ dsi->status.driven = DSI_DRIVEN_MODE_HOST;
+ dsi->status.clk_burst = DSI_CLK_BURST_NOT_INIT;
+ dsi->status.vtype = DSI_VIDEO_TYPE_NOT_INIT;
+}
+
+static void tegra_dsi_set_control_reg_hs(struct tegra_dc_dsi_data *dsi)
+{
+ u32 dsi_control;
+ u32 host_dsi_control;
+ u32 max_threshold;
+ u32 dcs_cmd;
+
+ dsi_control = dsi->dsi_control_val;
+ host_dsi_control = HOST_DSI_CTRL_COMMON;
+ max_threshold = 0;
+ dcs_cmd = 0;
+
+ if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_HOST) {
+ dsi_control |= DSI_CTRL_HOST_DRIVEN;
+ host_dsi_control |= HOST_DSI_CTRL_HOST_DRIVEN;
+ max_threshold = DSI_MAX_THRESHOLD_MAX_THRESHOLD(DSI_HOST_FIFO_DEPTH);
+ dsi->status.driven = DSI_DRIVEN_MODE_HOST;
+ } else {
+ dsi_control |= DSI_CTRL_DC_DRIVEN;
+ host_dsi_control |= HOST_DSI_CTRL_DC_DRIVEN;
+ max_threshold = DSI_MAX_THRESHOLD_MAX_THRESHOLD(DSI_VIDEO_FIFO_DEPTH);
+ dsi->status.driven = DSI_DRIVEN_MODE_DC;
+ }
+
+ if (dsi->info.video_data_type == TEGRA_DSI_VIDEO_TYPE_COMMAND_MODE) {
+ dsi_control |= DSI_CTRL_CMD_MODE;
+ host_dsi_control |= HOST_DSI_CTRL_CMD_MODE;
+ dcs_cmd = DSI_DCS_CMDS_LT5_DCS_CMD(DSI_WRITE_MEMORY_START)|
+ DSI_DCS_CMDS_LT3_DCS_CMD(DSI_WRITE_MEMORY_CONTINUE);
+ dsi->status.vtype = DSI_VIDEO_TYPE_CMD_MODE;
+
+ } else {
+ dsi_control |= DSI_CTRL_VIDEO_MODE;
+ host_dsi_control |= HOST_DSI_CTRL_VIDEO_MODE;
+ dsi->status.vtype = DSI_VIDEO_TYPE_VIDEO_MODE;
+ }
+
+ tegra_dsi_writel(dsi, max_threshold, DSI_MAX_THRESHOLD);
+ tegra_dsi_writel(dsi, dcs_cmd, DSI_DCS_CMDS);
+ tegra_dsi_writel(dsi, dsi_control, DSI_CONTROL);
+ tegra_dsi_writel(dsi, host_dsi_control, DSI_HOST_DSI_CONTROL);
+}
+
+static int tegra_dsi_init_hw(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 val;
+ u32 i;
+ int err;
+
+ tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_lp_clk_khz);
+
+ /* TODO: only need to change the timing for bta */
+ tegra_dsi_set_phy_timing(dsi);
+
+ err = gpio_request(TEGRA_GPIO_PJ1, "DSI TE");
+ if (err < 0)
+ goto fail;
+
+ err = gpio_direction_input(TEGRA_GPIO_PJ1);
+ if (err < 0) {
+ gpio_free(TEGRA_GPIO_PJ1);
+ goto fail;
+ }
+ tegra_gpio_enable(TEGRA_GPIO_PJ1);
+
+ if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
+ tegra_dsi_stop_dc_stream(dc, dsi);
+
+ /* Initializing DSI registers */
+ for (i = 0; i < ARRAY_SIZE(init_reg); i++) {
+ tegra_dsi_writel(dsi, 0, init_reg[i]);
+ }
+ tegra_dsi_writel(dsi, dsi->dsi_control_val, DSI_CONTROL);
+
+ val = DSI_PAD_CONTROL_PAD_PDIO(0) |
+ DSI_PAD_CONTROL_PAD_PDIO_CLK(0) |
+ DSI_PAD_CONTROL_PAD_PULLDN_ENAB(TEGRA_DSI_DISABLE);
+ tegra_dsi_writel(dsi, val, DSI_PAD_CONTROL);
+
+ val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_ENABLE);
+ tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL);
+
+ while (tegra_dsi_readl(dsi, DSI_POWER_CONTROL) != val) {
+ tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL);
+ }
+
+ dsi->status.init = DSI_MODULE_INIT;
+ dsi->status.lphs = DSI_LPHS_NOT_INIT;
+ dsi->status.vtype = DSI_VIDEO_TYPE_NOT_INIT;
+ dsi->status.driven = DSI_DRIVEN_MODE_NOT_INIT;
+ dsi->status.clk_out = DSI_PHYCLK_OUT_DIS;
+ dsi->status.clk_mode = DSI_PHYCLK_NOT_INIT;
+ dsi->status.clk_burst = DSI_CLK_BURST_NOT_INIT;
+fail:
+ return err;
+}
+
+static int tegra_dsi_set_to_lp_mode(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ int err;
+
+ if (dsi->status.init != DSI_MODULE_INIT) {
+ err = -EPERM;
+ goto fail;
+ }
+
+ if (dsi->status.lphs == DSI_LPHS_IN_LP_MODE)
+ goto success;
+
+ if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
+ tegra_dsi_stop_dc_stream(dc, dsi);
+
+ /* disable/enable hs clock according to enable_hs_clock_on_lp_cmd_mode */
+ if ((dsi->status.clk_out == DSI_PHYCLK_OUT_EN) &&
+ (!dsi->info.enable_hs_clock_on_lp_cmd_mode))
+ tegra_dsi_hs_clk_out_disable(dc, dsi);
+
+ if (dsi->current_dsi_clk_khz != dsi->target_lp_clk_khz){
+ tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_lp_clk_khz);
+ tegra_dsi_set_timeout(dsi);
+ }
+
+ tegra_dsi_set_control_reg_lp(dsi);
+
+ if ((dsi->status.clk_out == DSI_PHYCLK_OUT_DIS) &&
+ (dsi->info.enable_hs_clock_on_lp_cmd_mode))
+ tegra_dsi_hs_clk_out_enable_in_lp(dsi);
+
+success:
+ dsi->status.lphs = DSI_LPHS_IN_LP_MODE;
+ err = 0;
+fail:
+ return err;
+}
+
+static int tegra_dsi_set_to_hs_mode(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ int err;
+
+ if (dsi->status.init != DSI_MODULE_INIT) {
+ err = -EPERM;
+ goto fail;
+ }
+
+ if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
+ tegra_dsi_stop_dc_stream(dc, dsi);
+
+ if ((dsi->status.clk_out == DSI_PHYCLK_OUT_EN) &&
+ (!dsi->info.enable_hs_clock_on_lp_cmd_mode))
+ tegra_dsi_hs_clk_out_disable(dc, dsi);
+
+ if (dsi->current_dsi_clk_khz != dsi->target_hs_clk_khz) {
+ tegra_dsi_set_dsi_clk(dc, dsi, dsi->target_hs_clk_khz);
+ tegra_dsi_set_timeout(dsi);
+ }
+
+ tegra_dsi_set_phy_timing(dsi);
+
+ if (dsi->driven_mode == TEGRA_DSI_DRIVEN_BY_DC){
+ tegra_dsi_set_pkt_seq(dc, dsi);
+ tegra_dsi_set_pkt_length(dc, dsi);
+ tegra_dsi_set_sol_delay(dc, dsi);
+ tegra_dsi_set_dc_clk(dc, dsi);
+ }
+
+ tegra_dsi_set_control_reg_hs(dsi);
+
+ if (dsi->status.clk_out == DSI_PHYCLK_OUT_DIS)
+ tegra_dsi_hs_clk_out_enable(dsi);
+
+ dsi->status.lphs = DSI_LPHS_IN_HS_MODE;
+ err = 0;
+fail:
+ return err;
+}
+
+static bool tegra_dsi_is_controller_idle(struct tegra_dc_dsi_data *dsi)
+{
+ u32 timeout = 0;
+ bool retVal;
+
+ retVal = false;
+ while (timeout <= DSI_MAX_COMMAND_DELAY_USEC) {
+ if (!tegra_dsi_readl(dsi, DSI_TRIGGER)) {
+ retVal = true;
+ break;
+ }
+ udelay(DSI_COMMAND_DELAY_STEPS_USEC);
+ timeout += DSI_COMMAND_DELAY_STEPS_USEC;
+ }
+
+ return retVal;
+}
+
+static bool tegra_dsi_host_trigger(struct tegra_dc_dsi_data *dsi)
+{
+ bool status;
+
+ status = false;
+ if (tegra_dsi_readl(dsi, DSI_TRIGGER))
+ goto fail;
+
+ tegra_dsi_writel(dsi, DSI_TRIGGER_HOST_TRIGGER(TEGRA_DSI_ENABLE),
+ DSI_TRIGGER);
+
+#if DSI_USE_SYNC_POINTS
+ /* TODO: Implement sync point */
+#else
+ status = tegra_dsi_is_controller_idle(dsi);
+#endif
+
+fail:
+ return status;
+}
+
+static int tegra_dsi_read_data(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ /* TODO: implement DSI read */
+ return ENXIO;
+}
+
+static int tegra_dsi_write_data(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi,
+ u8* pdata, u8 data_id, u16 data_len)
+{
+ bool switch_back_to_hs_mode;
+ bool switch_back_to_dc_mode;
+ u32 val;
+ u8 *pval;
+ int err;
+ u8 virtua_channel;
+
+ err = 0;
+ switch_back_to_hs_mode = false;
+ switch_back_to_dc_mode = false;
+
+ if ((dsi->status.init != DSI_MODULE_INIT) ||
+ (dsi->status.lphs == DSI_LPHS_NOT_INIT)) {
+ err = -EPERM;
+ goto fail;
+ }
+
+ if (!tegra_dsi_is_controller_idle(dsi)) {
+ err = -EBUSY;
+ goto fail;
+ }
+
+ err = 0;
+
+ if (dsi->status.lphs == DSI_LPHS_IN_HS_MODE) {
+ if (dsi->info.hs_cmd_mode_supported) {
+ if (dsi->status.driven == DSI_DRIVEN_MODE_DC) {
+ dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_HOST;
+ tegra_dsi_set_to_hs_mode(dc, dsi);
+ switch_back_to_dc_mode = true;
+ }
+ } else {
+ tegra_dsi_set_to_lp_mode(dc, dsi);
+ switch_back_to_hs_mode = true;
+ }
+ }
+
+ virtua_channel = dsi->info.virtual_channel << DSI_VIR_CHANNEL_BIT_POSITION;
+
+ /* always use hw for ecc */
+ val = (virtua_channel | data_id) << 0 |
+ data_len << 8;
+ tegra_dsi_writel(dsi, val, DSI_WR_DATA);
+
+ /* if pdata != NULL, pkt type is long pkt */
+ if (pdata != NULL) {
+ while (data_len) {
+ if (data_len >= 4) {
+ val = ((u32*) pdata)[0];
+ data_len -= 4;
+ pdata += 4;
+ } else {
+ val = 0;
+ pval = (u8*) &val;
+ do
+ *pval++ = *pdata++;
+ while(--data_len);
+ }
+ tegra_dsi_writel(dsi, val, DSI_WR_DATA);
+ }
+ }
+
+ if (!tegra_dsi_host_trigger(dsi))
+ err = -EIO;
+
+ if (switch_back_to_dc_mode)
+ dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_DC;
+ if (switch_back_to_dc_mode || switch_back_to_hs_mode)
+ tegra_dsi_set_to_hs_mode(dc, dsi);
+
+fail:
+ return err;
+}
+
+static int tegra_dsi_init_panel(struct tegra_dc *dc,
+ struct tegra_dc_dsi_data *dsi)
+{
+ u32 i;
+ int err;
+
+ err = 0;
+ for (i = 0; i < dsi->info.n_init_cmd; i++) {
+ struct tegra_dsi_cmd *cur_cmd;
+ cur_cmd = &dsi->info.dsi_init_cmd[i];
+
+ if (cur_cmd->cmd_type == TEGRA_DSI_DELAY_MS)
+ mdelay(cur_cmd->sp_len_dly.delay_ms);
+ else {
+ err = tegra_dsi_write_data(dc, dsi,
+ cur_cmd->pdata,
+ cur_cmd->data_id,
+ cur_cmd->sp_len_dly.data_len);
+ if (err < 0)
+ break;
+ }
+ }
+ return err;
+}
+
+static void tegra_dc_dsi_enable(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+ int err;
+
+ tegra_dc_io_start(dc);
+ mutex_lock(&dsi->lock);
+
+ err = tegra_dsi_init_hw(dc, dsi);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev, "dsi: not able to init dsi hardware\n");
+ return;
+ }
+
+ err = tegra_dsi_set_to_lp_mode(dc, dsi);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev, "dsi: not able to set to lp mode\n");
+ return;
+ }
+
+ err = tegra_dsi_init_panel(dc, dsi);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev, "dsi: error while sending dsi cmd\n");
+ return;
+ }
+
+ err = tegra_dsi_set_to_hs_mode(dc, dsi);
+ if (err < 0) {
+ dev_err(&dc->ndev->dev,
+ "dsi: not able to set to hs mode\n");
+ return;
+ }
+
+ if (dsi->status.driven == DSI_DRIVEN_MODE_DC) {
+ tegra_dsi_start_dc_stream(dc, dsi);
+ }
+
+ mutex_unlock(&dsi->lock);
+ tegra_dc_io_end(dc);
+}
+
+static void _tegra_dc_dsi_init(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+
+ tegra_dsi_init_sw(dc, dsi);
+ /* TODO: Configure the CSI pad configuration */
+}
+
+static int tegra_dc_dsi_cp_init_cmd(struct tegra_dsi_cmd* src,
+ struct tegra_dsi_cmd* dst, u16 n_cmd)
+{
+ u16 i;
+ u16 len;
+
+ memcpy(dst, src, sizeof(*dst) * n_cmd);
+
+ for (i = 0; i < n_cmd; i++)
+ if (src[i].pdata) {
+ len = sizeof(*src[i].pdata) * src[i].sp_len_dly.data_len;
+ dst[i].pdata = kzalloc(len, GFP_KERNEL);
+ if (!dst[i].pdata)
+ goto free_cmd_pdata;
+ memcpy(dst[i].pdata, src[i].pdata, len);
+ }
+
+ return 0;
+
+free_cmd_pdata:
+ for (--i; i >=0; i--)
+ if (dst[i].pdata)
+ kfree(dst[i].pdata);
+ return -ENOMEM;
+}
+
+static int tegra_dc_dsi_cp_info(struct tegra_dc_dsi_data* dsi,
+ struct tegra_dsi_out* p_dsi)
+{
+ struct tegra_dsi_cmd* pcmd;
+ int err;
+
+ pcmd = kzalloc(sizeof(*pcmd) * p_dsi->n_init_cmd, GFP_KERNEL);
+ if (!pcmd)
+ return -ENOMEM;
+
+ if (p_dsi->n_data_lanes > MAX_DSI_DATA_LANES) {
+ err = -EINVAL;
+ goto err_free_pcmd;
+ }
+
+ memcpy(&dsi->info, p_dsi, sizeof(dsi->info));
+
+ err = tegra_dc_dsi_cp_init_cmd(p_dsi->dsi_init_cmd,
+ pcmd, p_dsi->n_init_cmd);
+ if (err < 0)
+ goto err_free_pcmd;
+
+ dsi->info.dsi_init_cmd = pcmd;
+
+ if (!dsi->info.panel_reset_timeout_msec)
+ dsi->info.panel_reset_timeout_msec = DEFAULT_PANEL_RESET_TIMEOUT;
+
+ if (!dsi->info.panel_buffer_size_byte)
+ dsi->info.panel_buffer_size_byte = DEFAULT_PANEL_BUFFER_BYTE;
+
+ if (!dsi->info.max_panel_freq_khz)
+ dsi->info.max_panel_freq_khz = DEFAULT_MAX_DSI_PHY_CLK_KHZ;
+
+ if (!dsi->info.lp_cmd_mode_freq_khz)
+ dsi->info.lp_cmd_mode_freq_khz = DEFAULT_LP_CMD_MODE_CLK_KHZ;
+
+ dsi->controller_index = 0;
+
+ /* host mode is for testing only*/
+ dsi->driven_mode = TEGRA_DSI_DRIVEN_BY_DC;
+
+ return 0;
+
+err_free_pcmd:
+ kfree(pcmd);
+ return err;
+}
+
+static int tegra_dc_dsi_init(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi;
+ struct resource *res;
+ struct resource *base_res;
+ void __iomem *base;
+ struct clk *dc_clk = NULL;
+ struct clk *dsi_clk = NULL;
+ int err;
+
+ err = 0;
+
+ dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
+ if (!dsi)
+ return -ENOMEM;
+
+ res = nvhost_get_resource_byname(dc->ndev, IORESOURCE_MEM,
+ "dsi_regs");
+ if (!res) {
+ dev_err(&dc->ndev->dev, "dsi: no mem resource\n");
+ err = -ENOENT;
+ goto err_free_dsi;
+ }
+
+ base_res = request_mem_region(res->start, resource_size(res),
+ dc->ndev->name);
+ if (!base_res) {
+ dev_err(&dc->ndev->dev, "dsi: request_mem_region failed\n");
+ err = -EBUSY;
+ goto err_free_dsi;
+ }
+
+ base = ioremap(res->start, resource_size(res));
+ if (!base) {
+ dev_err(&dc->ndev->dev, "dsi: registers can't be mapped\n");
+ err = -EBUSY;
+ goto err_release_regs;
+ }
+
+ dsi_clk = clk_get(&dc->ndev->dev, "dsi");
+ if (IS_ERR_OR_NULL(dsi_clk)) {
+ dev_err(&dc->ndev->dev, "dsi: can't get clock\n");
+ err = -EBUSY;
+ goto err_release_regs;
+ }
+
+ dc_clk = clk_get_sys(dev_name(&dc->ndev->dev), NULL);
+ if (IS_ERR_OR_NULL(dc_clk)) {
+ dev_err(&dc->ndev->dev, "dsi: dc clock %s unavailable\n",
+ dev_name(&dc->ndev->dev));
+ err = -EBUSY;
+ goto err_clk_put;
+ }
+
+ if (!dc->pdata->default_out->dsi) {
+ dev_err(&dc->ndev->dev, "dsi: dsi data not available\n");
+ goto err_dsi_data;
+ }
+
+ err = tegra_dc_dsi_cp_info(dsi, dc->pdata->default_out->dsi);
+ if (err < 0)
+ goto err_dsi_data;
+
+ mutex_init(&dsi->lock);
+ dsi->dc = dc;
+ dsi->base = base;
+ dsi->base_res = base_res;
+ dsi->dc_clk = dc_clk;
+ dsi->dsi_clk = dsi_clk;
+
+ tegra_dc_set_outdata(dc, dsi);
+ _tegra_dc_dsi_init(dc);
+
+ return 0;
+
+err_dsi_data:
+err_clk_put:
+ clk_put(dsi->dsi_clk);
+err_release_regs:
+ release_resource(base_res);
+err_free_dsi:
+ kfree(dsi);
+
+ return err;
+}
+
+static void tegra_dc_dsi_destroy(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+ u16 i;
+ u32 val;
+
+ mutex_lock(&dsi->lock);
+
+ /* free up the pdata*/
+ for(i = 0; i < dsi->info.n_init_cmd; i++){
+ if(dsi->info.dsi_init_cmd[i].pdata)
+ kfree(dsi->info.dsi_init_cmd[i].pdata);
+ }
+ kfree(dsi->info.dsi_init_cmd);
+
+ /* Disable dc stream*/
+ if(dsi->status.driven == DSI_DRIVEN_MODE_DC)
+ tegra_dsi_stop_dc_stream(dc, dsi);
+
+ /* Disable dsi phy clock*/
+ if(dsi->status.clk_out == DSI_PHYCLK_OUT_EN)
+ tegra_dsi_hs_clk_out_disable(dc, dsi);
+
+ val = DSI_POWER_CONTROL_LEG_DSI_ENABLE(TEGRA_DSI_DISABLE);
+ tegra_dsi_writel(dsi, val, DSI_POWER_CONTROL);
+
+ iounmap(dsi->base);
+ release_resource(dsi->base_res);
+
+ clk_put(dsi->dc_clk);
+ clk_put(dsi->dsi_clk);
+
+ mutex_unlock(&dsi->lock);
+
+ mutex_destroy(dsi->lock);
+ kfree(dsi);
+}
+
+static void tegra_dc_dsi_disable(struct tegra_dc *dc)
+{
+ struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc);
+
+ mutex_lock(&dsi->lock);
+
+ if (dsi->status.driven == DSI_DRIVEN_MODE_DC)
+ tegra_dsi_stop_dc_stream(dc, dsi);
+
+ if (dsi->status.clk_out == DSI_PHYCLK_OUT_EN)
+ tegra_dsi_hs_clk_out_disable(dc, dsi);
+
+ mutex_unlock(&dsi->lock);
+
+ dev_err(&dc->ndev->dev, "dsi: disable\n");
+}
+
+struct tegra_dc_out_ops tegra_dc_dsi_ops = {
+ .init = tegra_dc_dsi_init,
+ .destroy = tegra_dc_dsi_destroy,
+ .enable = tegra_dc_dsi_enable,
+ .disable = tegra_dc_dsi_disable,
+};
diff --git a/drivers/video/tegra/dc/dsi.h b/drivers/video/tegra/dc/dsi.h
new file mode 100644
index 000000000000..dbbb357319f9
--- /dev/null
+++ b/drivers/video/tegra/dc/dsi.h
@@ -0,0 +1,272 @@
+/*
+ * drivers/video/tegra/dc/dsi.h
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
+#define __DRIVERS_VIDEO_TEGRA_DC_DSI_H__
+
+/* source of video data */
+enum{
+ TEGRA_DSI_VIDEO_DRIVEN_BY_DC,
+ TEGRA_DSI_VIDEO_DRIVEN_BY_HOST,
+};
+
+/* Max number of data lanes supported */
+#define MAX_DSI_DATA_LANES 2
+/* Default Peripheral reset timeout */
+#define DSI_PR_TO_VALUE 0x2000
+
+/* DCS commands for command mode */
+#define DSI_ENTER_PARTIAL_MODE 0x12
+#define DSI_SET_PIXEL_FORMAT 0x3A
+#define DSI_AREA_COLOR_MODE 0x4C
+#define DSI_SET_PARTIAL_AREA 0x30
+#define DSI_SET_PAGE_ADDRESS 0x2B
+#define DSI_SET_ADDRESS_MODE 0x36
+#define DSI_SET_COLUMN_ADDRESS 0x2A
+#define DSI_WRITE_MEMORY_START 0x2C
+#define DSI_WRITE_MEMORY_CONTINUE 0x3C
+#define DSI_MAX_COMMAND_DELAY_USEC 250000
+#define DSI_COMMAND_DELAY_STEPS_USEC 10
+
+/* End of Transmit command for HS mode */
+#define DSI_CMD_HS_EOT_PACKAGE 0x000F0F08
+
+/* Delay required after issuing the trigger*/
+#define DSI_COMMAND_COMPLETION_DELAY_USEC 5
+
+#define DSI_DELAY_FOR_READ_FIFO 5
+
+/* Dsi virtual channel bit position, refer to the DSI specs */
+#define DSI_VIR_CHANNEL_BIT_POSITION 6
+
+/* DSI packet commands from Host to peripherals */
+enum {
+ dsi_command_v_sync_start = 0x01,
+ dsi_command_v_sync_end = 0x11,
+ dsi_command_h_sync_start = 0x21,
+ dsi_command_h_sync_end = 0x31,
+ dsi_command_end_of_transaction = 0x08,
+ dsi_command_blanking = 0x19,
+ dsi_command_null_packet = 0x09,
+ dsi_command_h_active_length_16bpp = 0x0E,
+ dsi_command_h_active_length_18bpp = 0x1E,
+ dsi_command_h_active_length_18bpp_np = 0x2E,
+ dsi_command_h_active_length_24bpp = 0x3E,
+ dsi_command_h_sync_active = dsi_command_blanking,
+ dsi_command_h_back_porch = dsi_command_blanking,
+ dsi_command_h_front_porch = dsi_command_blanking,
+ dsi_command_writ_no_param = 0x05,
+ dsi_command_long_write = 0x39,
+ dsi_command_max_return_pkt_size = 0x37,
+ dsi_command_generic_read_request_with_2_param = 0x24,
+ dsi_command_dcs_read_with_no_params = 0x06,
+};
+
+/* Maximum polling time for reading the dsi status register */
+#define DSI_STATUS_POLLING_DURATION_USEC 100000
+#define DSI_STATUS_POLLING_DELAY_USEC 100
+
+/*
+ * Horizontal Sync Blank Packet Over head
+ * DSI_overhead = size_of(HS packet header)
+ * + size_of(BLANK packet header) + size_of(checksum)
+ * DSI_overhead = 4 + 4 + 2 = 10
+ */
+#define DSI_HSYNC_BLNK_PKT_OVERHEAD 10
+
+/*
+ * Horizontal Front Porch Packet Overhead
+ * DSI_overhead = size_of(checksum)
+ * + size_of(BLANK packet header) + size_of(checksum)
+ * DSI_overhead = 2 + 4 + 2 = 8
+ */
+#define DSI_HFRONT_PORCH_PKT_OVERHEAD 8
+
+/*
+ * Horizontal Back Porch Packet
+ * DSI_overhead = size_of(HE packet header)
+ * + size_of(BLANK packet header) + size_of(checksum)
+ * + size_of(RGB packet header)
+ * DSI_overhead = 4 + 4 + 2 + 4 = 14
+ */
+#define DSI_HBACK_PORCH_PKT_OVERHEAD 14
+
+/* Additional Hs TX timeout margin */
+#define DSI_HTX_TO_MARGIN 720
+
+#define DSI_CYCLE_COUNTER_VALUE 512
+
+#define DSI_LRXH_TO_VALUE 0x2000
+
+/* Turn around timeout terminal count */
+#define DSI_TA_TO_VALUE 0x2000
+
+/* Turn around timeout tally */
+#define DSI_TA_TALLY_VALUE 0x0
+/* LP Rx timeout tally */
+#define DSI_LRXH_TALLY_VALUE 0x0
+/* HS Tx Timeout tally */
+#define DSI_HTX_TALLY_VALUE 0x0
+
+/* DSI Power control settle time 10 micro seconds */
+#define DSI_POWER_CONTROL_SETTLE_TIME_US 10
+
+#define DSI_HOST_FIFO_DEPTH 64
+#define DSI_VIDEO_FIFO_DEPTH 480
+#define DSI_READ_FIFO_DEPTH (32 << 2)
+
+#define NUMOF_BIT_PER_BYTE 8
+#define DEFAULT_LP_CMD_MODE_CLK_KHZ 10000
+#define DEFAULT_MAX_DSI_PHY_CLK_KHZ (500*1000)
+#define DEFAULT_PANEL_RESET_TIMEOUT 2
+#define DEFAULT_PANEL_BUFFER_BYTE 512
+
+/*
+ * TODO: are DSI_HOST_DSI_CONTROL_CRC_RESET(RESET_CRC) and
+ * DSI_HOST_DSI_CONTROL_HOST_TX_TRIG_SRC(IMMEDIATE) required for everyone?
+ */
+#define HOST_DSI_CTRL_COMMON \
+ (DSI_HOST_DSI_CONTROL_PHY_CLK_DIV(DSI_PHY_CLK_DIV1) | \
+ DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(NORMAL) | \
+ DSI_HOST_DSI_CONTROL_PERIPH_RESET(TEGRA_DSI_DISABLE) | \
+ DSI_HOST_DSI_CONTROL_RAW_DATA(TEGRA_DSI_DISABLE) | \
+ DSI_HOST_DSI_CONTROL_IMM_BTA(TEGRA_DSI_DISABLE) | \
+ DSI_HOST_DSI_CONTROL_PKT_BTA(TEGRA_DSI_DISABLE) | \
+ DSI_HOST_DSI_CONTROL_CS_ENABLE(TEGRA_DSI_ENABLE) | \
+ DSI_HOST_DSI_CONTROL_ECC_ENABLE(TEGRA_DSI_ENABLE))
+
+#define HOST_DSI_CTRL_HOST_DRIVEN \
+ (DSI_HOST_DSI_CONTROL_CRC_RESET(RESET_CRC) | \
+ DSI_HOST_DSI_CONTROL_HOST_TX_TRIG_SRC(IMMEDIATE) | \
+ DSI_HOST_DSI_CONTROL_PKT_WR_FIFO_SEL(HOST_ONLY))
+
+#define HOST_DSI_CTRL_DC_DRIVEN 0
+
+#define HOST_DSI_CTRL_VIDEO_MODE \
+ (DSI_HOST_DSI_CONTROL_PKT_WR_FIFO_SEL(VIDEO_HOST))
+
+#define HOST_DSI_CTRL_CMD_MODE \
+ (DSI_HOST_DSI_CONTROL_PKT_WR_FIFO_SEL(HOST_ONLY))
+
+
+#define DSI_CTRL_HOST_DRIVEN (DSI_CONTROL_VID_ENABLE(TEGRA_DSI_DISABLE) | \
+ DSI_CONTROL_HOST_ENABLE(TEGRA_DSI_ENABLE))
+
+#define DSI_CTRL_DC_DRIVEN (DSI_CONTROL_VID_TX_TRIG_SRC(SOL) | \
+ DSI_CONTROL_VID_ENABLE(TEGRA_DSI_ENABLE) | \
+ DSI_CONTROL_HOST_ENABLE(TEGRA_DSI_DISABLE))
+
+#define DSI_CTRL_CMD_MODE (DSI_CONTROL_VID_DCS_ENABLE(TEGRA_DSI_ENABLE))
+
+#define DSI_CTRL_VIDEO_MODE (DSI_CONTROL_VID_DCS_ENABLE(TEGRA_DSI_DISABLE))
+
+
+enum {
+ CMD_VS = 0x01,
+ CMD_VE = 0x11,
+
+ CMD_HS = 0x21,
+ CMD_HE = 0x31,
+
+ CMD_EOT = 0x08,
+ CMD_NULL = 0x09,
+ CMD_BLNK = 0x19,
+ CMD_LONGW = 0x39,
+
+ CMD_RGB = 0x00,
+ CMD_RGB_16BPP = 0x0E,
+ CMD_RGB_18BPP = 0x1E,
+ CMD_RGB_18BPPNP = 0x2E,
+ CMD_RGB_24BPP = 0x3E,
+};
+
+#define PKT_ID0(id) DSI_PKT_SEQ_0_LO_PKT_00_ID(id) | \
+ DSI_PKT_SEQ_1_LO_PKT_10_EN(TEGRA_DSI_ENABLE)
+#define PKT_LEN0(len) DSI_PKT_SEQ_0_LO_PKT_00_SIZE(len)
+
+#define PKT_ID1(id) DSI_PKT_SEQ_0_LO_PKT_01_ID(id) | \
+ DSI_PKT_SEQ_1_LO_PKT_11_EN(TEGRA_DSI_ENABLE)
+#define PKT_LEN1(len) DSI_PKT_SEQ_0_LO_PKT_01_SIZE(len)
+
+#define PKT_ID2(id) DSI_PKT_SEQ_0_LO_PKT_02_ID(id) | \
+ DSI_PKT_SEQ_1_LO_PKT_12_EN(TEGRA_DSI_ENABLE)
+#define PKT_LEN2(len) DSI_PKT_SEQ_0_LO_PKT_02_SIZE(len)
+
+#define PKT_ID3(id) DSI_PKT_SEQ_0_HI_PKT_03_ID(id) | \
+ DSI_PKT_SEQ_1_HI_PKT_13_EN(TEGRA_DSI_ENABLE)
+#define PKT_LEN3(len) DSI_PKT_SEQ_0_HI_PKT_03_SIZE(len)
+
+#define PKT_ID4(id) DSI_PKT_SEQ_0_HI_PKT_04_ID(id) | \
+ DSI_PKT_SEQ_1_HI_PKT_14_EN(TEGRA_DSI_ENABLE)
+#define PKT_LEN4(len) DSI_PKT_SEQ_0_HI_PKT_04_SIZE(len)
+
+#define PKT_ID5(id) DSI_PKT_SEQ_0_HI_PKT_05_ID(id) | \
+ DSI_PKT_SEQ_1_HI_PKT_15_EN(TEGRA_DSI_ENABLE)
+#define PKT_LEN5(len) DSI_PKT_SEQ_0_HI_PKT_05_SIZE(len)
+
+#define PKT_LP DSI_PKT_SEQ_0_LO_SEQ_0_FORCE_LP(TEGRA_DSI_ENABLE)
+
+#define NUMOF_PKT_SEQ 12
+
+
+/* Macros for calculating the phy timings */
+#define T_HSEXIT_DEFAULT(clkns) (100 / ((clkns) * 8) + 1)
+#define T_HSTRAIL_DEFAULT(clkns) (3 + max((8 * (clkns)), \
+ (60 + 4 * (clkns))) / ((clkns) * 8) + 1)
+#define T_HSPREPR_ORG(clkns) ((65 + 5 * (clkns)) / ((clkns) * 8))
+#define T_HSPREPR_DEFAULT(clkns) ((T_HSPREPR_ORG(clkns) == 0) ? \
+ 1 : T_HSPREPR_ORG(clkns))
+#define T_DATZERO_DEFAULT(clkns) ((145 + 5 * (clkns)) / ((clkns) * 8) +1)
+
+#define T_CLKTRAIL_DEFAULT(clkns) (60 / ((clkns) * 8) + 1)
+#define T_CLKPOST_DEFAULT(clkns) ((60 + 52 * (clkns)) / ((clkns) * 8) +1)
+#define T_CLKZERO_DEFAULT(clkns) (170 / ((clkns) * 8) + 1)
+#define T_TLPX_ORG(clkns) (50 / ((clkns) * 8) + 1)
+#define T_TLPX_DEFAULT(clkns) ((T_TLPX_ORG(clkns) == 0) ? \
+ 1 : T_TLPX_ORG(clkns))
+
+#define T_CLKPRE_DEFAULT(clkns) 1
+#define T_CLKPREPARE_DEFAULT(clkns) 4
+
+/* Minimum ULPM wakeup time as per the spec is 1msec */
+#define T_WAKEUP_DEFAULT(clkns) (2*1000*1000 / (clkns))
+
+#define DSI_CYCLE_COUNTER_VALUE 512
+
+/* Defines the DSI phy timing parameters */
+struct dsi_phy_timing_inclk
+{
+ unsigned t_hsdexit;
+ unsigned t_hstrail;
+ unsigned t_hsprepr;
+ unsigned t_datzero;
+
+ unsigned t_clktrail;
+ unsigned t_clkpost;
+ unsigned t_clkzero;
+ unsigned t_tlpx;
+
+ unsigned t_clkpre;
+ unsigned t_clkprepare;
+ unsigned t_wakeup;
+
+ unsigned t_taget;
+ unsigned t_tasure;
+ unsigned t_tago;
+
+};
+
+#endif
diff --git a/drivers/video/tegra/dc/dsi_regs.h b/drivers/video/tegra/dc/dsi_regs.h
new file mode 100644
index 000000000000..7625f93c40d3
--- /dev/null
+++ b/drivers/video/tegra/dc/dsi_regs.h
@@ -0,0 +1,336 @@
+/*
+ * drivers/video/tegra/dc/dsi_regs.h
+ *
+ * Copyright (c) 2011, NVIDIA Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
+#define __DRIVERS_VIDEO_TEGRA_DC_DSI_REG_H__
+
+enum {
+ TEGRA_DSI_DISABLE,
+ TEGRA_DSI_ENABLE,
+};
+
+/* These are word offsets from base (not byte offsets) */
+#define DSI_INCR_SYNCPT 0x00
+#define DSI_INCR_SYNCPT_CNTRL 0x01
+#define DSI_INCR_SYNCPT_ERROR 0x02
+#define DSI_CTXSW 0x08
+#define DSI_RD_DATA 0x09
+#define DSI_WR_DATA 0x0a
+
+#define DSI_POWER_CONTROL 0x0b
+#define DSI_POWER_CONTROL_LEG_DSI_ENABLE(x) (((x) & 0x1) << 0)
+
+#define DSI_INT_ENABLE 0x0c
+#define DSI_INT_STATUS 0x0d
+#define DSI_INT_MASK 0x0e
+
+#define DSI_HOST_DSI_CONTROL 0x0f
+enum {
+ RESET_CRC = 1,
+};
+#define DSI_HOST_CONTROL_FIFO_STAT_RESET(x) (((x) & 0x1) << 21)
+#define DSI_HOST_DSI_CONTROL_CRC_RESET(x) (((x) & 0x1) << 20)
+enum {
+ DSI_PHY_CLK_DIV1,
+ DSI_PHY_CLK_DIV2,
+};
+#define DSI_HOST_DSI_CONTROL_PHY_CLK_DIV(x) (((x) & 0x7) << 16)
+enum {
+ SOL,
+ FIFO_LEVEL,
+ IMMEDIATE,
+};
+#define DSI_HOST_DSI_CONTROL_HOST_TX_TRIG_SRC(x) (((x) & 0x3) << 12)
+enum {
+ NORMAL,
+ ENTER_ULPM,
+ EXIT_ULPM,
+};
+#define DSI_HOST_DSI_CONTROL_ULTRA_LOW_POWER(x) (((x) & 0x3) << 8)
+#define DSI_HOST_DSI_CONTROL_PERIPH_RESET(x) (((x) & 0x1) << 7)
+#define DSI_HOST_DSI_CONTROL_RAW_DATA(x) (((x) & 0x1) << 6)
+enum {
+ TEGRA_DSI_LOW,
+ TEGRA_DSI_HIGH,
+};
+#define DSI_HOST_DSI_CONTROL_HIGH_SPEED_TRANS(x) (((x) & 0x1) << 5)
+enum {
+ HOST_ONLY,
+ VIDEO_HOST,
+};
+#define DSI_HOST_DSI_CONTROL_PKT_WR_FIFO_SEL(x) (((x) & 0x1) << 4)
+#define DSI_HOST_DSI_CONTROL_IMM_BTA(x) (((x) & 0x1) << 3)
+#define DSI_HOST_DSI_CONTROL_PKT_BTA(x) (((x) & 0x1) << 2)
+#define DSI_HOST_DSI_CONTROL_CS_ENABLE(x) (((x) & 0x1) << 1)
+#define DSI_HOST_DSI_CONTROL_ECC_ENABLE(x) (((x) & 0x1) << 0)
+
+#define DSI_CONTROL 0x10
+#define DSI_CONTROL_DBG_ENABLE(x) (((x) & 0x1) << 31)
+enum {
+ CONTINUOUS,
+ TX_ONLY,
+};
+#define DSI_CONTROL_HS_CLK_CTRL(x) (((x) & 0x1) << 20)
+#define DSI_CONTROL_VIRTUAL_CHANNEL(x) (((x) & 0x3) << 16)
+#define DSI_CONTROL_DATA_FORMAT(x) (((x) & 0x3) << 12)
+#define DSI_CONTROL_VID_TX_TRIG_SRC(x) (((x) & 0x3) << 8)
+#define DSI_CONTROL_NUM_DATA_LANES(x) (((x) & 0x3) << 4)
+#define DSI_CONTROL_VID_DCS_ENABLE(x) (((x) & 0x1) << 3)
+#define DSI_CONTROL_VID_SOURCE(x) (((x) & 0x1) << 2)
+#define DSI_CONTROL_VID_ENABLE(x) (((x) & 0x1) << 1)
+#define DSI_CONTROL_HOST_ENABLE(x) (((x) & 0x1) << 0)
+
+#define DSI_SOL_DELAY 0x11
+#define DSI_SOL_DELAY_SOL_DELAY(x) (((x) & 0xffff) << 0)
+
+#define DSI_MAX_THRESHOLD 0x12
+#define DSI_MAX_THRESHOLD_MAX_THRESHOLD(x) (((x) & 0xffff) << 0)
+
+#define DSI_TRIGGER 0x13
+#define DSI_TRIGGER_HOST_TRIGGER(x) (((x) & 0x1) << 1)
+#define DSI_TRIGGER_VID_TRIGGER(x) (((x) & 0x1) << 0)
+
+#define DSI_TX_CRC 0x14
+#define DSI_TX_CRC_TX_CRC(x) (((x) & 0xffffffff) << 0)
+
+#define DSI_STATUS 0x15
+#define DSI_STATUS_IDLE(x) (((x) & 0x1) << 10)
+#define DSI_STATUS_LB_UNDERFLOW(x) (((x) & 0x1) << 9)
+#define DSI_STATUS_LB_OVERFLOW(x) (((x) & 0x1) << 8)
+#define DSI_STATUS_RD_FIFO_COUNT(x) (((x) & 0x1f) << 0)
+
+#define DSI_INIT_SEQ_CONTROL 0x1a
+#define DSI_INIT_SEQ_CONTROL_DSI_FRAME_INIT_BYTE_COUNT(x) \
+ (((x) & 0x3f) << 8)
+#define DSI_INIT_SEQ_CONTROL_DSI_SEND_INIT_SEQUENCE(x) \
+ (((x) & 0xff) << 0)
+
+#define DSI_INIT_SEQ_DATA_0 0x1b
+#define DSI_INIT_SEQ_DATA_1 0x1c
+#define DSI_INIT_SEQ_DATA_2 0x1d
+#define DSI_INIT_SEQ_DATA_3 0x1e
+
+#define DSI_PKT_SEQ_0_LO 0x23
+#define DSI_PKT_SEQ_0_LO_SEQ_0_FORCE_LP(x) (((x) & 0x1) << 30)
+#define DSI_PKT_SEQ_0_LO_PKT_02_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_0_LO_PKT_02_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_0_LO_PKT_02_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_0_LO_PKT_01_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_0_LO_PKT_01_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_0_LO_PKT_01_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_0_LO_PKT_00_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_0_LO_PKT_00_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_0_LO_PKT_00_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_0_HI 0x24
+#define DSI_PKT_SEQ_0_HI_PKT_05_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_0_HI_PKT_05_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_0_HI_PKT_05_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_0_HI_PKT_04_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_0_HI_PKT_04_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_0_HI_PKT_04_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_0_HI_PKT_03_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_0_HI_PKT_03_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_0_HI_PKT_03_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_1_LO 0x25
+#define DSI_PKT_SEQ_1_LO_SEQ_1_FORCE_LP(x) (((x) & 0x1) << 30)
+#define DSI_PKT_SEQ_1_LO_PKT_12_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_1_LO_PKT_12_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_1_LO_PKT_12_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_1_LO_PKT_11_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_1_LO_PKT_11_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_1_LO_PKT_11_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_1_LO_PKT_10_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_1_LO_PKT_10_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_1_LO_PKT_10_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_1_HI 0x26
+#define DSI_PKT_SEQ_1_HI_PKT_15_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_1_HI_PKT_15_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_1_HI_PKT_15_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_1_HI_PKT_14_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_1_HI_PKT_14_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_1_HI_PKT_14_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_1_HI_PKT_13_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_1_HI_PKT_13_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_1_HI_PKT_13_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_2_LO 0x27
+#define DSI_PKT_SEQ_2_LO_SEQ_2_FORCE_LP(x) (((x) & 0x1) << 30)
+#define DSI_PKT_SEQ_2_LO_PKT_22_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_2_LO_PKT_22_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_2_LO_PKT_22_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_2_LO_PKT_21_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_2_LO_PKT_21_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_2_LO_PKT_21_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_2_LO_PKT_20_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_2_LO_PKT_20_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_2_LO_PKT_20_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_2_HI 0x28
+#define DSI_PKT_SEQ_2_HI_PKT_25_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_2_HI_PKT_25_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_2_HI_PKT_25_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_2_HI_PKT_24_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_2_HI_PKT_24_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_2_HI_PKT_24_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_2_HI_PKT_23_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_2_HI_PKT_23_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_2_HI_PKT_23_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_3_LO 0x29
+#define DSI_PKT_SEQ_3_LO_SEQ_3_FORCE_LP(x) (((x) & 0x1) << 30)
+#define DSI_PKT_SEQ_3_LO_PKT_32_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_3_LO_PKT_32_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_3_LO_PKT_32_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_3_LO_PKT_31_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_3_LO_PKT_31_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_3_LO_PKT_31_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_3_LO_PKT_30_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_3_LO_PKT_30_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_3_LO_PKT_30_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_3_HI 0x2a
+#define DSI_PKT_SEQ_3_HI_PKT_35_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_3_HI_PKT_35_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_3_HI_PKT_35_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_3_HI_PKT_34_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_3_HI_PKT_34_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_3_HI_PKT_34_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_3_HI_PKT_33_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_3_HI_PKT_33_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_3_HI_PKT_33_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_4_LO 0x2b
+#define DSI_PKT_SEQ_4_LO_SEQ_4_FORCE_LP(x) (((x) & 0x1) << 30)
+#define DSI_PKT_SEQ_4_LO_PKT_42_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_4_LO_PKT_42_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_4_LO_PKT_42_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_4_LO_PKT_41_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_4_LO_PKT_41_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_4_LO_PKT_41_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_4_LO_PKT_40_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_4_LO_PKT_40_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_4_LO_PKT_40_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_4_HI 0x2c
+#define DSI_PKT_SEQ_4_HI_PKT_45_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_4_HI_PKT_45_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_4_HI_PKT_45_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_4_HI_PKT_44_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_4_HI_PKT_44_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_4_HI_PKT_44_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_4_HI_PKT_43_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_4_HI_PKT_43_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_4_HI_PKT_43_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_5_LO 0x2d
+#define DSI_PKT_SEQ_5_LO_SEQ_5_FORCE_LP(x) (((x) & 0x1) << 30)
+#define DSI_PKT_SEQ_5_LO_PKT_52_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_5_LO_PKT_52_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_5_LO_PKT_52_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_5_LO_PKT_51_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_5_LO_PKT_51_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_5_LO_PKT_51_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_5_LO_PKT_50_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_5_LO_PKT_50_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_5_LO_PKT_50_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_PKT_SEQ_5_HI 0x2e
+#define DSI_PKT_SEQ_5_HI_PKT_55_EN(x) (((x) & 0x1) << 29)
+#define DSI_PKT_SEQ_5_HI_PKT_55_ID(x) (((x) & 0x3f) << 23)
+#define DSI_PKT_SEQ_5_HI_PKT_55_SIZE(x) (((x) & 0x7) << 20)
+#define DSI_PKT_SEQ_5_HI_PKT_54_EN(x) (((x) & 0x1) << 19)
+#define DSI_PKT_SEQ_5_HI_PKT_54_ID(x) (((x) & 0x3f) << 13)
+#define DSI_PKT_SEQ_5_HI_PKT_54_SIZE(x) (((x) & 0x7) << 10)
+#define DSI_PKT_SEQ_5_HI_PKT_53_EN(x) (((x) & 0x1) << 9)
+#define DSI_PKT_SEQ_5_HI_PKT_53_ID(x) (((x) & 0x3f) << 3)
+#define DSI_PKT_SEQ_5_HI_PKT_53_SIZE(x) (((x) & 0x7) << 0)
+
+#define DSI_DCS_CMDS 0x33
+#define DSI_DCS_CMDS_LT5_DCS_CMD(x) (((x) & 0xff) << 8)
+#define DSI_DCS_CMDS_LT3_DCS_CMD(x) (((x) & 0xff) << 0)
+
+#define DSI_PKT_LEN_0_1 0x34
+#define DSI_PKT_LEN_0_1_LENGTH_1(x) (((x) & 0xffff) << 16)
+#define DSI_PKT_LEN_0_1_LENGTH_0(x) (((x) & 0xffff) << 0)
+
+#define DSI_PKT_LEN_2_3 0x35
+#define DSI_PKT_LEN_2_3_LENGTH_3(x) (((x) & 0xffff) << 16)
+#define DSI_PKT_LEN_2_3_LENGTH_2(x) (((x) & 0xffff) << 0)
+
+
+#define DSI_PKT_LEN_4_5 0x36
+#define DSI_PKT_LEN_4_5_LENGTH_5(x) (((x) & 0xffff) << 16)
+#define DSI_PKT_LEN_4_5_LENGTH_4(x) (((x) & 0xffff) << 0)
+
+#define DSI_PKT_LEN_6_7 0x37
+#define DSI_PKT_LEN_6_7_LENGTH_7(x) (((x) & 0xffff) << 16)
+#define DSI_PKT_LEN_6_7_LENGTH_6(x) (((x) & 0xffff) << 0)
+
+#define DSI_PHY_TIMING_0 0x3c
+#define DSI_PHY_TIMING_0_THSDEXIT(x) (((x) & 0xff) << 24)
+#define DSI_PHY_TIMING_0_THSTRAIL(x) (((x) & 0xff) << 16)
+#define DSI_PHY_TIMING_0_TDATZERO(x) (((x) & 0xff) << 8)
+#define DSI_PHY_TIMING_0_THSPREPR(x) (((x) & 0xff) << 0)
+
+#define DSI_PHY_TIMING_1 0x3d
+#define DSI_PHY_TIMING_1_TCLKTRAIL(x) (((x) & 0xff) << 24)
+#define DSI_PHY_TIMING_1_TCLKPOST(x) (((x) & 0xff) << 16)
+#define DSI_PHY_TIMING_1_TCLKZERO(x) (((x) & 0xff) << 8)
+#define DSI_PHY_TIMING_1_TTLPX(x) (((x) & 0xff) << 0)
+
+#define DSI_PHY_TIMING_2 0x3e
+#define DSI_PHY_TIMING_2_TCLKPREPARE(x) (((x) & 0xff) << 16)
+#define DSI_PHY_TIMING_2_TCLKPRE(x) (((x) & 0xff) << 8)
+#define DSI_PHY_TIMING_2_TWAKEUP(x) (((x) & 0xff) << 0)
+
+#define DSI_BTA_TIMING 0x3f
+#define DSI_BTA_TIMING_TTAGET(x) (((x) & 0xff) << 16)
+#define DSI_BTA_TIMING_TTASURE(x) (((x) & 0xff) << 8)
+#define DSI_BTA_TIMING_TTAGO(x) (((x) & 0xff) << 0)
+
+
+#define DSI_TIMEOUT_0 0x44
+#define DSI_TIMEOUT_0_LRXH_TO(x) (((x) & 0xffff) << 16)
+#define DSI_TIMEOUT_0_HTX_TO(x) (((x) & 0xffff) << 0)
+
+#define DSI_TIMEOUT_1 0x45
+#define DSI_TIMEOUT_1_PR_TO(x) (((x) & 0xffff) << 16)
+#define DSI_TIMEOUT_1_TA_TO(x) (((x) & 0xffff) << 0)
+
+#define DSI_TO_TALLY 0x46
+enum {
+ IN_RESET,
+ READY,
+};
+#define DSI_TO_TALLY_P_RESET_STATUS(x) (((x) & 0x1) << 24)
+#define DSI_TO_TALLY_TA_TALLY(x) (((x) & 0xff) << 16)
+#define DSI_TO_TALLY_LRXH_TALLY(x) (((x) & 0xff) << 8)
+#define DSI_TO_TALLY_HTX_TALLY(x) (((x) & 0xff) << 0)
+
+#define DSI_PAD_CONTROL 0x4b
+#define DSI_PAD_CONTROL_PAD_PULLDN_ENAB(x) (((x) & 0x1) << 28)
+#define DSI_PAD_CONTROL_PAD_PDIO_CLK(x) (((x) & 0x1) << 18)
+#define DSI_PAD_CONTROL_PAD_PDIO(x) (((x) & 0x3) << 16)
+
+#define DSI_PAD_CONTROL_CD 0x4c
+#define DSI_PAD_CD_STATUS 0x4d
+#define DSI_VID_MODE_CONTROL 0x4e
+
+#endif
+