drm: msm: dsi-staging: add support for DSI controller v2.0.0
Add a separate DSI controller h/w driver to support DSI
controller v2.0.0. This includes reorganizing the DSI controller
programming sequence which is common between DSI v1.4.0 and
DSI v2.0.0 to a common DSI h/w driver file.
CRs-Fixed: 2008002
Change-Id: I6e2821b6874924c8fbaca888f940e8ad34ee90ec
Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
Signed-off-by: Shashank Babu Chinta Venkata <sbchin@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 5c29e67..70e3be2 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -98,7 +98,9 @@
dsi-staging/dsi_pwr.o \
dsi-staging/dsi_phy.o \
dsi-staging/dsi_phy_hw_v4_0.o \
+ dsi-staging/dsi_ctrl_hw_cmn.o \
dsi-staging/dsi_ctrl_hw_1_4.o \
+ dsi-staging/dsi_ctrl_hw_2_0.o \
dsi-staging/dsi_ctrl.o \
dsi-staging/dsi_catalog.o \
dsi-staging/dsi_drm.o \
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index 07503f5..83daed1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -18,56 +18,74 @@
#include "dsi_catalog.h"
/**
- * dsi_catalog_14_init() - catalog init for dsi controller v1.4
+ * dsi_catalog_cmn_init() - catalog init for dsi controller v1.4
*/
-static void dsi_catalog_14_init(struct dsi_ctrl_hw *ctrl)
+static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
+ enum dsi_ctrl_version version)
{
- ctrl->ops.host_setup = dsi_ctrl_hw_14_host_setup;
- ctrl->ops.setup_lane_map = dsi_ctrl_hw_14_setup_lane_map;
- ctrl->ops.video_engine_en = dsi_ctrl_hw_14_video_engine_en;
- ctrl->ops.video_engine_setup = dsi_ctrl_hw_14_video_engine_setup;
- ctrl->ops.set_video_timing = dsi_ctrl_hw_14_set_video_timing;
- ctrl->ops.cmd_engine_setup = dsi_ctrl_hw_14_cmd_engine_setup;
- ctrl->ops.setup_cmd_stream = dsi_ctrl_hw_14_setup_cmd_stream;
- ctrl->ops.ctrl_en = dsi_ctrl_hw_14_ctrl_en;
- ctrl->ops.cmd_engine_en = dsi_ctrl_hw_14_cmd_engine_en;
- ctrl->ops.phy_sw_reset = dsi_ctrl_hw_14_phy_sw_reset;
- ctrl->ops.soft_reset = dsi_ctrl_hw_14_soft_reset;
- ctrl->ops.kickoff_command = dsi_ctrl_hw_14_kickoff_command;
- ctrl->ops.kickoff_fifo_command = dsi_ctrl_hw_14_kickoff_fifo_command;
- ctrl->ops.reset_cmd_fifo = dsi_ctrl_hw_14_reset_cmd_fifo;
- ctrl->ops.trigger_command_dma = dsi_ctrl_hw_14_trigger_command_dma;
- ctrl->ops.ulps_ops.ulps_request = dsi_ctrl_hw_14_ulps_request;
- ctrl->ops.ulps_ops.ulps_exit = dsi_ctrl_hw_14_ulps_exit;
- ctrl->ops.ulps_ops.wait_for_lane_idle = dsi_ctrl_hw_wait_for_lane_idle;
- ctrl->ops.ulps_ops.get_lanes_in_ulps = dsi_ctrl_hw_14_get_lanes_in_ulps;
- ctrl->ops.clamp_enable = dsi_ctrl_hw_14_clamp_enable;
- ctrl->ops.clamp_disable = dsi_ctrl_hw_14_clamp_disable;
- ctrl->ops.get_interrupt_status = dsi_ctrl_hw_14_get_interrupt_status;
- ctrl->ops.get_error_status = dsi_ctrl_hw_14_get_error_status;
- ctrl->ops.clear_error_status = dsi_ctrl_hw_14_clear_error_status;
+ /* common functions */
+ ctrl->ops.host_setup = dsi_ctrl_hw_cmn_host_setup;
+ ctrl->ops.video_engine_en = dsi_ctrl_hw_cmn_video_engine_en;
+ ctrl->ops.video_engine_setup = dsi_ctrl_hw_cmn_video_engine_setup;
+ ctrl->ops.set_video_timing = dsi_ctrl_hw_cmn_set_video_timing;
+ ctrl->ops.cmd_engine_setup = dsi_ctrl_hw_cmn_cmd_engine_setup;
+ ctrl->ops.setup_cmd_stream = dsi_ctrl_hw_cmn_setup_cmd_stream;
+ ctrl->ops.ctrl_en = dsi_ctrl_hw_cmn_ctrl_en;
+ ctrl->ops.cmd_engine_en = dsi_ctrl_hw_cmn_cmd_engine_en;
+ ctrl->ops.phy_sw_reset = dsi_ctrl_hw_cmn_phy_sw_reset;
+ ctrl->ops.soft_reset = dsi_ctrl_hw_cmn_soft_reset;
+ ctrl->ops.kickoff_command = dsi_ctrl_hw_cmn_kickoff_command;
+ ctrl->ops.kickoff_fifo_command = dsi_ctrl_hw_cmn_kickoff_fifo_command;
+ ctrl->ops.reset_cmd_fifo = dsi_ctrl_hw_cmn_reset_cmd_fifo;
+ ctrl->ops.trigger_command_dma = dsi_ctrl_hw_cmn_trigger_command_dma;
+ ctrl->ops.get_interrupt_status = dsi_ctrl_hw_cmn_get_interrupt_status;
+ ctrl->ops.get_error_status = dsi_ctrl_hw_cmn_get_error_status;
+ ctrl->ops.clear_error_status = dsi_ctrl_hw_cmn_clear_error_status;
ctrl->ops.clear_interrupt_status =
- dsi_ctrl_hw_14_clear_interrupt_status;
+ dsi_ctrl_hw_cmn_clear_interrupt_status;
ctrl->ops.enable_status_interrupts =
- dsi_ctrl_hw_14_enable_status_interrupts;
+ dsi_ctrl_hw_cmn_enable_status_interrupts;
ctrl->ops.enable_error_interrupts =
- dsi_ctrl_hw_14_enable_error_interrupts;
+ dsi_ctrl_hw_cmn_enable_error_interrupts;
ctrl->ops.video_test_pattern_setup =
- dsi_ctrl_hw_14_video_test_pattern_setup;
+ dsi_ctrl_hw_cmn_video_test_pattern_setup;
ctrl->ops.cmd_test_pattern_setup =
- dsi_ctrl_hw_14_cmd_test_pattern_setup;
- ctrl->ops.test_pattern_enable = dsi_ctrl_hw_14_test_pattern_enable;
+ dsi_ctrl_hw_cmn_cmd_test_pattern_setup;
+ ctrl->ops.test_pattern_enable = dsi_ctrl_hw_cmn_test_pattern_enable;
ctrl->ops.trigger_cmd_test_pattern =
- dsi_ctrl_hw_14_trigger_cmd_test_pattern;
- ctrl->ops.reg_dump_to_buffer = dsi_ctrl_hw_14_reg_dump_to_buffer;
-}
+ dsi_ctrl_hw_cmn_trigger_cmd_test_pattern;
+ ctrl->ops.clear_phy0_ln_err = dsi_ctrl_hw_dln0_phy_err;
+ ctrl->ops.phy_reset_config = dsi_ctrl_hw_cmn_phy_reset_config;
-/**
- * dsi_catalog_20_init() - catalog init for dsi controller v2.0
- */
-static void dsi_catalog_20_init(struct dsi_ctrl_hw *ctrl)
-{
- set_bit(DSI_CTRL_CPHY, ctrl->feature_map);
+ switch (version) {
+ case DSI_CTRL_VERSION_1_4:
+ ctrl->ops.setup_lane_map = dsi_ctrl_hw_14_setup_lane_map;
+ ctrl->ops.ulps_ops.ulps_request = dsi_ctrl_hw_14_ulps_request;
+ ctrl->ops.ulps_ops.ulps_exit = dsi_ctrl_hw_14_ulps_exit;
+ ctrl->ops.wait_for_lane_idle =
+ dsi_ctrl_hw_14_wait_for_lane_idle;
+ ctrl->ops.ulps_ops.get_lanes_in_ulps =
+ dsi_ctrl_hw_14_get_lanes_in_ulps;
+ ctrl->ops.clamp_enable = dsi_ctrl_hw_14_clamp_enable;
+ ctrl->ops.clamp_disable = dsi_ctrl_hw_14_clamp_disable;
+ ctrl->ops.reg_dump_to_buffer =
+ dsi_ctrl_hw_14_reg_dump_to_buffer;
+ break;
+ case DSI_CTRL_VERSION_2_0:
+ ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map;
+ ctrl->ops.wait_for_lane_idle =
+ dsi_ctrl_hw_20_wait_for_lane_idle;
+ ctrl->ops.reg_dump_to_buffer =
+ dsi_ctrl_hw_20_reg_dump_to_buffer;
+ ctrl->ops.ulps_ops.ulps_request = NULL;
+ ctrl->ops.ulps_ops.ulps_exit = NULL;
+ ctrl->ops.ulps_ops.get_lanes_in_ulps = NULL;
+ ctrl->ops.clamp_enable = NULL;
+ ctrl->ops.clamp_disable = NULL;
+ break;
+ default:
+ break;
+ }
}
/**
@@ -102,10 +120,8 @@
switch (version) {
case DSI_CTRL_VERSION_1_4:
- dsi_catalog_14_init(ctrl);
- break;
case DSI_CTRL_VERSION_2_0:
- dsi_catalog_20_init(ctrl);
+ dsi_catalog_cmn_init(ctrl, version);
break;
default:
return -ENOTSUPP;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 03bf905..b4625d5 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -60,43 +60,69 @@
void dsi_phy_hw_v4_0_idle_on(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg);
void dsi_phy_hw_v4_0_idle_off(struct dsi_phy_hw *phy);
-/* Definitions for 1.4 controller hardware driver */
-void dsi_ctrl_hw_14_host_setup(struct dsi_ctrl_hw *ctrl,
+/* DSI controller common ops */
+u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints);
+void dsi_ctrl_hw_cmn_enable_status_interrupts(struct dsi_ctrl_hw *ctrl,
+ u32 ints);
+
+u64 dsi_ctrl_hw_cmn_get_error_status(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors);
+void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
+ u64 errors);
+
+void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
+ enum dsi_test_pattern type,
+ u32 init_val);
+void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
+ enum dsi_test_pattern type,
+ u32 init_val,
+ u32 stream_id);
+void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable);
+void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl,
+ u32 stream_id);
+
+void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl,
struct dsi_host_common_cfg *config);
-void dsi_ctrl_hw_14_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on);
-void dsi_ctrl_hw_14_video_engine_setup(struct dsi_ctrl_hw *ctrl,
+void dsi_ctrl_hw_cmn_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on);
+void dsi_ctrl_hw_cmn_video_engine_setup(struct dsi_ctrl_hw *ctrl,
struct dsi_host_common_cfg *common_cfg,
struct dsi_video_engine_cfg *cfg);
-void dsi_ctrl_hw_14_set_video_timing(struct dsi_ctrl_hw *ctrl,
+void dsi_ctrl_hw_cmn_set_video_timing(struct dsi_ctrl_hw *ctrl,
struct dsi_mode_info *mode);
-void dsi_ctrl_hw_14_cmd_engine_setup(struct dsi_ctrl_hw *ctrl,
+void dsi_ctrl_hw_cmn_cmd_engine_setup(struct dsi_ctrl_hw *ctrl,
struct dsi_host_common_cfg *common_cfg,
struct dsi_cmd_engine_cfg *cfg);
-void dsi_ctrl_hw_14_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on);
-void dsi_ctrl_hw_14_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on);
+void dsi_ctrl_hw_cmn_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on);
+void dsi_ctrl_hw_cmn_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on);
-void dsi_ctrl_hw_14_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
+void dsi_ctrl_hw_cmn_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
u32 width_in_pixels,
u32 h_stride,
u32 height_in_lines,
u32 vc_id);
-void dsi_ctrl_hw_14_phy_sw_reset(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_soft_reset(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_phy_sw_reset(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_soft_reset(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl,
- struct dsi_lane_mapping *lane_map);
-void dsi_ctrl_hw_14_kickoff_command(struct dsi_ctrl_hw *ctrl,
+void dsi_ctrl_hw_cmn_kickoff_command(struct dsi_ctrl_hw *ctrl,
struct dsi_ctrl_cmd_dma_info *cmd,
u32 flags);
-void dsi_ctrl_hw_14_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl,
+void dsi_ctrl_hw_cmn_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl,
struct dsi_ctrl_cmd_dma_fifo_info *cmd,
u32 flags);
-void dsi_ctrl_hw_14_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_trigger_command_dma(struct dsi_ctrl_hw *ctrl);
-int dsi_ctrl_hw_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
+void dsi_ctrl_hw_cmn_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl,
+ bool enable);
+
+/* Definitions specific to 1.4 DSI controller hardware */
+int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
+void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl,
+ struct dsi_lane_map *lane_map);
void dsi_ctrl_hw_14_ulps_request(struct dsi_ctrl_hw *ctrl, u32 lanes);
void dsi_ctrl_hw_14_ulps_exit(struct dsi_ctrl_hw *ctrl, u32 lanes);
u32 dsi_ctrl_hw_14_get_lanes_in_ulps(struct dsi_ctrl_hw *ctrl);
@@ -108,27 +134,16 @@
void dsi_ctrl_hw_14_clamp_disable(struct dsi_ctrl_hw *ctrl,
u32 lanes,
bool disable_ulps);
-u32 dsi_ctrl_hw_14_get_interrupt_status(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints);
-void dsi_ctrl_hw_14_enable_status_interrupts(struct dsi_ctrl_hw *ctrl,
- u32 ints);
-
-u64 dsi_ctrl_hw_14_get_error_status(struct dsi_ctrl_hw *ctrl);
-void dsi_ctrl_hw_14_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors);
-void dsi_ctrl_hw_14_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
- u64 errors);
-
-void dsi_ctrl_hw_14_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val);
-void dsi_ctrl_hw_14_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val,
- u32 stream_id);
-void dsi_ctrl_hw_14_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable);
-void dsi_ctrl_hw_14_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl,
- u32 stream_id);
ssize_t dsi_ctrl_hw_14_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl,
char *buf,
u32 size);
+
+/* Definitions specific to 2.0 DSI controller hardware */
+void dsi_ctrl_hw_20_setup_lane_map(struct dsi_ctrl_hw *ctrl,
+ struct dsi_lane_map *lane_map);
+int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
+ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl,
+ char *buf,
+ u32 size);
+
#endif /* _DSI_CATALOG_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 3e0e9f6..10e91ac 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -155,6 +155,7 @@
return rc;
}
+ if (dsi_ctrl->hw.ops.reg_dump_to_buffer)
len = dsi_ctrl->hw.ops.reg_dump_to_buffer(&dsi_ctrl->hw,
buf, SZ_4K);
@@ -162,6 +163,7 @@
rc = dsi_ctrl->clk_cb.dsi_clk_cb(dsi_ctrl->clk_cb.priv, clk_info);
if (rc) {
pr_err("failed to disable DSI core clocks\n");
+ kfree(buf);
return rc;
}
@@ -1007,12 +1009,18 @@
if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
lanes = dsi_ctrl->host_config.common_config.data_lanes;
- rc = dsi_ctrl->hw.ops.ulps_ops.wait_for_lane_idle(&dsi_ctrl->hw, lanes);
+ rc = dsi_ctrl->hw.ops.wait_for_lane_idle(&dsi_ctrl->hw, lanes);
if (rc) {
pr_err("lanes not entering idle, skip ULPS\n");
return rc;
}
+ if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request ||
+ !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) {
+ pr_debug("DSI controller ULPS ops not present\n");
+ return 0;
+ }
+
lanes |= DSI_CLOCK_LANE;
dsi_ctrl->hw.ops.ulps_ops.ulps_request(&dsi_ctrl->hw, lanes);
@@ -1032,10 +1040,19 @@
int rc = 0;
u32 ulps_lanes, lanes = 0;
+ dsi_ctrl->hw.ops.clear_phy0_ln_err(&dsi_ctrl->hw);
+
+ if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request ||
+ !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) {
+ pr_debug("DSI controller ULPS ops not present\n");
+ return 0;
+ }
+
if (dsi_ctrl->host_config.panel_mode == DSI_OP_CMD_MODE)
lanes = dsi_ctrl->host_config.common_config.data_lanes;
lanes |= DSI_CLOCK_LANE;
+
ulps_lanes = dsi_ctrl->hw.ops.ulps_ops.get_lanes_in_ulps(&dsi_ctrl->hw);
if ((lanes & ulps_lanes) != lanes)
@@ -1565,6 +1582,26 @@
return rc;
}
+/**
+ * dsi_ctrl_phy_reset_config() - Mask/unmask propagation of ahb reset signal
+ * to DSI PHY hardware.
+ * @dsi_ctrl: DSI controller handle.
+ * @enable: Mask/unmask the PHY reset signal.
+ *
+ * Return: error code.
+ */
+int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable)
+{
+ if (!dsi_ctrl) {
+ pr_err("Invalid params\n");
+ return -EINVAL;
+ }
+
+ if (dsi_ctrl->hw.ops.phy_reset_config)
+ dsi_ctrl->hw.ops.phy_reset_config(&dsi_ctrl->hw, enable);
+
+ return 0;
+}
/**
* dsi_ctrl_host_init() - Initialize DSI host hardware.
@@ -2089,12 +2126,6 @@
return -EINVAL;
}
- if (!dsi_ctrl->hw.ops.ulps_ops.ulps_request ||
- !dsi_ctrl->hw.ops.ulps_ops.ulps_exit) {
- pr_debug("DSI controller ULPS ops not present\n");
- return 0;
- }
-
mutex_lock(&dsi_ctrl->ctrl_lock);
if (enable)
@@ -2133,6 +2164,12 @@
return -EINVAL;
}
+ if (!dsi_ctrl->hw.ops.clamp_enable ||
+ !dsi_ctrl->hw.ops.clamp_disable) {
+ pr_debug("No clamp control for DSI controller\n");
+ return 0;
+ }
+
mutex_lock(&dsi_ctrl->ctrl_lock);
rc = dsi_enable_io_clamp(dsi_ctrl, enable, ulps_enabled);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index 5b3e25c..1df09b4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -319,6 +319,16 @@
int dsi_ctrl_phy_sw_reset(struct dsi_ctrl *dsi_ctrl);
/**
+ * dsi_ctrl_phy_reset_config() - Mask/unmask propagation of ahb reset signal
+ * to DSI PHY hardware.
+ * @dsi_ctrl: DSI controller handle.
+ * @enable: Mask/unmask the PHY reset signal.
+ *
+ * Return: error code.
+ */
+int dsi_ctrl_phy_reset_config(struct dsi_ctrl *dsi_ctrl, bool enable);
+
+/**
* dsi_ctrl_host_init() - Initialize DSI host hardware.
* @dsi_ctrl: DSI controller handle.
*
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index a25c780..009795a 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -215,15 +215,7 @@
struct dsi_ctrl_hw;
-struct ulps_config_ops {
- /**
- * wait_for_lane_idle() - wait for DSI lanes to go to idle state
- * @ctrl: Pointer to the controller host hardware.
- * @lanes: ORed list of lanes (enum dsi_data_lanes) which need
- * to be checked to be in idle state.
- */
- int (*wait_for_lane_idle)(struct dsi_ctrl_hw *ctrl, u32 lanes);
-
+struct ctrl_ulps_config_ops {
/**
* ulps_request() - request ulps entry for specified lanes
* @ctrl: Pointer to the controller host hardware.
@@ -256,7 +248,6 @@
* Return: List of lanes in ULPS state.
*/
u32 (*get_lanes_in_ulps)(struct dsi_ctrl_hw *ctrl);
-
};
/**
@@ -371,7 +362,7 @@
* lanes and physical lanes.
*/
void (*setup_lane_map)(struct dsi_ctrl_hw *ctrl,
- struct dsi_lane_mapping *lane_map);
+ struct dsi_lane_map *lane_map);
/**
* kickoff_command() - transmits commands stored in memory
@@ -427,7 +418,22 @@
u8 *rd_buf,
u32 total_read_len);
- struct ulps_config_ops ulps_ops;
+ /**
+ * wait_for_lane_idle() - wait for DSI lanes to go to idle state
+ * @ctrl: Pointer to the controller host hardware.
+ * @lanes: ORed list of lanes (enum dsi_data_lanes) which need
+ * to be checked to be in idle state.
+ */
+ int (*wait_for_lane_idle)(struct dsi_ctrl_hw *ctrl, u32 lanes);
+
+ struct ctrl_ulps_config_ops ulps_ops;
+
+ /**
+ * clamp_enable() - enable DSI clamps
+ * @ctrl: Pointer to the controller host hardware.
+ * @lanes: ORed list of lanes which need to have clamps released.
+ * @enable_ulps: ulps state.
+ */
/**
* clamp_enable() - enable DSI clamps to keep PHY driving a stable link
@@ -443,13 +449,22 @@
* clamp_disable() - disable DSI clamps
* @ctrl: Pointer to the controller host hardware.
* @lanes: ORed list of lanes which need to have clamps released.
- * @disable_ulps: TODO:??
+ * @disable_ulps: ulps state.
*/
void (*clamp_disable)(struct dsi_ctrl_hw *ctrl,
u32 lanes,
bool disable_ulps);
/**
+ * phy_reset_config() - Disable/enable propagation of reset signal
+ * from ahb domain to DSI PHY
+ * @ctrl: Pointer to the controller host hardware.
+ * @enable: True to mask the reset signal, false to unmask
+ */
+ void (*phy_reset_config)(struct dsi_ctrl_hw *ctrl,
+ bool enable);
+
+ /**
* get_interrupt_status() - returns the interrupt status
* @ctrl: Pointer to the controller host hardware.
*
@@ -541,6 +556,12 @@
void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable);
/**
+ * clear_phy0_ln_err() - clear DSI PHY lane-0 errors
+ * @ctrl: Pointer to the controller host hardware.
+ */
+ void (*clear_phy0_ln_err)(struct dsi_ctrl_hw *ctrl);
+
+ /**
* trigger_cmd_test_pattern() - trigger a command mode frame update with
* test pattern
* @ctrl: Pointer to the controller host hardware.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
index e367db3..37473b8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_1_4.c
@@ -17,585 +17,28 @@
#include <linux/iopoll.h>
#include "dsi_ctrl_hw.h"
-#include "dsi_ctrl_reg_1_4.h"
+#include "dsi_ctrl_reg.h"
#include "dsi_hw.h"
#define MMSS_MISC_CLAMP_REG_OFF 0x0014
-/* Unsupported formats default to RGB888 */
-static const u8 cmd_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
- 0x6, 0x7, 0x8, 0x8, 0x0, 0x3, 0x4 };
-static const u8 video_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
- 0x0, 0x1, 0x2, 0x3, 0x3, 0x3, 0x3 };
-
-
/**
- * dsi_setup_trigger_controls() - setup dsi trigger configurations
- * @ctrl: Pointer to the controller host hardware.
- * @cfg: DSI host configuration that is common to both video and
- * command modes.
- */
-static void dsi_setup_trigger_controls(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *cfg)
-{
- u32 reg = 0;
- const u8 trigger_map[DSI_TRIGGER_MAX] = {
- 0x0, 0x2, 0x1, 0x4, 0x5, 0x6 };
-
- reg |= (cfg->te_mode == DSI_TE_ON_EXT_PIN) ? BIT(31) : 0;
- reg |= (trigger_map[cfg->dma_cmd_trigger] & 0x7);
- reg |= (trigger_map[cfg->mdp_cmd_trigger] & 0x7) << 4;
- DSI_W32(ctrl, DSI_TRIG_CTRL, reg);
-}
-
-/**
- * dsi_ctrl_hw_14_host_setup() - setup dsi host configuration
- * @ctrl: Pointer to the controller host hardware.
- * @cfg: DSI host configuration that is common to both video and
- * command modes.
- */
-void dsi_ctrl_hw_14_host_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *cfg)
-{
- u32 reg_value = 0;
-
- dsi_setup_trigger_controls(ctrl, cfg);
-
- /* Setup clocking timing controls */
- reg_value = ((cfg->t_clk_post & 0x3F) << 8);
- reg_value |= (cfg->t_clk_pre & 0x3F);
- DSI_W32(ctrl, DSI_CLKOUT_TIMING_CTRL, reg_value);
-
- /* EOT packet control */
- reg_value = cfg->append_tx_eot ? 1 : 0;
- reg_value |= (cfg->ignore_rx_eot ? (1 << 4) : 0);
- DSI_W32(ctrl, DSI_EOT_PACKET_CTRL, reg_value);
-
- /* Turn on dsi clocks */
- DSI_W32(ctrl, DSI_CLK_CTRL, 0x23F);
-
- /* Setup DSI control register */
- reg_value = 0;
- reg_value |= (cfg->en_crc_check ? BIT(24) : 0);
- reg_value |= (cfg->en_ecc_check ? BIT(20) : 0);
- reg_value |= BIT(8); /* Clock lane */
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(7) : 0);
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(6) : 0);
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(5) : 0);
- reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(4) : 0);
-
- DSI_W32(ctrl, DSI_CTRL, reg_value);
-
- pr_debug("[DSI_%d]Host configuration complete\n", ctrl->index);
-}
-
-/**
- * phy_sw_reset() - perform a soft reset on the PHY.
- * @ctrl: Pointer to the controller host hardware.
- */
-void dsi_ctrl_hw_14_phy_sw_reset(struct dsi_ctrl_hw *ctrl)
-{
- DSI_W32(ctrl, DSI_PHY_SW_RESET, 0x1);
- udelay(1000);
- DSI_W32(ctrl, DSI_PHY_SW_RESET, 0x0);
- udelay(100);
-
- pr_debug("[DSI_%d] phy sw reset done\n", ctrl->index);
-}
-
-/**
- * soft_reset() - perform a soft reset on DSI controller
- * @ctrl: Pointer to the controller host hardware.
- *
- * The video, command and controller engines will be disable before the
- * reset is triggered. These engines will not be enabled after the reset
- * is complete. Caller must re-enable the engines.
- *
- * If the reset is done while MDP timing engine is turned on, the video
- * enigne should be re-enabled only during the vertical blanking time.
- */
-void dsi_ctrl_hw_14_soft_reset(struct dsi_ctrl_hw *ctrl)
-{
- u32 reg = 0;
- u32 reg_ctrl = 0;
-
- /* Clear DSI_EN, VIDEO_MODE_EN, CMD_MODE_EN */
- reg_ctrl = DSI_R32(ctrl, DSI_CTRL);
- DSI_W32(ctrl, DSI_CTRL, reg_ctrl & ~0x7);
-
- /* Force enable PCLK, BYTECLK, AHBM_HCLK */
- reg = DSI_R32(ctrl, DSI_CLK_CTRL);
- reg |= 0x23F;
- DSI_W32(ctrl, DSI_CLK_CTRL, reg);
-
- /* Trigger soft reset */
- DSI_W32(ctrl, DSI_SOFT_RESET, 0x1);
- udelay(1);
- DSI_W32(ctrl, DSI_SOFT_RESET, 0x0);
-
- /* Disable force clock on */
- reg &= ~(BIT(20) | BIT(11));
- DSI_W32(ctrl, DSI_CLK_CTRL, reg);
-
- /* Re-enable DSI controller */
- DSI_W32(ctrl, DSI_CTRL, reg_ctrl);
- pr_debug("[DSI_%d] ctrl soft reset done\n", ctrl->index);
-}
-
-/**
- * set_video_timing() - set up the timing for video frame
- * @ctrl: Pointer to controller host hardware.
- * @mode: Video mode information.
- *
- * Set up the video timing parameters for the DSI video mode operation.
- */
-void dsi_ctrl_hw_14_set_video_timing(struct dsi_ctrl_hw *ctrl,
- struct dsi_mode_info *mode)
-{
- u32 reg = 0;
- u32 hs_start = 0;
- u32 hs_end, active_h_start, active_h_end, h_total;
- u32 vs_start = 0, vs_end = 0;
- u32 vpos_start = 0, vpos_end, active_v_start, active_v_end, v_total;
-
- hs_end = mode->h_sync_width;
- active_h_start = mode->h_sync_width + mode->h_back_porch;
- active_h_end = active_h_start + mode->h_active;
- h_total = (mode->h_sync_width + mode->h_back_porch + mode->h_active +
- mode->h_front_porch) - 1;
-
- vpos_end = mode->v_sync_width;
- active_v_start = mode->v_sync_width + mode->v_back_porch;
- active_v_end = active_v_start + mode->v_active;
- v_total = (mode->v_sync_width + mode->v_back_porch + mode->v_active +
- mode->v_front_porch) - 1;
-
- reg = ((active_h_end & 0xFFFF) << 16) | (active_h_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_H, reg);
-
- reg = ((active_v_end & 0xFFFF) << 16) | (active_v_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_V, reg);
-
- reg = ((v_total & 0xFFFF) << 16) | (h_total & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_TOTAL, reg);
-
- reg = ((hs_end & 0xFFFF) << 16) | (hs_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_HSYNC, reg);
-
- reg = ((vs_end & 0xFFFF) << 16) | (vs_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC, reg);
-
- reg = ((vpos_end & 0xFFFF) << 16) | (vpos_start & 0xFFFF);
- DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC_VPOS, reg);
-
- /* TODO: HS TIMER value? */
- DSI_W32(ctrl, DSI_HS_TIMER_CTRL, 0x3FD08);
- DSI_W32(ctrl, DSI_MISR_VIDEO_CTRL, 0x10100);
- DSI_W32(ctrl, DSI_DSI_TIMING_FLUSH, 0x1);
- pr_debug("[DSI_%d] ctrl video parameters updated\n", ctrl->index);
-}
-
-/**
- * setup_cmd_stream() - set up parameters for command pixel streams
- * @ctrl: Pointer to controller host hardware.
- * @width_in_pixels: Width of the stream in pixels.
- * @h_stride: Horizontal stride in bytes.
- * @height_inLines: Number of lines in the stream.
- * @vc_id: stream_id
- *
- * Setup parameters for command mode pixel stream size.
- */
-void dsi_ctrl_hw_14_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
- u32 width_in_pixels,
- u32 h_stride,
- u32 height_in_lines,
- u32 vc_id)
-{
- u32 reg = 0;
-
- reg = (h_stride + 1) << 16;
- reg |= (vc_id & 0x3) << 8;
- reg |= 0x39; /* packet data type */
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_CTRL, reg);
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_CTRL, reg);
-
- reg = (height_in_lines << 16) | width_in_pixels;
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_TOTAL, reg);
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_TOTAL, reg);
-}
-
-/**
- * video_engine_setup() - Setup dsi host controller for video mode
- * @ctrl: Pointer to controller host hardware.
- * @common_cfg: Common configuration parameters.
- * @cfg: Video mode configuration.
- *
- * Set up DSI video engine with a specific configuration. Controller and
- * video engine are not enabled as part of this function.
- */
-void dsi_ctrl_hw_14_video_engine_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_video_engine_cfg *cfg)
-{
- u32 reg = 0;
-
- reg |= (cfg->last_line_interleave_en ? BIT(31) : 0);
- reg |= (cfg->pulse_mode_hsa_he ? BIT(28) : 0);
- reg |= (cfg->hfp_lp11_en ? BIT(24) : 0);
- reg |= (cfg->hbp_lp11_en ? BIT(20) : 0);
- reg |= (cfg->hsa_lp11_en ? BIT(16) : 0);
- reg |= (cfg->eof_bllp_lp11_en ? BIT(15) : 0);
- reg |= (cfg->bllp_lp11_en ? BIT(12) : 0);
- reg |= (cfg->traffic_mode & 0x3) << 8;
- reg |= (cfg->vc_id & 0x3);
- reg |= (video_mode_format_map[common_cfg->dst_format] & 0x3) << 4;
- DSI_W32(ctrl, DSI_VIDEO_MODE_CTRL, reg);
-
- reg = (common_cfg->swap_mode & 0x7) << 12;
- reg |= (common_cfg->bit_swap_red ? BIT(0) : 0);
- reg |= (common_cfg->bit_swap_green ? BIT(4) : 0);
- reg |= (common_cfg->bit_swap_blue ? BIT(8) : 0);
- DSI_W32(ctrl, DSI_VIDEO_MODE_DATA_CTRL, reg);
- /* Enable Timing double buffering */
- DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1);
-
-
- pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index);
-}
-
-/**
- * cmd_engine_setup() - setup dsi host controller for command mode
- * @ctrl: Pointer to the controller host hardware.
- * @common_cfg: Common configuration parameters.
- * @cfg: Command mode configuration.
- *
- * Setup DSI CMD engine with a specific configuration. Controller and
- * command engine are not enabled as part of this function.
- */
-void dsi_ctrl_hw_14_cmd_engine_setup(struct dsi_ctrl_hw *ctrl,
- struct dsi_host_common_cfg *common_cfg,
- struct dsi_cmd_engine_cfg *cfg)
-{
- u32 reg = 0;
-
- reg = (cfg->max_cmd_packets_interleave & 0xF) << 20;
- reg |= (common_cfg->bit_swap_red ? BIT(4) : 0);
- reg |= (common_cfg->bit_swap_green ? BIT(8) : 0);
- reg |= (common_cfg->bit_swap_blue ? BIT(12) : 0);
- reg |= cmd_mode_format_map[common_cfg->dst_format];
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL, reg);
-
- reg = DSI_R32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2);
- reg |= BIT(16);
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2, reg);
-
- reg = cfg->wr_mem_start & 0xFF;
- reg |= (cfg->wr_mem_continue & 0xFF) << 8;
- reg |= (cfg->insert_dcs_command ? BIT(16) : 0);
- DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL, reg);
-
- pr_debug("[DSI_%d] Cmd engine setup done\n", ctrl->index);
-}
-
-/**
- * video_engine_en() - enable DSI video engine
- * @ctrl: Pointer to controller host hardware.
- * @on: Enable/disabel video engine.
- */
-void dsi_ctrl_hw_14_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on)
-{
- u32 reg = 0;
-
- /* Set/Clear VIDEO_MODE_EN bit */
- reg = DSI_R32(ctrl, DSI_CTRL);
- if (on)
- reg |= BIT(1);
- else
- reg &= ~BIT(1);
-
- DSI_W32(ctrl, DSI_CTRL, reg);
-
- pr_debug("[DSI_%d] Video engine = %d\n", ctrl->index, on);
-}
-
-/**
- * ctrl_en() - enable DSI controller engine
- * @ctrl: Pointer to the controller host hardware.
- * @on: turn on/off the DSI controller engine.
- */
-void dsi_ctrl_hw_14_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on)
-{
- u32 reg = 0;
-
- /* Set/Clear DSI_EN bit */
- reg = DSI_R32(ctrl, DSI_CTRL);
- if (on)
- reg |= BIT(0);
- else
- reg &= ~BIT(0);
-
- DSI_W32(ctrl, DSI_CTRL, reg);
-
- pr_debug("[DSI_%d] Controller engine = %d\n", ctrl->index, on);
-}
-
-/**
- * cmd_engine_en() - enable DSI controller command engine
- * @ctrl: Pointer to the controller host hardware.
- * @on: Turn on/off the DSI command engine.
- */
-void dsi_ctrl_hw_14_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on)
-{
- u32 reg = 0;
-
- /* Set/Clear CMD_MODE_EN bit */
- reg = DSI_R32(ctrl, DSI_CTRL);
- if (on)
- reg |= BIT(2);
- else
- reg &= ~BIT(2);
-
- DSI_W32(ctrl, DSI_CTRL, reg);
-
- pr_debug("[DSI_%d] command engine = %d\n", ctrl->index, on);
-}
-
-/**
- * setup_lane_map() - setup mapping between logical and physical lanes
+ * dsi_ctrl_hw_14_setup_lane_map() - setup mapping between
+ * logical and physical lanes
* @ctrl: Pointer to the controller host hardware.
* @lane_map: Structure defining the mapping between DSI logical
* lanes and physical lanes.
*/
void dsi_ctrl_hw_14_setup_lane_map(struct dsi_ctrl_hw *ctrl,
- struct dsi_lane_mapping *lane_map)
+ struct dsi_lane_map *lane_map)
{
- u32 reg_value = 0;
- u32 lane_number = ((lane_map->physical_lane0 * 1000)+
- (lane_map->physical_lane1 * 100) +
- (lane_map->physical_lane2 * 10) +
- (lane_map->physical_lane3));
-
- if (lane_number == 123)
- reg_value = 0;
- else if (lane_number == 3012)
- reg_value = 1;
- else if (lane_number == 2301)
- reg_value = 2;
- else if (lane_number == 1230)
- reg_value = 3;
- else if (lane_number == 321)
- reg_value = 4;
- else if (lane_number == 1032)
- reg_value = 5;
- else if (lane_number == 2103)
- reg_value = 6;
- else if (lane_number == 3210)
- reg_value = 7;
-
- DSI_W32(ctrl, DSI_LANE_SWAP_CTRL, reg_value);
+ DSI_W32(ctrl, DSI_LANE_SWAP_CTRL, lane_map->lane_map_v1);
pr_debug("[DSI_%d] Lane swap setup complete\n", ctrl->index);
}
/**
- * kickoff_command() - transmits commands stored in memory
- * @ctrl: Pointer to the controller host hardware.
- * @cmd: Command information.
- * @flags: Modifiers for command transmission.
- *
- * The controller hardware is programmed with address and size of the
- * command buffer. The transmission is kicked off if
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
- * set, caller should make a separate call to trigger_command_dma() to
- * transmit the command.
- */
-void dsi_ctrl_hw_14_kickoff_command(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_info *cmd,
- u32 flags)
-{
- u32 reg = 0;
-
- /*Set BROADCAST_EN and EMBEDDED_MODE */
- reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL);
- if (cmd->en_broadcast)
- reg |= BIT(31);
- else
- reg &= ~BIT(31);
-
- if (cmd->is_master)
- reg |= BIT(30);
- else
- reg &= ~BIT(30);
-
- if (cmd->use_lpm)
- reg |= BIT(26);
- else
- reg &= ~BIT(26);
-
- reg |= BIT(28);
- DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg);
-
- DSI_W32(ctrl, DSI_DMA_CMD_OFFSET, cmd->offset);
- DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->length & 0xFFFFFF));
-
- /* wait for writes to complete before kick off */
- wmb();
-
- if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER))
- DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
-}
-
-/**
- * kickoff_fifo_command() - transmits a command using FIFO in dsi
- * hardware.
- * @ctrl: Pointer to the controller host hardware.
- * @cmd: Command information.
- * @flags: Modifiers for command transmission.
- *
- * The controller hardware FIFO is programmed with command header and
- * payload. The transmission is kicked off if
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
- * set, caller should make a separate call to trigger_command_dma() to
- * transmit the command.
- */
-void dsi_ctrl_hw_14_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl,
- struct dsi_ctrl_cmd_dma_fifo_info *cmd,
- u32 flags)
-{
- u32 reg = 0, i = 0;
- u32 *ptr = cmd->command;
- /*
- * Set CMD_DMA_TPG_EN, TPG_DMA_FIFO_MODE and
- * CMD_DMA_PATTERN_SEL = custom pattern stored in TPG DMA FIFO
- */
- reg = (BIT(1) | BIT(2) | (0x3 << 16));
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
-
- /*
- * Program the FIFO with command buffer. Hardware requires an extra
- * DWORD (set to zero) if the length of command buffer is odd DWORDS.
- */
- for (i = 0; i < cmd->size; i += 4) {
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, *ptr);
- ptr++;
- }
-
- if ((cmd->size / 4) & 0x1)
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, 0);
-
- /*Set BROADCAST_EN and EMBEDDED_MODE */
- reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL);
- if (cmd->en_broadcast)
- reg |= BIT(31);
- else
- reg &= ~BIT(31);
-
- if (cmd->is_master)
- reg |= BIT(30);
- else
- reg &= ~BIT(30);
-
- if (cmd->use_lpm)
- reg |= BIT(26);
- else
- reg &= ~BIT(26);
-
- reg |= BIT(28);
-
- DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg);
-
- DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->size & 0xFFFFFFFF));
- /* Finish writes before command trigger */
- wmb();
-
- if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER))
- DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
-
- pr_debug("[DSI_%d]size=%d, trigger = %d\n",
- ctrl->index, cmd->size,
- (flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER) ? false : true);
-}
-
-void dsi_ctrl_hw_14_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl)
-{
- /* disable cmd dma tpg */
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, 0x0);
-
- DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x1);
- udelay(1);
- DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x0);
-}
-
-/**
- * trigger_command_dma() - trigger transmission of command buffer.
- * @ctrl: Pointer to the controller host hardware.
- *
- * This trigger can be only used if there was a prior call to
- * kickoff_command() of kickoff_fifo_command() with
- * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag.
- */
-void dsi_ctrl_hw_14_trigger_command_dma(struct dsi_ctrl_hw *ctrl)
-{
- DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
- pr_debug("[DSI_%d] CMD DMA triggered\n", ctrl->index);
-}
-
-/**
- * get_cmd_read_data() - get data read from the peripheral
- * @ctrl: Pointer to the controller host hardware.
- * @rd_buf: Buffer where data will be read into.
- * @total_read_len: Number of bytes to read.
- *
- * return: number of bytes read.
- */
-u32 dsi_ctrl_hw_14_get_cmd_read_data(struct dsi_ctrl_hw *ctrl,
- u8 *rd_buf,
- u32 read_offset,
- u32 total_read_len)
-{
- u32 *lp, *temp, data;
- int i, j = 0, cnt;
- u32 read_cnt;
- u32 rx_byte = 0;
- u32 repeated_bytes = 0;
- u8 reg[16];
- u32 pkt_size = 0;
- int buf_offset = read_offset;
-
- lp = (u32 *)rd_buf;
- temp = (u32 *)reg;
- cnt = (rx_byte + 3) >> 2;
-
- if (cnt > 4)
- cnt = 4;
-
- if (rx_byte == 4)
- read_cnt = 4;
- else
- read_cnt = pkt_size + 6;
-
- if (read_cnt > 16) {
- int bytes_shifted;
-
- bytes_shifted = read_cnt - 16;
- repeated_bytes = buf_offset - bytes_shifted;
- }
-
- for (i = cnt - 1; i >= 0; i--) {
- data = DSI_R32(ctrl, DSI_RDBK_DATA0 + i*4);
- *temp++ = ntohl(data);
- }
-
- for (i = repeated_bytes; i < 16; i++)
- rd_buf[j++] = reg[i];
-
- pr_debug("[DSI_%d] Read %d bytes\n", ctrl->index, j);
- return j;
-}
-
-
-/**
- * dsi_ctrl_hw_wait_for_lane_idle()
+ * dsi_ctrl_hw_14_wait_for_lane_idle()
* This function waits for all the active DSI lanes to be idle by polling all
* the FIFO_EMPTY bits and polling he lane status to ensure that all the lanes
* are in stop state. This function assumes that the bus clocks required to
@@ -607,7 +50,7 @@
*
* return: Error code.
*/
-int dsi_ctrl_hw_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes)
+int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes)
{
int rc = 0, val = 0;
u32 stop_state_mask = 0, fifo_empty_mask = 0;
@@ -691,17 +134,6 @@
lanes);
}
-static void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl)
-{
- u32 status = 0;
-
- status = DSI_R32(ctrl, DSI_DLN0_PHY_ERR);
- if (status & 0x011111) {
- DSI_W32(ctrl, DSI_DLN0_PHY_ERR, status);
- pr_err("%s: phy_err_status = %x\n", __func__, status);
- }
-}
-
/**
* ulps_exit() - exit ULPS on specified lanes
* @ctrl: Pointer to the controller host hardware.
@@ -715,13 +147,6 @@
{
u32 reg = 0;
- /*
- * Clear out any phy errors prior to exiting ULPS
- * This fixes certain instances where phy does not exit
- * ULPS cleanly. Also, do not print error during such cases.
- */
- dsi_ctrl_hw_dln0_phy_err(ctrl);
-
if (lanes & DSI_CLOCK_LANE)
reg = BIT(12);
if (lanes & DSI_DATA_LANE_0)
@@ -837,10 +262,6 @@
reg |= (BIT(15) << bit_shift); /* Enable clamp */
DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
- reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
- reg |= BIT(30); /* Disable PHY reset */
- DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
-
pr_debug("[DSI_%d] Clamps enabled for lanes=0x%x\n", ctrl->index,
lanes);
}
@@ -895,11 +316,6 @@
clamp_reg |= BIT(15); /* Enable clamp */
clamp_reg <<= bit_shift;
- /* Clear disable PHY reset bit */
- reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
- reg &= ~BIT(30);
- DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
-
reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
reg &= ~(clamp_reg);
DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
@@ -907,521 +323,6 @@
pr_debug("[DSI_%d] Disable clamps for lanes=%d\n", ctrl->index, lanes);
}
-/**
- * get_interrupt_status() - returns the interrupt status
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns the ORed list of interrupts(enum dsi_status_int_type) that
- * are active. This list does not include any error interrupts. Caller
- * should call get_error_status for error interrupts.
- *
- * Return: List of active interrupts.
- */
-u32 dsi_ctrl_hw_14_get_interrupt_status(struct dsi_ctrl_hw *ctrl)
-{
- u32 reg = 0;
- u32 ints = 0;
-
- reg = DSI_R32(ctrl, DSI_INT_CTRL);
-
- if (reg & BIT(0))
- ints |= DSI_CMD_MODE_DMA_DONE;
- if (reg & BIT(8))
- ints |= DSI_CMD_FRAME_DONE;
- if (reg & BIT(10))
- ints |= DSI_CMD_STREAM0_FRAME_DONE;
- if (reg & BIT(12))
- ints |= DSI_CMD_STREAM1_FRAME_DONE;
- if (reg & BIT(14))
- ints |= DSI_CMD_STREAM2_FRAME_DONE;
- if (reg & BIT(16))
- ints |= DSI_VIDEO_MODE_FRAME_DONE;
- if (reg & BIT(20))
- ints |= DSI_BTA_DONE;
- if (reg & BIT(28))
- ints |= DSI_DYN_REFRESH_DONE;
- if (reg & BIT(30))
- ints |= DSI_DESKEW_DONE;
-
- pr_debug("[DSI_%d] Interrupt status = 0x%x, INT_CTRL=0x%x\n",
- ctrl->index, ints, reg);
- return ints;
-}
-
-/**
- * clear_interrupt_status() - clears the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @ints: List of interrupts to be cleared.
- */
-void dsi_ctrl_hw_14_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints)
-{
- u32 reg = 0;
-
- if (ints & DSI_CMD_MODE_DMA_DONE)
- reg |= BIT(0);
- if (ints & DSI_CMD_FRAME_DONE)
- reg |= BIT(8);
- if (ints & DSI_CMD_STREAM0_FRAME_DONE)
- reg |= BIT(10);
- if (ints & DSI_CMD_STREAM1_FRAME_DONE)
- reg |= BIT(12);
- if (ints & DSI_CMD_STREAM2_FRAME_DONE)
- reg |= BIT(14);
- if (ints & DSI_VIDEO_MODE_FRAME_DONE)
- reg |= BIT(16);
- if (ints & DSI_BTA_DONE)
- reg |= BIT(20);
- if (ints & DSI_DYN_REFRESH_DONE)
- reg |= BIT(28);
- if (ints & DSI_DESKEW_DONE)
- reg |= BIT(30);
-
- DSI_W32(ctrl, DSI_INT_CTRL, reg);
-
- pr_debug("[DSI_%d] Clear interrupts, ints = 0x%x, INT_CTRL=0x%x\n",
- ctrl->index, ints, reg);
-}
-
-/**
- * enable_status_interrupts() - enable the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @ints: List of interrupts to be enabled.
- *
- * Enables the specified interrupts. This list will override the
- * previous interrupts enabled through this function. Caller has to
- * maintain the state of the interrupts enabled. To disable all
- * interrupts, set ints to 0.
- */
-void dsi_ctrl_hw_14_enable_status_interrupts(struct dsi_ctrl_hw *ctrl, u32 ints)
-{
- u32 reg = 0;
-
- /* Do not change value of DSI_ERROR_MASK bit */
- reg |= (DSI_R32(ctrl, DSI_INT_CTRL) & BIT(25));
- if (ints & DSI_CMD_MODE_DMA_DONE)
- reg |= BIT(1);
- if (ints & DSI_CMD_FRAME_DONE)
- reg |= BIT(9);
- if (ints & DSI_CMD_STREAM0_FRAME_DONE)
- reg |= BIT(11);
- if (ints & DSI_CMD_STREAM1_FRAME_DONE)
- reg |= BIT(13);
- if (ints & DSI_CMD_STREAM2_FRAME_DONE)
- reg |= BIT(15);
- if (ints & DSI_VIDEO_MODE_FRAME_DONE)
- reg |= BIT(17);
- if (ints & DSI_BTA_DONE)
- reg |= BIT(21);
- if (ints & DSI_DYN_REFRESH_DONE)
- reg |= BIT(29);
- if (ints & DSI_DESKEW_DONE)
- reg |= BIT(31);
-
- DSI_W32(ctrl, DSI_INT_CTRL, reg);
-
- pr_debug("[DSI_%d] Enable interrupts 0x%x, INT_CTRL=0x%x\n",
- ctrl->index, ints, reg);
-}
-
-/**
- * get_error_status() - returns the error status
- * @ctrl: Pointer to the controller host hardware.
- *
- * Returns the ORed list of errors(enum dsi_error_int_type) that are
- * active. This list does not include any status interrupts. Caller
- * should call get_interrupt_status for status interrupts.
- *
- * Return: List of active error interrupts.
- */
-u64 dsi_ctrl_hw_14_get_error_status(struct dsi_ctrl_hw *ctrl)
-{
- u32 dln0_phy_err;
- u32 fifo_status;
- u32 ack_error;
- u32 timeout_errors;
- u32 clk_error;
- u32 dsi_status;
- u64 errors = 0;
-
- dln0_phy_err = DSI_R32(ctrl, DSI_DLN0_PHY_ERR);
- if (dln0_phy_err & BIT(0))
- errors |= DSI_DLN0_ESC_ENTRY_ERR;
- if (dln0_phy_err & BIT(4))
- errors |= DSI_DLN0_ESC_SYNC_ERR;
- if (dln0_phy_err & BIT(8))
- errors |= DSI_DLN0_LP_CONTROL_ERR;
- if (dln0_phy_err & BIT(12))
- errors |= DSI_DLN0_LP0_CONTENTION;
- if (dln0_phy_err & BIT(16))
- errors |= DSI_DLN0_LP1_CONTENTION;
-
- fifo_status = DSI_R32(ctrl, DSI_FIFO_STATUS);
- if (fifo_status & BIT(7))
- errors |= DSI_CMD_MDP_FIFO_UNDERFLOW;
- if (fifo_status & BIT(10))
- errors |= DSI_CMD_DMA_FIFO_UNDERFLOW;
- if (fifo_status & BIT(18))
- errors |= DSI_DLN0_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(19))
- errors |= DSI_DLN0_HS_FIFO_UNDERFLOW;
- if (fifo_status & BIT(22))
- errors |= DSI_DLN1_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(23))
- errors |= DSI_DLN1_HS_FIFO_UNDERFLOW;
- if (fifo_status & BIT(26))
- errors |= DSI_DLN2_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(27))
- errors |= DSI_DLN2_HS_FIFO_UNDERFLOW;
- if (fifo_status & BIT(30))
- errors |= DSI_DLN3_HS_FIFO_OVERFLOW;
- if (fifo_status & BIT(31))
- errors |= DSI_DLN3_HS_FIFO_UNDERFLOW;
-
- ack_error = DSI_R32(ctrl, DSI_ACK_ERR_STATUS);
- if (ack_error & BIT(16))
- errors |= DSI_RDBK_SINGLE_ECC_ERR;
- if (ack_error & BIT(17))
- errors |= DSI_RDBK_MULTI_ECC_ERR;
- if (ack_error & BIT(20))
- errors |= DSI_RDBK_CRC_ERR;
- if (ack_error & BIT(23))
- errors |= DSI_RDBK_INCOMPLETE_PKT;
- if (ack_error & BIT(24))
- errors |= DSI_PERIPH_ERROR_PKT;
-
- timeout_errors = DSI_R32(ctrl, DSI_TIMEOUT_STATUS);
- if (timeout_errors & BIT(0))
- errors |= DSI_HS_TX_TIMEOUT;
- if (timeout_errors & BIT(4))
- errors |= DSI_LP_RX_TIMEOUT;
- if (timeout_errors & BIT(8))
- errors |= DSI_BTA_TIMEOUT;
-
- clk_error = DSI_R32(ctrl, DSI_CLK_STATUS);
- if (clk_error & BIT(16))
- errors |= DSI_PLL_UNLOCK;
-
- dsi_status = DSI_R32(ctrl, DSI_STATUS);
- if (dsi_status & BIT(31))
- errors |= DSI_INTERLEAVE_OP_CONTENTION;
-
- pr_debug("[DSI_%d] Error status = 0x%llx, phy=0x%x, fifo=0x%x",
- ctrl->index, errors, dln0_phy_err, fifo_status);
- pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n",
- ctrl->index, ack_error, timeout_errors, clk_error, dsi_status);
- return errors;
-}
-
-/**
- * clear_error_status() - clears the specified errors
- * @ctrl: Pointer to the controller host hardware.
- * @errors: List of errors to be cleared.
- */
-void dsi_ctrl_hw_14_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors)
-{
- u32 dln0_phy_err = 0;
- u32 fifo_status = 0;
- u32 ack_error = 0;
- u32 timeout_error = 0;
- u32 clk_error = 0;
- u32 dsi_status = 0;
- u32 int_ctrl = 0;
-
- if (errors & DSI_RDBK_SINGLE_ECC_ERR)
- ack_error |= BIT(16);
- if (errors & DSI_RDBK_MULTI_ECC_ERR)
- ack_error |= BIT(17);
- if (errors & DSI_RDBK_CRC_ERR)
- ack_error |= BIT(20);
- if (errors & DSI_RDBK_INCOMPLETE_PKT)
- ack_error |= BIT(23);
- if (errors & DSI_PERIPH_ERROR_PKT)
- ack_error |= BIT(24);
-
- if (errors & DSI_LP_RX_TIMEOUT)
- timeout_error |= BIT(4);
- if (errors & DSI_HS_TX_TIMEOUT)
- timeout_error |= BIT(0);
- if (errors & DSI_BTA_TIMEOUT)
- timeout_error |= BIT(8);
-
- if (errors & DSI_PLL_UNLOCK)
- clk_error |= BIT(16);
-
- if (errors & DSI_DLN0_LP0_CONTENTION)
- dln0_phy_err |= BIT(12);
- if (errors & DSI_DLN0_LP1_CONTENTION)
- dln0_phy_err |= BIT(16);
- if (errors & DSI_DLN0_ESC_ENTRY_ERR)
- dln0_phy_err |= BIT(0);
- if (errors & DSI_DLN0_ESC_SYNC_ERR)
- dln0_phy_err |= BIT(4);
- if (errors & DSI_DLN0_LP_CONTROL_ERR)
- dln0_phy_err |= BIT(8);
-
- if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW)
- fifo_status |= BIT(10);
- if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW)
- fifo_status |= BIT(7);
- if (errors & DSI_DLN0_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(18);
- if (errors & DSI_DLN1_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(22);
- if (errors & DSI_DLN2_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(26);
- if (errors & DSI_DLN3_HS_FIFO_OVERFLOW)
- fifo_status |= BIT(30);
- if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(19);
- if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(23);
- if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(27);
- if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW)
- fifo_status |= BIT(31);
-
- if (errors & DSI_INTERLEAVE_OP_CONTENTION)
- dsi_status |= BIT(31);
-
- DSI_W32(ctrl, DSI_DLN0_PHY_ERR, dln0_phy_err);
- DSI_W32(ctrl, DSI_FIFO_STATUS, fifo_status);
- DSI_W32(ctrl, DSI_ACK_ERR_STATUS, ack_error);
- DSI_W32(ctrl, DSI_TIMEOUT_STATUS, timeout_error);
- DSI_W32(ctrl, DSI_CLK_STATUS, clk_error);
- DSI_W32(ctrl, DSI_STATUS, dsi_status);
-
- int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
- int_ctrl |= BIT(24);
- DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
- pr_debug("[DSI_%d] clear errors = 0x%llx, phy=0x%x, fifo=0x%x",
- ctrl->index, errors, dln0_phy_err, fifo_status);
- pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n",
- ctrl->index, ack_error, timeout_error, clk_error, dsi_status);
-}
-
-/**
- * enable_error_interrupts() - enable the specified interrupts
- * @ctrl: Pointer to the controller host hardware.
- * @errors: List of errors to be enabled.
- *
- * Enables the specified interrupts. This list will override the
- * previous interrupts enabled through this function. Caller has to
- * maintain the state of the interrupts enabled. To disable all
- * interrupts, set errors to 0.
- */
-void dsi_ctrl_hw_14_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
- u64 errors)
-{
- u32 int_ctrl = 0;
- u32 int_mask0 = 0x7FFF3BFF;
-
- int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
- if (errors)
- int_ctrl |= BIT(25);
- else
- int_ctrl &= ~BIT(25);
-
- if (errors & DSI_RDBK_SINGLE_ECC_ERR)
- int_mask0 &= ~BIT(0);
- if (errors & DSI_RDBK_MULTI_ECC_ERR)
- int_mask0 &= ~BIT(1);
- if (errors & DSI_RDBK_CRC_ERR)
- int_mask0 &= ~BIT(2);
- if (errors & DSI_RDBK_INCOMPLETE_PKT)
- int_mask0 &= ~BIT(3);
- if (errors & DSI_PERIPH_ERROR_PKT)
- int_mask0 &= ~BIT(4);
-
- if (errors & DSI_LP_RX_TIMEOUT)
- int_mask0 &= ~BIT(5);
- if (errors & DSI_HS_TX_TIMEOUT)
- int_mask0 &= ~BIT(6);
- if (errors & DSI_BTA_TIMEOUT)
- int_mask0 &= ~BIT(7);
-
- if (errors & DSI_PLL_UNLOCK)
- int_mask0 &= ~BIT(28);
-
- if (errors & DSI_DLN0_LP0_CONTENTION)
- int_mask0 &= ~BIT(24);
- if (errors & DSI_DLN0_LP1_CONTENTION)
- int_mask0 &= ~BIT(25);
- if (errors & DSI_DLN0_ESC_ENTRY_ERR)
- int_mask0 &= ~BIT(21);
- if (errors & DSI_DLN0_ESC_SYNC_ERR)
- int_mask0 &= ~BIT(22);
- if (errors & DSI_DLN0_LP_CONTROL_ERR)
- int_mask0 &= ~BIT(23);
-
- if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(9);
- if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(11);
- if (errors & DSI_DLN0_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(16);
- if (errors & DSI_DLN1_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(17);
- if (errors & DSI_DLN2_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(18);
- if (errors & DSI_DLN3_HS_FIFO_OVERFLOW)
- int_mask0 &= ~BIT(19);
- if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(26);
- if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(27);
- if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(29);
- if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW)
- int_mask0 &= ~BIT(30);
-
- if (errors & DSI_INTERLEAVE_OP_CONTENTION)
- int_mask0 &= ~BIT(8);
-
- DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
- DSI_W32(ctrl, DSI_ERR_INT_MASK0, int_mask0);
-
- pr_debug("[DSI_%d] enable errors = 0x%llx, int_mask0=0x%x\n",
- ctrl->index, errors, int_mask0);
-}
-
-/**
- * video_test_pattern_setup() - setup test pattern engine for video mode
- * @ctrl: Pointer to the controller host hardware.
- * @type: Type of test pattern.
- * @init_val: Initial value to use for generating test pattern.
- */
-void dsi_ctrl_hw_14_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val)
-{
- u32 reg = 0;
-
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, init_val);
-
- switch (type) {
- case DSI_TEST_PATTERN_FIXED:
- reg |= (0x2 << 4);
- break;
- case DSI_TEST_PATTERN_INC:
- reg |= (0x1 << 4);
- break;
- case DSI_TEST_PATTERN_POLY:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_POLY, 0xF0F0F);
- break;
- default:
- break;
- }
-
- DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL, 0x100);
- DSI_W32(ctrl, DSI_TPG_VIDEO_CONFIG, 0x5);
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
-
- pr_debug("[DSI_%d] Video test pattern setup done\n", ctrl->index);
-}
-
-/**
- * cmd_test_pattern_setup() - setup test patttern engine for cmd mode
- * @ctrl: Pointer to the controller host hardware.
- * @type: Type of test pattern.
- * @init_val: Initial value to use for generating test pattern.
- * @stream_id: Stream Id on which packets are generated.
- */
-void dsi_ctrl_hw_14_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
- enum dsi_test_pattern type,
- u32 init_val,
- u32 stream_id)
-{
- u32 reg = 0;
- u32 init_offset;
- u32 poly_offset;
- u32 pattern_sel_shift;
-
- switch (stream_id) {
- case 0:
- init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0;
- poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM0_POLY;
- pattern_sel_shift = 8;
- break;
- case 1:
- init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL1;
- poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM1_POLY;
- pattern_sel_shift = 12;
- break;
- case 2:
- init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL2;
- poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY;
- pattern_sel_shift = 20;
- break;
- default:
- return;
- }
-
- DSI_W32(ctrl, init_offset, init_val);
-
- switch (type) {
- case DSI_TEST_PATTERN_FIXED:
- reg |= (0x2 << pattern_sel_shift);
- break;
- case DSI_TEST_PATTERN_INC:
- reg |= (0x1 << pattern_sel_shift);
- break;
- case DSI_TEST_PATTERN_POLY:
- DSI_W32(ctrl, poly_offset, 0xF0F0F);
- break;
- default:
- break;
- }
-
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
- pr_debug("[DSI_%d] Cmd test pattern setup done\n", ctrl->index);
-}
-
-/**
- * test_pattern_enable() - enable test pattern engine
- * @ctrl: Pointer to the controller host hardware.
- * @enable: Enable/Disable test pattern engine.
- */
-void dsi_ctrl_hw_14_test_pattern_enable(struct dsi_ctrl_hw *ctrl,
- bool enable)
-{
- u32 reg = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_CTRL);
-
- if (enable)
- reg |= BIT(0);
- else
- reg &= ~BIT(0);
-
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
-
- pr_debug("[DSI_%d] Test pattern enable=%d\n", ctrl->index, enable);
-}
-
-/**
- * trigger_cmd_test_pattern() - trigger a command mode frame update with
- * test pattern
- * @ctrl: Pointer to the controller host hardware.
- * @stream_id: Stream on which frame update is sent.
- */
-void dsi_ctrl_hw_14_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl,
- u32 stream_id)
-{
- switch (stream_id) {
- case 0:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER, 0x1);
- break;
- case 1:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM1_TRIGGER, 0x1);
- break;
- case 2:
- DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM2_TRIGGER, 0x1);
- break;
- default:
- break;
- }
-
- pr_debug("[DSI_%d] Cmd Test pattern trigger\n", ctrl->index);
-}
-
#define DUMP_REG_VALUE(off) "\t%-30s: 0x%08x\n", #off, DSI_R32(ctrl, off)
ssize_t dsi_ctrl_hw_14_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl,
char *buf,
@@ -1577,5 +478,3 @@
pr_err("LLENGTH = %d\n", len);
return len;
}
-
-
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c
new file mode 100644
index 0000000..c22849a
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) "dsi-hw:" fmt
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+
+#include "dsi_ctrl_hw.h"
+#include "dsi_ctrl_reg.h"
+#include "dsi_hw.h"
+
+void dsi_ctrl_hw_20_setup_lane_map(struct dsi_ctrl_hw *ctrl,
+ struct dsi_lane_map *lane_map)
+{
+ u32 reg_value = lane_map->lane_map_v2[DSI_LOGICAL_LANE_0] |
+ (lane_map->lane_map_v2[DSI_LOGICAL_LANE_1] << 4) |
+ (lane_map->lane_map_v2[DSI_LOGICAL_LANE_2] << 8) |
+ (lane_map->lane_map_v2[DSI_LOGICAL_LANE_3] << 12);
+
+ DSI_W32(ctrl, DSI_LANE_SWAP_CTRL, reg_value);
+
+ pr_debug("[DSI_%d] Lane swap setup complete\n", ctrl->index);
+}
+
+int dsi_ctrl_hw_20_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl,
+ u32 lanes)
+{
+ int rc = 0, val = 0;
+ u32 fifo_empty_mask = 0;
+ u32 const sleep_us = 10;
+ u32 const timeout_us = 100;
+
+ if (lanes & DSI_DATA_LANE_0)
+ fifo_empty_mask |= (BIT(12) | BIT(16));
+
+ if (lanes & DSI_DATA_LANE_1)
+ fifo_empty_mask |= BIT(20);
+
+ if (lanes & DSI_DATA_LANE_2)
+ fifo_empty_mask |= BIT(24);
+
+ if (lanes & DSI_DATA_LANE_3)
+ fifo_empty_mask |= BIT(28);
+
+ pr_debug("%s: polling for fifo empty, mask=0x%08x\n", __func__,
+ fifo_empty_mask);
+ rc = readl_poll_timeout(ctrl->base + DSI_FIFO_STATUS, val,
+ (val & fifo_empty_mask), sleep_us, timeout_us);
+ if (rc) {
+ pr_err("%s: fifo not empty, FIFO_STATUS=0x%08x\n",
+ __func__, val);
+ goto error;
+ }
+
+error:
+ return rc;
+}
+
+#define DUMP_REG_VALUE(off) "\t%-30s: 0x%08x\n", #off, DSI_R32(ctrl, off)
+ssize_t dsi_ctrl_hw_20_reg_dump_to_buffer(struct dsi_ctrl_hw *ctrl,
+ char *buf,
+ u32 size)
+{
+ u32 len = 0;
+
+ len += snprintf((buf + len), (size - len), "CONFIGURATION REGS:\n");
+
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_HW_VERSION));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_STATUS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_FIFO_STATUS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_SYNC_DATATYPE));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_PIXEL_DATATYPE));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_BLANKING_DATATYPE));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_DATA_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_ACTIVE_H));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_ACTIVE_V));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_TOTAL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_HSYNC));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_VSYNC));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VIDEO_MODE_VSYNC_VPOS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_DMA_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_DMA_CMD_OFFSET));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_DMA_CMD_LENGTH));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_DMA_FIFO_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_DMA_NULL_PACKET_DATA));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM0_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM0_TOTAL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM1_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM1_TOTAL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_ACK_ERR_STATUS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RDBK_DATA0));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RDBK_DATA1));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RDBK_DATA2));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RDBK_DATA3));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RDBK_DATATYPE0));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RDBK_DATATYPE1));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_TRIG_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_EXT_MUX));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_EXT_MUX_TE_PULSE_DETECT_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_CMD_MODE_DMA_SW_TRIGGER));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_CMD_MODE_MDP_SW_TRIGGER));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_CMD_MODE_BTA_SW_TRIGGER));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RESET_SW_TRIGGER));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_LANE_STATUS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_LANE_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_LANE_SWAP_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_DLN0_PHY_ERR));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_LP_TIMER_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_HS_TIMER_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_TIMEOUT_STATUS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_CLKOUT_TIMING_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_EOT_PACKET));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_EOT_PACKET_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_GENERIC_ESC_TX_TRIGGER));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_ERR_INT_MASK0));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_INT_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_SOFT_RESET));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_CLK_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_CLK_STATUS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_PHY_SW_RESET));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_AXI2AHB_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_CTRL2));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM2_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM2_TOTAL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VBIF_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_AES_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_RDBK_DATA_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL2));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_STATUS));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_WRITE_TRIGGER));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_DSI_TIMING_FLUSH));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_DSI_TIMING_DB_MODE));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_TPG_DMA_FIFO_RESET));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_VERSION));
+
+ pr_err("LLENGTH = %d\n", len);
+ return len;
+}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
new file mode 100644
index 0000000..9a6fc77
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -0,0 +1,1104 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) "dsi-hw:" fmt
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+
+#include "dsi_ctrl_hw.h"
+#include "dsi_ctrl_reg.h"
+#include "dsi_hw.h"
+
+#define MMSS_MISC_CLAMP_REG_OFF 0x0014
+
+/* Unsupported formats default to RGB888 */
+static const u8 cmd_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
+ 0x6, 0x7, 0x8, 0x8, 0x0, 0x3, 0x4 };
+static const u8 video_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
+ 0x0, 0x1, 0x2, 0x3, 0x3, 0x3, 0x3 };
+
+/**
+ * dsi_setup_trigger_controls() - setup dsi trigger configurations
+ * @ctrl: Pointer to the controller host hardware.
+ * @cfg: DSI host configuration that is common to both video and
+ * command modes.
+ */
+static void dsi_setup_trigger_controls(struct dsi_ctrl_hw *ctrl,
+ struct dsi_host_common_cfg *cfg)
+{
+ u32 reg = 0;
+ const u8 trigger_map[DSI_TRIGGER_MAX] = {
+ 0x0, 0x2, 0x1, 0x4, 0x5, 0x6 };
+
+ reg |= (cfg->te_mode == DSI_TE_ON_EXT_PIN) ? BIT(31) : 0;
+ reg |= (trigger_map[cfg->dma_cmd_trigger] & 0x7);
+ reg |= (trigger_map[cfg->mdp_cmd_trigger] & 0x7) << 4;
+ DSI_W32(ctrl, DSI_TRIG_CTRL, reg);
+}
+
+/**
+ * dsi_ctrl_hw_cmn_host_setup() - setup dsi host configuration
+ * @ctrl: Pointer to the controller host hardware.
+ * @cfg: DSI host configuration that is common to both video and
+ * command modes.
+ */
+void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl,
+ struct dsi_host_common_cfg *cfg)
+{
+ u32 reg_value = 0;
+
+ dsi_setup_trigger_controls(ctrl, cfg);
+
+ /* Setup clocking timing controls */
+ reg_value = ((cfg->t_clk_post & 0x3F) << 8);
+ reg_value |= (cfg->t_clk_pre & 0x3F);
+ DSI_W32(ctrl, DSI_CLKOUT_TIMING_CTRL, reg_value);
+
+ /* EOT packet control */
+ reg_value = cfg->append_tx_eot ? 1 : 0;
+ reg_value |= (cfg->ignore_rx_eot ? (1 << 4) : 0);
+ DSI_W32(ctrl, DSI_EOT_PACKET_CTRL, reg_value);
+
+ /* Turn on dsi clocks */
+ DSI_W32(ctrl, DSI_CLK_CTRL, 0x23F);
+
+ /* Setup DSI control register */
+ reg_value = 0;
+ reg_value |= (cfg->en_crc_check ? BIT(24) : 0);
+ reg_value |= (cfg->en_ecc_check ? BIT(20) : 0);
+ reg_value |= BIT(8); /* Clock lane */
+ reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_3) ? BIT(7) : 0);
+ reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_2) ? BIT(6) : 0);
+ reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_1) ? BIT(5) : 0);
+ reg_value |= ((cfg->data_lanes & DSI_DATA_LANE_0) ? BIT(4) : 0);
+
+ DSI_W32(ctrl, DSI_CTRL, reg_value);
+
+ pr_debug("[DSI_%d]Host configuration complete\n", ctrl->index);
+}
+
+/**
+ * phy_sw_reset() - perform a soft reset on the PHY.
+ * @ctrl: Pointer to the controller host hardware.
+ */
+void dsi_ctrl_hw_cmn_phy_sw_reset(struct dsi_ctrl_hw *ctrl)
+{
+ DSI_W32(ctrl, DSI_PHY_SW_RESET, 0x1);
+ udelay(1000);
+ DSI_W32(ctrl, DSI_PHY_SW_RESET, 0x0);
+ udelay(100);
+
+ pr_debug("[DSI_%d] phy sw reset done\n", ctrl->index);
+}
+
+/**
+ * soft_reset() - perform a soft reset on DSI controller
+ * @ctrl: Pointer to the controller host hardware.
+ *
+ * The video, command and controller engines will be disable before the
+ * reset is triggered. These engines will not be enabled after the reset
+ * is complete. Caller must re-enable the engines.
+ *
+ * If the reset is done while MDP timing engine is turned on, the video
+ * enigne should be re-enabled only during the vertical blanking time.
+ */
+void dsi_ctrl_hw_cmn_soft_reset(struct dsi_ctrl_hw *ctrl)
+{
+ u32 reg = 0;
+ u32 reg_ctrl = 0;
+
+ /* Clear DSI_EN, VIDEO_MODE_EN, CMD_MODE_EN */
+ reg_ctrl = DSI_R32(ctrl, DSI_CTRL);
+ DSI_W32(ctrl, DSI_CTRL, reg_ctrl & ~0x7);
+
+ /* Force enable PCLK, BYTECLK, AHBM_HCLK */
+ reg = DSI_R32(ctrl, DSI_CLK_CTRL);
+ reg |= 0x23F;
+ DSI_W32(ctrl, DSI_CLK_CTRL, reg);
+
+ /* Trigger soft reset */
+ DSI_W32(ctrl, DSI_SOFT_RESET, 0x1);
+ udelay(1);
+ DSI_W32(ctrl, DSI_SOFT_RESET, 0x0);
+
+ /* Disable force clock on */
+ reg &= ~(BIT(20) | BIT(11));
+ DSI_W32(ctrl, DSI_CLK_CTRL, reg);
+
+ /* Re-enable DSI controller */
+ DSI_W32(ctrl, DSI_CTRL, reg_ctrl);
+ pr_debug("[DSI_%d] ctrl soft reset done\n", ctrl->index);
+}
+
+/**
+ * set_video_timing() - set up the timing for video frame
+ * @ctrl: Pointer to controller host hardware.
+ * @mode: Video mode information.
+ *
+ * Set up the video timing parameters for the DSI video mode operation.
+ */
+void dsi_ctrl_hw_cmn_set_video_timing(struct dsi_ctrl_hw *ctrl,
+ struct dsi_mode_info *mode)
+{
+ u32 reg = 0;
+ u32 hs_start = 0;
+ u32 hs_end, active_h_start, active_h_end, h_total;
+ u32 vs_start = 0, vs_end = 0;
+ u32 vpos_start = 0, vpos_end, active_v_start, active_v_end, v_total;
+
+ hs_end = mode->h_sync_width;
+ active_h_start = mode->h_sync_width + mode->h_back_porch;
+ active_h_end = active_h_start + mode->h_active;
+ h_total = (mode->h_sync_width + mode->h_back_porch + mode->h_active +
+ mode->h_front_porch) - 1;
+
+ vpos_end = mode->v_sync_width;
+ active_v_start = mode->v_sync_width + mode->v_back_porch;
+ active_v_end = active_v_start + mode->v_active;
+ v_total = (mode->v_sync_width + mode->v_back_porch + mode->v_active +
+ mode->v_front_porch) - 1;
+
+ reg = ((active_h_end & 0xFFFF) << 16) | (active_h_start & 0xFFFF);
+ DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_H, reg);
+
+ reg = ((active_v_end & 0xFFFF) << 16) | (active_v_start & 0xFFFF);
+ DSI_W32(ctrl, DSI_VIDEO_MODE_ACTIVE_V, reg);
+
+ reg = ((v_total & 0xFFFF) << 16) | (h_total & 0xFFFF);
+ DSI_W32(ctrl, DSI_VIDEO_MODE_TOTAL, reg);
+
+ reg = ((hs_end & 0xFFFF) << 16) | (hs_start & 0xFFFF);
+ DSI_W32(ctrl, DSI_VIDEO_MODE_HSYNC, reg);
+
+ reg = ((vs_end & 0xFFFF) << 16) | (vs_start & 0xFFFF);
+ DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC, reg);
+
+ reg = ((vpos_end & 0xFFFF) << 16) | (vpos_start & 0xFFFF);
+ DSI_W32(ctrl, DSI_VIDEO_MODE_VSYNC_VPOS, reg);
+
+ /* TODO: HS TIMER value? */
+ DSI_W32(ctrl, DSI_HS_TIMER_CTRL, 0x3FD08);
+ DSI_W32(ctrl, DSI_MISR_VIDEO_CTRL, 0x10100);
+ DSI_W32(ctrl, DSI_DSI_TIMING_FLUSH, 0x1);
+ pr_debug("[DSI_%d] ctrl video parameters updated\n", ctrl->index);
+}
+
+/**
+ * setup_cmd_stream() - set up parameters for command pixel streams
+ * @ctrl: Pointer to controller host hardware.
+ * @width_in_pixels: Width of the stream in pixels.
+ * @h_stride: Horizontal stride in bytes.
+ * @height_inLines: Number of lines in the stream.
+ * @vc_id: stream_id
+ *
+ * Setup parameters for command mode pixel stream size.
+ */
+void dsi_ctrl_hw_cmn_setup_cmd_stream(struct dsi_ctrl_hw *ctrl,
+ u32 width_in_pixels,
+ u32 h_stride,
+ u32 height_in_lines,
+ u32 vc_id)
+{
+ u32 reg = 0;
+
+ reg = (h_stride + 1) << 16;
+ reg |= (vc_id & 0x3) << 8;
+ reg |= 0x39; /* packet data type */
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_CTRL, reg);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_CTRL, reg);
+
+ reg = (height_in_lines << 16) | width_in_pixels;
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM0_TOTAL, reg);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_STREAM1_TOTAL, reg);
+}
+
+/**
+ * video_engine_setup() - Setup dsi host controller for video mode
+ * @ctrl: Pointer to controller host hardware.
+ * @common_cfg: Common configuration parameters.
+ * @cfg: Video mode configuration.
+ *
+ * Set up DSI video engine with a specific configuration. Controller and
+ * video engine are not enabled as part of this function.
+ */
+void dsi_ctrl_hw_cmn_video_engine_setup(struct dsi_ctrl_hw *ctrl,
+ struct dsi_host_common_cfg *common_cfg,
+ struct dsi_video_engine_cfg *cfg)
+{
+ u32 reg = 0;
+
+ reg |= (cfg->last_line_interleave_en ? BIT(31) : 0);
+ reg |= (cfg->pulse_mode_hsa_he ? BIT(28) : 0);
+ reg |= (cfg->hfp_lp11_en ? BIT(24) : 0);
+ reg |= (cfg->hbp_lp11_en ? BIT(20) : 0);
+ reg |= (cfg->hsa_lp11_en ? BIT(16) : 0);
+ reg |= (cfg->eof_bllp_lp11_en ? BIT(15) : 0);
+ reg |= (cfg->bllp_lp11_en ? BIT(12) : 0);
+ reg |= (cfg->traffic_mode & 0x3) << 8;
+ reg |= (cfg->vc_id & 0x3);
+ reg |= (video_mode_format_map[common_cfg->dst_format] & 0x3) << 4;
+ DSI_W32(ctrl, DSI_VIDEO_MODE_CTRL, reg);
+
+ reg = (common_cfg->swap_mode & 0x7) << 12;
+ reg |= (common_cfg->bit_swap_red ? BIT(0) : 0);
+ reg |= (common_cfg->bit_swap_green ? BIT(4) : 0);
+ reg |= (common_cfg->bit_swap_blue ? BIT(8) : 0);
+ DSI_W32(ctrl, DSI_VIDEO_MODE_DATA_CTRL, reg);
+ /* Enable Timing double buffering */
+ DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1);
+
+
+ pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index);
+}
+
+/**
+ * cmd_engine_setup() - setup dsi host controller for command mode
+ * @ctrl: Pointer to the controller host hardware.
+ * @common_cfg: Common configuration parameters.
+ * @cfg: Command mode configuration.
+ *
+ * Setup DSI CMD engine with a specific configuration. Controller and
+ * command engine are not enabled as part of this function.
+ */
+void dsi_ctrl_hw_cmn_cmd_engine_setup(struct dsi_ctrl_hw *ctrl,
+ struct dsi_host_common_cfg *common_cfg,
+ struct dsi_cmd_engine_cfg *cfg)
+{
+ u32 reg = 0;
+
+ reg = (cfg->max_cmd_packets_interleave & 0xF) << 20;
+ reg |= (common_cfg->bit_swap_red ? BIT(4) : 0);
+ reg |= (common_cfg->bit_swap_green ? BIT(8) : 0);
+ reg |= (common_cfg->bit_swap_blue ? BIT(12) : 0);
+ reg |= cmd_mode_format_map[common_cfg->dst_format];
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL, reg);
+
+ reg = DSI_R32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2);
+ reg |= BIT(16);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_CTRL2, reg);
+
+ reg = cfg->wr_mem_start & 0xFF;
+ reg |= (cfg->wr_mem_continue & 0xFF) << 8;
+ reg |= (cfg->insert_dcs_command ? BIT(16) : 0);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL, reg);
+
+ pr_debug("[DSI_%d] Cmd engine setup done\n", ctrl->index);
+}
+
+/**
+ * video_engine_en() - enable DSI video engine
+ * @ctrl: Pointer to controller host hardware.
+ * @on: Enable/disabel video engine.
+ */
+void dsi_ctrl_hw_cmn_video_engine_en(struct dsi_ctrl_hw *ctrl, bool on)
+{
+ u32 reg = 0;
+
+ /* Set/Clear VIDEO_MODE_EN bit */
+ reg = DSI_R32(ctrl, DSI_CTRL);
+ if (on)
+ reg |= BIT(1);
+ else
+ reg &= ~BIT(1);
+
+ DSI_W32(ctrl, DSI_CTRL, reg);
+
+ pr_debug("[DSI_%d] Video engine = %d\n", ctrl->index, on);
+}
+
+/**
+ * ctrl_en() - enable DSI controller engine
+ * @ctrl: Pointer to the controller host hardware.
+ * @on: turn on/off the DSI controller engine.
+ */
+void dsi_ctrl_hw_cmn_ctrl_en(struct dsi_ctrl_hw *ctrl, bool on)
+{
+ u32 reg = 0;
+
+ /* Set/Clear DSI_EN bit */
+ reg = DSI_R32(ctrl, DSI_CTRL);
+ if (on)
+ reg |= BIT(0);
+ else
+ reg &= ~BIT(0);
+
+ DSI_W32(ctrl, DSI_CTRL, reg);
+
+ pr_debug("[DSI_%d] Controller engine = %d\n", ctrl->index, on);
+}
+
+/**
+ * cmd_engine_en() - enable DSI controller command engine
+ * @ctrl: Pointer to the controller host hardware.
+ * @on: Turn on/off the DSI command engine.
+ */
+void dsi_ctrl_hw_cmn_cmd_engine_en(struct dsi_ctrl_hw *ctrl, bool on)
+{
+ u32 reg = 0;
+
+ /* Set/Clear CMD_MODE_EN bit */
+ reg = DSI_R32(ctrl, DSI_CTRL);
+ if (on)
+ reg |= BIT(2);
+ else
+ reg &= ~BIT(2);
+
+ DSI_W32(ctrl, DSI_CTRL, reg);
+
+ pr_debug("[DSI_%d] command engine = %d\n", ctrl->index, on);
+}
+
+/**
+ * kickoff_command() - transmits commands stored in memory
+ * @ctrl: Pointer to the controller host hardware.
+ * @cmd: Command information.
+ * @flags: Modifiers for command transmission.
+ *
+ * The controller hardware is programmed with address and size of the
+ * command buffer. The transmission is kicked off if
+ * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
+ * set, caller should make a separate call to trigger_command_dma() to
+ * transmit the command.
+ */
+void dsi_ctrl_hw_cmn_kickoff_command(struct dsi_ctrl_hw *ctrl,
+ struct dsi_ctrl_cmd_dma_info *cmd,
+ u32 flags)
+{
+ u32 reg = 0;
+
+ /*Set BROADCAST_EN and EMBEDDED_MODE */
+ reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL);
+ if (cmd->en_broadcast)
+ reg |= BIT(31);
+ else
+ reg &= ~BIT(31);
+
+ if (cmd->is_master)
+ reg |= BIT(30);
+ else
+ reg &= ~BIT(30);
+
+ if (cmd->use_lpm)
+ reg |= BIT(26);
+ else
+ reg &= ~BIT(26);
+
+ reg |= BIT(28);
+ DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg);
+
+ DSI_W32(ctrl, DSI_DMA_CMD_OFFSET, cmd->offset);
+ DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->length & 0xFFFFFF));
+
+ /* wait for writes to complete before kick off */
+ wmb();
+
+ if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER))
+ DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
+}
+
+/**
+ * kickoff_fifo_command() - transmits a command using FIFO in dsi
+ * hardware.
+ * @ctrl: Pointer to the controller host hardware.
+ * @cmd: Command information.
+ * @flags: Modifiers for command transmission.
+ *
+ * The controller hardware FIFO is programmed with command header and
+ * payload. The transmission is kicked off if
+ * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag is not set. If this flag is
+ * set, caller should make a separate call to trigger_command_dma() to
+ * transmit the command.
+ */
+void dsi_ctrl_hw_cmn_kickoff_fifo_command(struct dsi_ctrl_hw *ctrl,
+ struct dsi_ctrl_cmd_dma_fifo_info *cmd,
+ u32 flags)
+{
+ u32 reg = 0, i = 0;
+ u32 *ptr = cmd->command;
+ /*
+ * Set CMD_DMA_TPG_EN, TPG_DMA_FIFO_MODE and
+ * CMD_DMA_PATTERN_SEL = custom pattern stored in TPG DMA FIFO
+ */
+ reg = (BIT(1) | BIT(2) | (0x3 << 16));
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
+
+ /*
+ * Program the FIFO with command buffer. Hardware requires an extra
+ * DWORD (set to zero) if the length of command buffer is odd DWORDS.
+ */
+ for (i = 0; i < cmd->size; i += 4) {
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, *ptr);
+ ptr++;
+ }
+
+ if ((cmd->size / 4) & 0x1)
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_DMA_INIT_VAL, 0);
+
+ /*Set BROADCAST_EN and EMBEDDED_MODE */
+ reg = DSI_R32(ctrl, DSI_COMMAND_MODE_DMA_CTRL);
+ if (cmd->en_broadcast)
+ reg |= BIT(31);
+ else
+ reg &= ~BIT(31);
+
+ if (cmd->is_master)
+ reg |= BIT(30);
+ else
+ reg &= ~BIT(30);
+
+ if (cmd->use_lpm)
+ reg |= BIT(26);
+ else
+ reg &= ~BIT(26);
+
+ reg |= BIT(28);
+
+ DSI_W32(ctrl, DSI_COMMAND_MODE_DMA_CTRL, reg);
+
+ DSI_W32(ctrl, DSI_DMA_CMD_LENGTH, (cmd->size & 0xFFFFFFFF));
+ /* Finish writes before command trigger */
+ wmb();
+
+ if (!(flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER))
+ DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
+
+ pr_debug("[DSI_%d]size=%d, trigger = %d\n",
+ ctrl->index, cmd->size,
+ (flags & DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER) ? false : true);
+}
+
+void dsi_ctrl_hw_cmn_reset_cmd_fifo(struct dsi_ctrl_hw *ctrl)
+{
+ /* disable cmd dma tpg */
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, 0x0);
+
+ DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x1);
+ udelay(1);
+ DSI_W32(ctrl, DSI_TPG_DMA_FIFO_RESET, 0x0);
+}
+
+/**
+ * trigger_command_dma() - trigger transmission of command buffer.
+ * @ctrl: Pointer to the controller host hardware.
+ *
+ * This trigger can be only used if there was a prior call to
+ * kickoff_command() of kickoff_fifo_command() with
+ * DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER flag.
+ */
+void dsi_ctrl_hw_cmn_trigger_command_dma(struct dsi_ctrl_hw *ctrl)
+{
+ DSI_W32(ctrl, DSI_CMD_MODE_DMA_SW_TRIGGER, 0x1);
+ pr_debug("[DSI_%d] CMD DMA triggered\n", ctrl->index);
+}
+
+/**
+ * get_cmd_read_data() - get data read from the peripheral
+ * @ctrl: Pointer to the controller host hardware.
+ * @rd_buf: Buffer where data will be read into.
+ * @total_read_len: Number of bytes to read.
+ *
+ * return: number of bytes read.
+ */
+u32 dsi_ctrl_hw_cmn_get_cmd_read_data(struct dsi_ctrl_hw *ctrl,
+ u8 *rd_buf,
+ u32 read_offset,
+ u32 total_read_len)
+{
+ u32 *lp, *temp, data;
+ int i, j = 0, cnt;
+ u32 read_cnt;
+ u32 rx_byte = 0;
+ u32 repeated_bytes = 0;
+ u8 reg[16] = {0};
+ u32 pkt_size = 0;
+ int buf_offset = read_offset;
+
+ lp = (u32 *)rd_buf;
+ temp = (u32 *)reg;
+ cnt = (rx_byte + 3) >> 2;
+
+ if (cnt > 4)
+ cnt = 4;
+
+ if (rx_byte == 4)
+ read_cnt = 4;
+ else
+ read_cnt = pkt_size + 6;
+
+ if (read_cnt > 16) {
+ int bytes_shifted;
+
+ bytes_shifted = read_cnt - 16;
+ repeated_bytes = buf_offset - bytes_shifted;
+ }
+
+ for (i = cnt - 1; i >= 0; i--) {
+ data = DSI_R32(ctrl, DSI_RDBK_DATA0 + i*4);
+ *temp++ = ntohl(data);
+ }
+
+ for (i = repeated_bytes; i < 16; i++)
+ rd_buf[j++] = reg[i];
+
+ pr_debug("[DSI_%d] Read %d bytes\n", ctrl->index, j);
+ return j;
+}
+
+/**
+ * get_interrupt_status() - returns the interrupt status
+ * @ctrl: Pointer to the controller host hardware.
+ *
+ * Returns the ORed list of interrupts(enum dsi_status_int_type) that
+ * are active. This list does not include any error interrupts. Caller
+ * should call get_error_status for error interrupts.
+ *
+ * Return: List of active interrupts.
+ */
+u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl)
+{
+ u32 reg = 0;
+ u32 ints = 0;
+
+ reg = DSI_R32(ctrl, DSI_INT_CTRL);
+
+ if (reg & BIT(0))
+ ints |= DSI_CMD_MODE_DMA_DONE;
+ if (reg & BIT(8))
+ ints |= DSI_CMD_FRAME_DONE;
+ if (reg & BIT(10))
+ ints |= DSI_CMD_STREAM0_FRAME_DONE;
+ if (reg & BIT(12))
+ ints |= DSI_CMD_STREAM1_FRAME_DONE;
+ if (reg & BIT(14))
+ ints |= DSI_CMD_STREAM2_FRAME_DONE;
+ if (reg & BIT(16))
+ ints |= DSI_VIDEO_MODE_FRAME_DONE;
+ if (reg & BIT(20))
+ ints |= DSI_BTA_DONE;
+ if (reg & BIT(28))
+ ints |= DSI_DYN_REFRESH_DONE;
+ if (reg & BIT(30))
+ ints |= DSI_DESKEW_DONE;
+
+ pr_debug("[DSI_%d] Interrupt status = 0x%x, INT_CTRL=0x%x\n",
+ ctrl->index, ints, reg);
+ return ints;
+}
+
+/**
+ * clear_interrupt_status() - clears the specified interrupts
+ * @ctrl: Pointer to the controller host hardware.
+ * @ints: List of interrupts to be cleared.
+ */
+void dsi_ctrl_hw_cmn_clear_interrupt_status(struct dsi_ctrl_hw *ctrl, u32 ints)
+{
+ u32 reg = 0;
+
+ if (ints & DSI_CMD_MODE_DMA_DONE)
+ reg |= BIT(0);
+ if (ints & DSI_CMD_FRAME_DONE)
+ reg |= BIT(8);
+ if (ints & DSI_CMD_STREAM0_FRAME_DONE)
+ reg |= BIT(10);
+ if (ints & DSI_CMD_STREAM1_FRAME_DONE)
+ reg |= BIT(12);
+ if (ints & DSI_CMD_STREAM2_FRAME_DONE)
+ reg |= BIT(14);
+ if (ints & DSI_VIDEO_MODE_FRAME_DONE)
+ reg |= BIT(16);
+ if (ints & DSI_BTA_DONE)
+ reg |= BIT(20);
+ if (ints & DSI_DYN_REFRESH_DONE)
+ reg |= BIT(28);
+ if (ints & DSI_DESKEW_DONE)
+ reg |= BIT(30);
+
+ DSI_W32(ctrl, DSI_INT_CTRL, reg);
+
+ pr_debug("[DSI_%d] Clear interrupts, ints = 0x%x, INT_CTRL=0x%x\n",
+ ctrl->index, ints, reg);
+}
+
+/**
+ * enable_status_interrupts() - enable the specified interrupts
+ * @ctrl: Pointer to the controller host hardware.
+ * @ints: List of interrupts to be enabled.
+ *
+ * Enables the specified interrupts. This list will override the
+ * previous interrupts enabled through this function. Caller has to
+ * maintain the state of the interrupts enabled. To disable all
+ * interrupts, set ints to 0.
+ */
+void dsi_ctrl_hw_cmn_enable_status_interrupts(
+ struct dsi_ctrl_hw *ctrl, u32 ints)
+{
+ u32 reg = 0;
+
+ /* Do not change value of DSI_ERROR_MASK bit */
+ reg |= (DSI_R32(ctrl, DSI_INT_CTRL) & BIT(25));
+ if (ints & DSI_CMD_MODE_DMA_DONE)
+ reg |= BIT(1);
+ if (ints & DSI_CMD_FRAME_DONE)
+ reg |= BIT(9);
+ if (ints & DSI_CMD_STREAM0_FRAME_DONE)
+ reg |= BIT(11);
+ if (ints & DSI_CMD_STREAM1_FRAME_DONE)
+ reg |= BIT(13);
+ if (ints & DSI_CMD_STREAM2_FRAME_DONE)
+ reg |= BIT(15);
+ if (ints & DSI_VIDEO_MODE_FRAME_DONE)
+ reg |= BIT(17);
+ if (ints & DSI_BTA_DONE)
+ reg |= BIT(21);
+ if (ints & DSI_DYN_REFRESH_DONE)
+ reg |= BIT(29);
+ if (ints & DSI_DESKEW_DONE)
+ reg |= BIT(31);
+
+ DSI_W32(ctrl, DSI_INT_CTRL, reg);
+
+ pr_debug("[DSI_%d] Enable interrupts 0x%x, INT_CTRL=0x%x\n",
+ ctrl->index, ints, reg);
+}
+
+/**
+ * get_error_status() - returns the error status
+ * @ctrl: Pointer to the controller host hardware.
+ *
+ * Returns the ORed list of errors(enum dsi_error_int_type) that are
+ * active. This list does not include any status interrupts. Caller
+ * should call get_interrupt_status for status interrupts.
+ *
+ * Return: List of active error interrupts.
+ */
+u64 dsi_ctrl_hw_cmn_get_error_status(struct dsi_ctrl_hw *ctrl)
+{
+ u32 dln0_phy_err;
+ u32 fifo_status;
+ u32 ack_error;
+ u32 timeout_errors;
+ u32 clk_error;
+ u32 dsi_status;
+ u64 errors = 0;
+
+ dln0_phy_err = DSI_R32(ctrl, DSI_DLN0_PHY_ERR);
+ if (dln0_phy_err & BIT(0))
+ errors |= DSI_DLN0_ESC_ENTRY_ERR;
+ if (dln0_phy_err & BIT(4))
+ errors |= DSI_DLN0_ESC_SYNC_ERR;
+ if (dln0_phy_err & BIT(8))
+ errors |= DSI_DLN0_LP_CONTROL_ERR;
+ if (dln0_phy_err & BIT(12))
+ errors |= DSI_DLN0_LP0_CONTENTION;
+ if (dln0_phy_err & BIT(16))
+ errors |= DSI_DLN0_LP1_CONTENTION;
+
+ fifo_status = DSI_R32(ctrl, DSI_FIFO_STATUS);
+ if (fifo_status & BIT(7))
+ errors |= DSI_CMD_MDP_FIFO_UNDERFLOW;
+ if (fifo_status & BIT(10))
+ errors |= DSI_CMD_DMA_FIFO_UNDERFLOW;
+ if (fifo_status & BIT(18))
+ errors |= DSI_DLN0_HS_FIFO_OVERFLOW;
+ if (fifo_status & BIT(19))
+ errors |= DSI_DLN0_HS_FIFO_UNDERFLOW;
+ if (fifo_status & BIT(22))
+ errors |= DSI_DLN1_HS_FIFO_OVERFLOW;
+ if (fifo_status & BIT(23))
+ errors |= DSI_DLN1_HS_FIFO_UNDERFLOW;
+ if (fifo_status & BIT(26))
+ errors |= DSI_DLN2_HS_FIFO_OVERFLOW;
+ if (fifo_status & BIT(27))
+ errors |= DSI_DLN2_HS_FIFO_UNDERFLOW;
+ if (fifo_status & BIT(30))
+ errors |= DSI_DLN3_HS_FIFO_OVERFLOW;
+ if (fifo_status & BIT(31))
+ errors |= DSI_DLN3_HS_FIFO_UNDERFLOW;
+
+ ack_error = DSI_R32(ctrl, DSI_ACK_ERR_STATUS);
+ if (ack_error & BIT(16))
+ errors |= DSI_RDBK_SINGLE_ECC_ERR;
+ if (ack_error & BIT(17))
+ errors |= DSI_RDBK_MULTI_ECC_ERR;
+ if (ack_error & BIT(20))
+ errors |= DSI_RDBK_CRC_ERR;
+ if (ack_error & BIT(23))
+ errors |= DSI_RDBK_INCOMPLETE_PKT;
+ if (ack_error & BIT(24))
+ errors |= DSI_PERIPH_ERROR_PKT;
+
+ timeout_errors = DSI_R32(ctrl, DSI_TIMEOUT_STATUS);
+ if (timeout_errors & BIT(0))
+ errors |= DSI_HS_TX_TIMEOUT;
+ if (timeout_errors & BIT(4))
+ errors |= DSI_LP_RX_TIMEOUT;
+ if (timeout_errors & BIT(8))
+ errors |= DSI_BTA_TIMEOUT;
+
+ clk_error = DSI_R32(ctrl, DSI_CLK_STATUS);
+ if (clk_error & BIT(16))
+ errors |= DSI_PLL_UNLOCK;
+
+ dsi_status = DSI_R32(ctrl, DSI_STATUS);
+ if (dsi_status & BIT(31))
+ errors |= DSI_INTERLEAVE_OP_CONTENTION;
+
+ pr_debug("[DSI_%d] Error status = 0x%llx, phy=0x%x, fifo=0x%x",
+ ctrl->index, errors, dln0_phy_err, fifo_status);
+ pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n",
+ ctrl->index, ack_error, timeout_errors, clk_error, dsi_status);
+ return errors;
+}
+
+/**
+ * clear_error_status() - clears the specified errors
+ * @ctrl: Pointer to the controller host hardware.
+ * @errors: List of errors to be cleared.
+ */
+void dsi_ctrl_hw_cmn_clear_error_status(struct dsi_ctrl_hw *ctrl, u64 errors)
+{
+ u32 dln0_phy_err = 0;
+ u32 fifo_status = 0;
+ u32 ack_error = 0;
+ u32 timeout_error = 0;
+ u32 clk_error = 0;
+ u32 dsi_status = 0;
+ u32 int_ctrl = 0;
+
+ if (errors & DSI_RDBK_SINGLE_ECC_ERR)
+ ack_error |= BIT(16);
+ if (errors & DSI_RDBK_MULTI_ECC_ERR)
+ ack_error |= BIT(17);
+ if (errors & DSI_RDBK_CRC_ERR)
+ ack_error |= BIT(20);
+ if (errors & DSI_RDBK_INCOMPLETE_PKT)
+ ack_error |= BIT(23);
+ if (errors & DSI_PERIPH_ERROR_PKT)
+ ack_error |= BIT(24);
+
+ if (errors & DSI_LP_RX_TIMEOUT)
+ timeout_error |= BIT(4);
+ if (errors & DSI_HS_TX_TIMEOUT)
+ timeout_error |= BIT(0);
+ if (errors & DSI_BTA_TIMEOUT)
+ timeout_error |= BIT(8);
+
+ if (errors & DSI_PLL_UNLOCK)
+ clk_error |= BIT(16);
+
+ if (errors & DSI_DLN0_LP0_CONTENTION)
+ dln0_phy_err |= BIT(12);
+ if (errors & DSI_DLN0_LP1_CONTENTION)
+ dln0_phy_err |= BIT(16);
+ if (errors & DSI_DLN0_ESC_ENTRY_ERR)
+ dln0_phy_err |= BIT(0);
+ if (errors & DSI_DLN0_ESC_SYNC_ERR)
+ dln0_phy_err |= BIT(4);
+ if (errors & DSI_DLN0_LP_CONTROL_ERR)
+ dln0_phy_err |= BIT(8);
+
+ if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW)
+ fifo_status |= BIT(10);
+ if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW)
+ fifo_status |= BIT(7);
+ if (errors & DSI_DLN0_HS_FIFO_OVERFLOW)
+ fifo_status |= BIT(18);
+ if (errors & DSI_DLN1_HS_FIFO_OVERFLOW)
+ fifo_status |= BIT(22);
+ if (errors & DSI_DLN2_HS_FIFO_OVERFLOW)
+ fifo_status |= BIT(26);
+ if (errors & DSI_DLN3_HS_FIFO_OVERFLOW)
+ fifo_status |= BIT(30);
+ if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW)
+ fifo_status |= BIT(19);
+ if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW)
+ fifo_status |= BIT(23);
+ if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW)
+ fifo_status |= BIT(27);
+ if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW)
+ fifo_status |= BIT(31);
+
+ if (errors & DSI_INTERLEAVE_OP_CONTENTION)
+ dsi_status |= BIT(31);
+
+ DSI_W32(ctrl, DSI_DLN0_PHY_ERR, dln0_phy_err);
+ DSI_W32(ctrl, DSI_FIFO_STATUS, fifo_status);
+ DSI_W32(ctrl, DSI_ACK_ERR_STATUS, ack_error);
+ DSI_W32(ctrl, DSI_TIMEOUT_STATUS, timeout_error);
+ DSI_W32(ctrl, DSI_CLK_STATUS, clk_error);
+ DSI_W32(ctrl, DSI_STATUS, dsi_status);
+
+ int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
+ int_ctrl |= BIT(24);
+ DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
+ pr_debug("[DSI_%d] clear errors = 0x%llx, phy=0x%x, fifo=0x%x",
+ ctrl->index, errors, dln0_phy_err, fifo_status);
+ pr_debug("[DSI_%d] ack=0x%x, timeout=0x%x, clk=0x%x, dsi=0x%x\n",
+ ctrl->index, ack_error, timeout_error, clk_error, dsi_status);
+}
+
+/**
+ * enable_error_interrupts() - enable the specified interrupts
+ * @ctrl: Pointer to the controller host hardware.
+ * @errors: List of errors to be enabled.
+ *
+ * Enables the specified interrupts. This list will override the
+ * previous interrupts enabled through this function. Caller has to
+ * maintain the state of the interrupts enabled. To disable all
+ * interrupts, set errors to 0.
+ */
+void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
+ u64 errors)
+{
+ u32 int_ctrl = 0;
+ u32 int_mask0 = 0x7FFF3BFF;
+
+ int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
+ if (errors)
+ int_ctrl |= BIT(25);
+ else
+ int_ctrl &= ~BIT(25);
+
+ if (errors & DSI_RDBK_SINGLE_ECC_ERR)
+ int_mask0 &= ~BIT(0);
+ if (errors & DSI_RDBK_MULTI_ECC_ERR)
+ int_mask0 &= ~BIT(1);
+ if (errors & DSI_RDBK_CRC_ERR)
+ int_mask0 &= ~BIT(2);
+ if (errors & DSI_RDBK_INCOMPLETE_PKT)
+ int_mask0 &= ~BIT(3);
+ if (errors & DSI_PERIPH_ERROR_PKT)
+ int_mask0 &= ~BIT(4);
+
+ if (errors & DSI_LP_RX_TIMEOUT)
+ int_mask0 &= ~BIT(5);
+ if (errors & DSI_HS_TX_TIMEOUT)
+ int_mask0 &= ~BIT(6);
+ if (errors & DSI_BTA_TIMEOUT)
+ int_mask0 &= ~BIT(7);
+
+ if (errors & DSI_PLL_UNLOCK)
+ int_mask0 &= ~BIT(28);
+
+ if (errors & DSI_DLN0_LP0_CONTENTION)
+ int_mask0 &= ~BIT(24);
+ if (errors & DSI_DLN0_LP1_CONTENTION)
+ int_mask0 &= ~BIT(25);
+ if (errors & DSI_DLN0_ESC_ENTRY_ERR)
+ int_mask0 &= ~BIT(21);
+ if (errors & DSI_DLN0_ESC_SYNC_ERR)
+ int_mask0 &= ~BIT(22);
+ if (errors & DSI_DLN0_LP_CONTROL_ERR)
+ int_mask0 &= ~BIT(23);
+
+ if (errors & DSI_CMD_DMA_FIFO_UNDERFLOW)
+ int_mask0 &= ~BIT(9);
+ if (errors & DSI_CMD_MDP_FIFO_UNDERFLOW)
+ int_mask0 &= ~BIT(11);
+ if (errors & DSI_DLN0_HS_FIFO_OVERFLOW)
+ int_mask0 &= ~BIT(16);
+ if (errors & DSI_DLN1_HS_FIFO_OVERFLOW)
+ int_mask0 &= ~BIT(17);
+ if (errors & DSI_DLN2_HS_FIFO_OVERFLOW)
+ int_mask0 &= ~BIT(18);
+ if (errors & DSI_DLN3_HS_FIFO_OVERFLOW)
+ int_mask0 &= ~BIT(19);
+ if (errors & DSI_DLN0_HS_FIFO_UNDERFLOW)
+ int_mask0 &= ~BIT(26);
+ if (errors & DSI_DLN1_HS_FIFO_UNDERFLOW)
+ int_mask0 &= ~BIT(27);
+ if (errors & DSI_DLN2_HS_FIFO_UNDERFLOW)
+ int_mask0 &= ~BIT(29);
+ if (errors & DSI_DLN3_HS_FIFO_UNDERFLOW)
+ int_mask0 &= ~BIT(30);
+
+ if (errors & DSI_INTERLEAVE_OP_CONTENTION)
+ int_mask0 &= ~BIT(8);
+
+ DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
+ DSI_W32(ctrl, DSI_ERR_INT_MASK0, int_mask0);
+
+ pr_debug("[DSI_%d] enable errors = 0x%llx, int_mask0=0x%x\n",
+ ctrl->index, errors, int_mask0);
+}
+
+/**
+ * video_test_pattern_setup() - setup test pattern engine for video mode
+ * @ctrl: Pointer to the controller host hardware.
+ * @type: Type of test pattern.
+ * @init_val: Initial value to use for generating test pattern.
+ */
+void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
+ enum dsi_test_pattern type,
+ u32 init_val)
+{
+ u32 reg = 0;
+
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, init_val);
+
+ switch (type) {
+ case DSI_TEST_PATTERN_FIXED:
+ reg |= (0x2 << 4);
+ break;
+ case DSI_TEST_PATTERN_INC:
+ reg |= (0x1 << 4);
+ break;
+ case DSI_TEST_PATTERN_POLY:
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_POLY, 0xF0F0F);
+ break;
+ default:
+ break;
+ }
+
+ DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL, 0x100);
+ DSI_W32(ctrl, DSI_TPG_VIDEO_CONFIG, 0x5);
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
+
+ pr_debug("[DSI_%d] Video test pattern setup done\n", ctrl->index);
+}
+
+/**
+ * cmd_test_pattern_setup() - setup test patttern engine for cmd mode
+ * @ctrl: Pointer to the controller host hardware.
+ * @type: Type of test pattern.
+ * @init_val: Initial value to use for generating test pattern.
+ * @stream_id: Stream Id on which packets are generated.
+ */
+void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl,
+ enum dsi_test_pattern type,
+ u32 init_val,
+ u32 stream_id)
+{
+ u32 reg = 0;
+ u32 init_offset;
+ u32 poly_offset;
+ u32 pattern_sel_shift;
+
+ switch (stream_id) {
+ case 0:
+ init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL0;
+ poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM0_POLY;
+ pattern_sel_shift = 8;
+ break;
+ case 1:
+ init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL1;
+ poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM1_POLY;
+ pattern_sel_shift = 12;
+ break;
+ case 2:
+ init_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_INIT_VAL2;
+ poly_offset = DSI_TEST_PATTERN_GEN_CMD_MDP_STREAM2_POLY;
+ pattern_sel_shift = 20;
+ break;
+ default:
+ return;
+ }
+
+ DSI_W32(ctrl, init_offset, init_val);
+
+ switch (type) {
+ case DSI_TEST_PATTERN_FIXED:
+ reg |= (0x2 << pattern_sel_shift);
+ break;
+ case DSI_TEST_PATTERN_INC:
+ reg |= (0x1 << pattern_sel_shift);
+ break;
+ case DSI_TEST_PATTERN_POLY:
+ DSI_W32(ctrl, poly_offset, 0xF0F0F);
+ break;
+ default:
+ break;
+ }
+
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
+ pr_debug("[DSI_%d] Cmd test pattern setup done\n", ctrl->index);
+}
+
+/**
+ * test_pattern_enable() - enable test pattern engine
+ * @ctrl: Pointer to the controller host hardware.
+ * @enable: Enable/Disable test pattern engine.
+ */
+void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl,
+ bool enable)
+{
+ u32 reg = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_CTRL);
+
+ if (enable)
+ reg |= BIT(0);
+ else
+ reg &= ~BIT(0);
+
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CTRL, reg);
+
+ pr_debug("[DSI_%d] Test pattern enable=%d\n", ctrl->index, enable);
+}
+
+/**
+ * trigger_cmd_test_pattern() - trigger a command mode frame update with
+ * test pattern
+ * @ctrl: Pointer to the controller host hardware.
+ * @stream_id: Stream on which frame update is sent.
+ */
+void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl,
+ u32 stream_id)
+{
+ switch (stream_id) {
+ case 0:
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM0_TRIGGER, 0x1);
+ break;
+ case 1:
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM1_TRIGGER, 0x1);
+ break;
+ case 2:
+ DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_CMD_STREAM2_TRIGGER, 0x1);
+ break;
+ default:
+ break;
+ }
+
+ pr_debug("[DSI_%d] Cmd Test pattern trigger\n", ctrl->index);
+}
+
+void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl)
+{
+ u32 status = 0;
+ /*
+ * Clear out any phy errors prior to exiting ULPS
+ * This fixes certain instances where phy does not exit
+ * ULPS cleanly. Also, do not print error during such cases.
+ */
+ status = DSI_R32(ctrl, DSI_DLN0_PHY_ERR);
+ if (status & 0x011111) {
+ DSI_W32(ctrl, DSI_DLN0_PHY_ERR, status);
+ pr_err("%s: phy_err_status = %x\n", __func__, status);
+ }
+}
+
+void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl,
+ bool enable)
+{
+ u32 reg = 0;
+
+ reg = DSI_MMSS_MISC_R32(ctrl, MMSS_MISC_CLAMP_REG_OFF);
+
+ /* Mask/unmask disable PHY reset bit */
+ if (enable)
+ reg |= BIT(30);
+ else
+ reg &= ~BIT(30);
+
+ DSI_MMSS_MISC_W32(ctrl, MMSS_MISC_CLAMP_REG_OFF, reg);
+}
+
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg_1_4.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h
similarity index 98%
rename from drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg_1_4.h
rename to drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h
index 028ad46..34e9e72 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg_1_4.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_reg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -187,6 +187,7 @@
#define DSI_SECURE_DISPLAY_STATUS (0x02CC)
#define DSI_SECURE_DISPLAY_BLOCK_COMMAND_COLOR (0x02D0)
#define DSI_SECURE_DISPLAY_BLOCK_VIDEO_COLOR (0x02D4)
+#define DSI_LOGICAL_LANE_SWAP_CTRL (0x0310)
#endif /* _DSI_CTRL_REG_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index 2caa32e..a30fdb5 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -70,22 +70,6 @@
};
/**
- * enum dsi_data_lanes - dsi physical lanes
- * @DSI_DATA_LANE_0: Physical lane 0
- * @DSI_DATA_LANE_1: Physical lane 1
- * @DSI_DATA_LANE_2: Physical lane 2
- * @DSI_DATA_LANE_3: Physical lane 3
- * @DSI_CLOCK_LANE: Physical clock lane
- */
-enum dsi_data_lanes {
- DSI_DATA_LANE_0 = BIT(0),
- DSI_DATA_LANE_1 = BIT(1),
- DSI_DATA_LANE_2 = BIT(2),
- DSI_DATA_LANE_3 = BIT(3),
- DSI_CLOCK_LANE = BIT(4)
-};
-
-/**
* enum dsi_logical_lane - dsi logical lanes
* @DSI_LOGICAL_LANE_0: Logical lane 0
* @DSI_LOGICAL_LANE_1: Logical lane 1
@@ -104,6 +88,63 @@
};
/**
+ * enum dsi_data_lanes - BIT map for DSI data lanes
+ * This is used to identify the active DSI data lanes for
+ * various operations like DSI data lane enable/ULPS/clamp
+ * configurations.
+ * @DSI_DATA_LANE_0: BIT(DSI_LOGICAL_LANE_0)
+ * @DSI_DATA_LANE_1: BIT(DSI_LOGICAL_LANE_1)
+ * @DSI_DATA_LANE_2: BIT(DSI_LOGICAL_LANE_2)
+ * @DSI_DATA_LANE_3: BIT(DSI_LOGICAL_LANE_3)
+ * @DSI_CLOCK_LANE: BIT(DSI_LOGICAL_CLOCK_LANE)
+ */
+enum dsi_data_lanes {
+ DSI_DATA_LANE_0 = BIT(DSI_LOGICAL_LANE_0),
+ DSI_DATA_LANE_1 = BIT(DSI_LOGICAL_LANE_1),
+ DSI_DATA_LANE_2 = BIT(DSI_LOGICAL_LANE_2),
+ DSI_DATA_LANE_3 = BIT(DSI_LOGICAL_LANE_3),
+ DSI_CLOCK_LANE = BIT(DSI_LOGICAL_CLOCK_LANE)
+};
+
+/**
+ * enum dsi_phy_data_lanes - dsi physical lanes
+ * used for DSI logical to physical lane mapping
+ * @DSI_PHYSICAL_LANE_INVALID: Physical lane valid/invalid
+ * @DSI_PHYSICAL_LANE_0: Physical lane 0
+ * @DSI_PHYSICAL_LANE_1: Physical lane 1
+ * @DSI_PHYSICAL_LANE_2: Physical lane 2
+ * @DSI_PHYSICAL_LANE_3: Physical lane 3
+ */
+enum dsi_phy_data_lanes {
+ DSI_PHYSICAL_LANE_INVALID = 0,
+ DSI_PHYSICAL_LANE_0 = BIT(0),
+ DSI_PHYSICAL_LANE_1 = BIT(1),
+ DSI_PHYSICAL_LANE_2 = BIT(2),
+ DSI_PHYSICAL_LANE_3 = BIT(3)
+};
+
+enum dsi_lane_map_type_v1 {
+ DSI_LANE_MAP_0123,
+ DSI_LANE_MAP_3012,
+ DSI_LANE_MAP_2301,
+ DSI_LANE_MAP_1230,
+ DSI_LANE_MAP_0321,
+ DSI_LANE_MAP_1032,
+ DSI_LANE_MAP_2103,
+ DSI_LANE_MAP_3210,
+};
+
+/**
+ * lane_map: DSI logical <-> physical lane mapping
+ * lane_map_v1: Lane mapping for DSI controllers < v2.0
+ * lane_map_v2: Lane mapping for DSI controllers >= 2.0
+ */
+struct dsi_lane_map {
+ enum dsi_lane_map_type_v1 lane_map_v1;
+ u8 lane_map_v2[DSI_LANE_MAX - 1];
+};
+
+/**
* enum dsi_trigger_type - dsi trigger type
* @DSI_TRIGGER_NONE: No trigger.
* @DSI_TRIGGER_TE: TE trigger.
@@ -224,20 +265,6 @@
};
/**
- * struct dsi_lane_mapping - Mapping between DSI logical and physical lanes
- * @physical_lane0: Logical lane to which physical lane 0 is mapped.
- * @physical_lane1: Logical lane to which physical lane 1 is mapped.
- * @physical_lane2: Logical lane to which physical lane 2 is mapped.
- * @physical_lane3: Logical lane to which physical lane 3 is mapped.
- */
-struct dsi_lane_mapping {
- enum dsi_logical_lane physical_lane0;
- enum dsi_logical_lane physical_lane1;
- enum dsi_logical_lane physical_lane2;
- enum dsi_logical_lane physical_lane3;
-};
-
-/**
* struct dsi_host_common_cfg - Host configuration common to video and cmd mode
* @dst_format: Destination pixel format.
* @data_lanes: Physical data lanes to be enabled.
@@ -247,6 +274,7 @@
* @mdp_cmd_trigger: MDP frame update trigger for command mode.
* @dma_cmd_trigger: Command DMA trigger.
* @cmd_trigger_stream: Command mode stream to trigger.
+ * @swap_mode: DSI color swap mode.
* @bit_swap_read: Is red color bit swapped.
* @bit_swap_green: Is green color bit swapped.
* @bit_swap_blue: Is blue color bit swapped.
@@ -281,7 +309,6 @@
/**
* struct dsi_video_engine_cfg - DSI video engine configuration
- * @host_cfg: Pointer to host common configuration.
* @last_line_interleave_en: Allow command mode op interleaved on last line of
* video stream.
* @pulse_mode_hsa_he: Send HSA and HE following VS/VE packet if set to
@@ -309,8 +336,6 @@
/**
* struct dsi_cmd_engine_cfg - DSI command engine configuration
- * @host_cfg: Pointer to host common configuration.
- * @host_cfg: Common host configuration
* @max_cmd_packets_interleave Maximum number of command mode RGB packets to
* send with in one horizontal blanking period
* of the video mode frame.
@@ -339,7 +364,6 @@
* @bit_clk_rate_hz: Bit clock frequency in Hz.
* @video_timing: Video timing information of a frame.
* @lane_map: Mapping between logical and physical lanes.
- * @phy_type: PHY type to be used.
*/
struct dsi_host_config {
enum dsi_op_mode panel_mode;
@@ -351,7 +375,7 @@
u64 esc_clk_rate_hz;
u64 bit_clk_rate_hz;
struct dsi_mode_info video_timing;
- struct dsi_lane_mapping lane_map;
+ struct dsi_lane_map lane_map;
};
/**
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 06f9ccb..a39ebb7 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -582,6 +582,25 @@
return 0;
}
+static int dsi_display_phy_reset_config(struct dsi_display *display,
+ bool enable)
+{
+ int rc = 0;
+ int i;
+ struct dsi_display_ctrl *ctrl;
+
+ for (i = 0 ; i < display->ctrl_count; i++) {
+ ctrl = &display->ctrl[i];
+ rc = dsi_ctrl_phy_reset_config(ctrl->ctrl, enable);
+ if (rc) {
+ pr_err("[%s] failed to %s phy reset, rc=%d\n",
+ display->name, enable ? "mask" : "unmask", rc);
+ return rc;
+ }
+ }
+ return 0;
+}
+
static int dsi_display_ctrl_init(struct dsi_display *display)
{
int rc = 0;
@@ -1344,7 +1363,7 @@
if (mmss_clamp)
dsi_display_ctrl_setup(display);
- if (display->ulps_enabled) {
+ if (display->ulps_enabled && mmss_clamp) {
/*
* ULPS Entry Request. This is needed if the lanes were
* in ULPS prior to power collapse, since after
@@ -1467,16 +1486,109 @@
return rc;
}
+static void __set_lane_map_v2(u8 *lane_map_v2,
+ enum dsi_phy_data_lanes lane0,
+ enum dsi_phy_data_lanes lane1,
+ enum dsi_phy_data_lanes lane2,
+ enum dsi_phy_data_lanes lane3)
+{
+ lane_map_v2[DSI_LOGICAL_LANE_0] = lane0;
+ lane_map_v2[DSI_LOGICAL_LANE_1] = lane1;
+ lane_map_v2[DSI_LOGICAL_LANE_2] = lane2;
+ lane_map_v2[DSI_LOGICAL_LANE_3] = lane3;
+}
static int dsi_display_parse_lane_map(struct dsi_display *display)
{
- int rc = 0;
+ int rc = 0, i = 0;
+ const char *data;
+ u8 temp[DSI_LANE_MAX - 1];
- display->lane_map.physical_lane0 = DSI_LOGICAL_LANE_0;
- display->lane_map.physical_lane1 = DSI_LOGICAL_LANE_1;
- display->lane_map.physical_lane2 = DSI_LOGICAL_LANE_2;
- display->lane_map.physical_lane3 = DSI_LOGICAL_LANE_3;
- return rc;
+ if (!display) {
+ pr_err("invalid params\n");
+ return -EINVAL;
+ }
+
+ /* lane-map-v2 supersedes lane-map-v1 setting */
+ rc = of_property_read_u8_array(display->pdev->dev.of_node,
+ "qcom,lane-map-v2", temp, (DSI_LANE_MAX - 1));
+ if (!rc) {
+ for (i = DSI_LOGICAL_LANE_0; i < (DSI_LANE_MAX - 1); i++)
+ display->lane_map.lane_map_v2[i] = BIT(temp[i]);
+ return 0;
+ } else if (rc != EINVAL) {
+ pr_warn("Incorrect mapping, configure default\n");
+ goto set_default;
+ }
+
+ /* lane-map older version, for DSI controller version < 2.0 */
+ data = of_get_property(display->pdev->dev.of_node,
+ "qcom,lane-map", NULL);
+ if (!data)
+ goto set_default;
+
+ if (!strcmp(data, "lane_map_3012")) {
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_3012;
+ __set_lane_map_v2(display->lane_map.lane_map_v2,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_0);
+ } else if (!strcmp(data, "lane_map_2301")) {
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_2301;
+ __set_lane_map_v2(display->lane_map.lane_map_v2,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_1);
+ } else if (!strcmp(data, "lane_map_1230")) {
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_1230;
+ __set_lane_map_v2(display->lane_map.lane_map_v2,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_2);
+ } else if (!strcmp(data, "lane_map_0321")) {
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_0321;
+ __set_lane_map_v2(display->lane_map.lane_map_v2,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_1);
+ } else if (!strcmp(data, "lane_map_1032")) {
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_1032;
+ __set_lane_map_v2(display->lane_map.lane_map_v2,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_2);
+ } else if (!strcmp(data, "lane_map_2103")) {
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_2103;
+ __set_lane_map_v2(display->lane_map.lane_map_v2,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_3);
+ } else if (!strcmp(data, "lane_map_3210")) {
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_3210;
+ __set_lane_map_v2(display->lane_map.lane_map_v2,
+ DSI_PHYSICAL_LANE_3,
+ DSI_PHYSICAL_LANE_2,
+ DSI_PHYSICAL_LANE_1,
+ DSI_PHYSICAL_LANE_0);
+ } else {
+ pr_warn("%s: invalid lane map %s specified. defaulting to lane_map0123\n",
+ __func__, data);
+ goto set_default;
+ }
+ return 0;
+
+set_default:
+ /* default lane mapping */
+ __set_lane_map_v2(display->lane_map.lane_map_v2, DSI_PHYSICAL_LANE_0,
+ DSI_PHYSICAL_LANE_1, DSI_PHYSICAL_LANE_2, DSI_PHYSICAL_LANE_3);
+ display->lane_map.lane_map_v1 = DSI_LANE_MAP_0123;
+ return 0;
}
static int dsi_display_parse_dt(struct dsi_display *display)
@@ -1535,11 +1647,6 @@
display->panel_of = of_node;
}
- rc = dsi_display_parse_lane_map(display);
- if (rc) {
- pr_err("Lane map not found, rc=%d\n", rc);
- goto error;
- }
error:
return rc;
}
@@ -1578,6 +1685,12 @@
goto error_ctrl_put;
}
+ rc = dsi_display_parse_lane_map(display);
+ if (rc) {
+ pr_err("Lane map not found, rc=%d\n", rc);
+ goto error_ctrl_put;
+ }
+
rc = dsi_display_clocks_init(display);
if (rc) {
pr_err("Failed to parse clock data, rc=%d\n", rc);
@@ -1978,7 +2091,6 @@
display->name, rc);
goto error;
}
-
}
error:
return rc;
@@ -2317,7 +2429,6 @@
display->display_type = "unknown";
mutex_init(&display->display_lock);
-
display->pdev = pdev;
platform_set_drvdata(pdev, display);
mutex_lock(&dsi_display_list_lock);
@@ -2773,11 +2884,18 @@
goto error_phy_disable;
}
+ rc = dsi_display_phy_reset_config(display, true);
+ if (rc) {
+ pr_err("[%s] failed to setup DSI controller, rc=%d\n",
+ display->name, rc);
+ goto error_ctrl_deinit;
+ }
+
rc = dsi_display_set_clk_src(display);
if (rc) {
pr_err("[%s] failed to set DSI link clock source, rc=%d\n",
display->name, rc);
- goto error_ctrl_deinit;
+ goto error_phy_reset_off;
}
rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
@@ -2785,7 +2903,7 @@
if (rc) {
pr_err("[%s] failed to enable DSI link clocks, rc=%d\n",
display->name, rc);
- goto error_ctrl_deinit;
+ goto error_phy_reset_off;
}
rc = dsi_display_ctrl_host_enable(display);
@@ -2808,6 +2926,8 @@
error_ctrl_link_off:
(void)dsi_display_clk_ctrl(display->dsi_clk_handle,
DSI_LINK_CLK, DSI_CLK_OFF);
+error_phy_reset_off:
+ (void)dsi_display_phy_reset_config(display, false);
error_ctrl_deinit:
(void)dsi_display_ctrl_deinit(display);
error_phy_disable:
@@ -2991,6 +3111,11 @@
pr_err("[%s] failed to disable DSI PHY, rc=%d\n",
display->name, rc);
+ rc = dsi_display_phy_reset_config(display, false);
+ if (rc)
+ pr_err("[%s] failed to disable DSI PHY reset config, rc=%d\n",
+ display->name, rc);
+
rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
DSI_CORE_CLK, DSI_CLK_OFF);
if (rc)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index 1c1f4b4..563c525 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -149,7 +149,7 @@
struct dsi_display_clk_info clock_info;
struct dsi_host_config config;
- struct dsi_lane_mapping lane_map;
+ struct dsi_lane_map lane_map;
u32 num_of_modes;
bool is_tpg_enabled;
bool ulps_enabled;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
index 4249ac4..27cee05 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
@@ -697,9 +697,9 @@
pr_debug("[PHY_%d] TODO: perform validation\n", phy->index);
memcpy(&phy->mode, &config->video_timing, sizeof(phy->mode));
+ memcpy(&phy->cfg.lane_map, &config->lane_map, sizeof(config->lane_map));
phy->data_lanes = config->common_config.data_lanes;
phy->dst_format = config->common_config.dst_format;
- phy->lane_map = config->lane_map;
phy->cfg.pll_source = pll_source;
rc = phy->hw.ops.calculate_timing_params(&phy->hw,
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
index d8bfd15..a2b19505 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
@@ -67,7 +67,6 @@
* @mode: Current mode.
* @data_lanes: Number of data lanes used.
* @dst_format: Destination format.
- * @lane_map: Map between logical and physical lanes.
*/
struct msm_dsi_phy {
struct platform_device *pdev;
@@ -89,7 +88,6 @@
struct dsi_mode_info mode;
enum dsi_data_lanes data_lanes;
enum dsi_pixel_format dst_format;
- struct dsi_lane_mapping lane_map;
};
/**
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
index 78c59e2..1f5618f 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
@@ -80,6 +80,7 @@
* @timing: Timing parameters for lanes.
* @regulators: Regulator settings for lanes.
* @pll_source: PLL source.
+ * @lane_map: DSI logical to PHY lane mapping.
*/
struct dsi_phy_cfg {
struct dsi_phy_per_lane_cfgs lanecfg;
@@ -87,6 +88,7 @@
struct dsi_phy_per_lane_cfgs timing;
struct dsi_phy_per_lane_cfgs regulators;
enum dsi_phy_pll_source pll_source;
+ struct dsi_lane_map lane_map;
};
struct dsi_phy_hw;