Merge "disp: msm: dsi: implement ESD recovery cleanup"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
24057ec69c
@@ -448,10 +448,8 @@ static void dsi_ctrl_post_cmd_transfer(struct dsi_ctrl *dsi_ctrl)
|
||||
if (rc)
|
||||
DSI_CTRL_ERR(dsi_ctrl, "failed to disable command engine\n");
|
||||
|
||||
if (dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_READ)
|
||||
mask |= BIT(DSI_FIFO_UNDERFLOW);
|
||||
|
||||
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, false);
|
||||
if (!(dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_READ))
|
||||
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, false);
|
||||
|
||||
mutex_unlock(&dsi_ctrl->ctrl_lock);
|
||||
|
||||
@@ -1909,16 +1907,18 @@ static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dsi_ctrl_enable_error_interrupts(struct dsi_ctrl *dsi_ctrl)
|
||||
void dsi_ctrl_toggle_error_interrupt_status(struct dsi_ctrl *dsi_ctrl, bool enable)
|
||||
{
|
||||
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE &&
|
||||
!dsi_ctrl->host_config.u.video_engine.bllp_lp11_en &&
|
||||
!dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en)
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw,
|
||||
0xFF00A0);
|
||||
else
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw,
|
||||
0xFF00E0);
|
||||
if (!enable) {
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0);
|
||||
} else {
|
||||
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE &&
|
||||
!dsi_ctrl->host_config.u.video_engine.bllp_lp11_en &&
|
||||
!dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en)
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00A0);
|
||||
else
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
|
||||
}
|
||||
}
|
||||
|
||||
static int dsi_ctrl_drv_state_init(struct dsi_ctrl *dsi_ctrl)
|
||||
@@ -2597,7 +2597,7 @@ int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
|
||||
&dsi_ctrl->host_config.common_config);
|
||||
|
||||
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
|
||||
dsi_ctrl_enable_error_interrupts(dsi_ctrl);
|
||||
dsi_ctrl_toggle_error_interrupt_status(dsi_ctrl, true);
|
||||
|
||||
dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);
|
||||
|
||||
@@ -3131,7 +3131,7 @@ int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool skip_op)
|
||||
}
|
||||
|
||||
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
|
||||
dsi_ctrl_enable_error_interrupts(dsi_ctrl);
|
||||
dsi_ctrl_toggle_error_interrupt_status(dsi_ctrl, true);
|
||||
|
||||
DSI_CTRL_DEBUG(dsi_ctrl, "Host initialization complete, skip op: %d\n",
|
||||
skip_op);
|
||||
@@ -3417,10 +3417,8 @@ int dsi_ctrl_transfer_prepare(struct dsi_ctrl *dsi_ctrl, u32 flags)
|
||||
|
||||
mutex_lock(&dsi_ctrl->ctrl_lock);
|
||||
|
||||
if (flags & DSI_CTRL_CMD_READ)
|
||||
mask |= BIT(DSI_FIFO_UNDERFLOW);
|
||||
|
||||
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, true);
|
||||
if (!(flags & DSI_CTRL_CMD_READ))
|
||||
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, true);
|
||||
|
||||
rc = dsi_ctrl_set_cmd_engine_state(dsi_ctrl, DSI_CTRL_ENGINE_ON, false);
|
||||
if (rc) {
|
||||
|
@@ -920,4 +920,8 @@ int dsi_ctrl_wait4dynamic_refresh_done(struct dsi_ctrl *ctrl);
|
||||
*/
|
||||
int dsi_ctrl_get_io_resources(struct msm_io_res *io_res);
|
||||
|
||||
/**
|
||||
* dsi_ctrl_toggle_error_interrupt_status() - Toggles error interrupt status
|
||||
*/
|
||||
void dsi_ctrl_toggle_error_interrupt_status(struct dsi_ctrl *dsi_ctrl, bool enable);
|
||||
#endif /* _DSI_CTRL_H_ */
|
||||
|
@@ -1411,6 +1411,22 @@ void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
|
||||
{
|
||||
u32 int_ctrl = 0;
|
||||
u32 int_mask0 = 0x7FFF3BFF;
|
||||
u32 dln0_phy_err = 0x11111;
|
||||
u32 fifo_status = 0xCCCC0789;
|
||||
u32 ack_error = 0x1193BFFF;
|
||||
u32 timeout_status = 0x11111111;
|
||||
u32 clk_status = 0x10000;
|
||||
u32 dsi_status_error = 0x80000000;
|
||||
u32 reg = 0;
|
||||
|
||||
DSI_W32(ctrl, DSI_DLN0_PHY_ERR, dln0_phy_err);
|
||||
DSI_W32(ctrl, DSI_FIFO_STATUS, fifo_status);
|
||||
DSI_W32(ctrl, DSI_TIMEOUT_STATUS, timeout_status);
|
||||
DSI_W32(ctrl, DSI_ACK_ERR_STATUS, ack_error);
|
||||
reg = DSI_R32(ctrl, DSI_CLK_STATUS);
|
||||
DSI_W32(ctrl, DSI_CLK_STATUS, reg | clk_status);
|
||||
reg = DSI_R32(ctrl, DSI_STATUS);
|
||||
DSI_W32(ctrl, DSI_STATUS, reg | dsi_status_error);
|
||||
|
||||
int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
|
||||
if (errors)
|
||||
|
@@ -921,6 +921,19 @@ static int dsi_display_status_check_te(struct dsi_display *display,
|
||||
return rc;
|
||||
}
|
||||
|
||||
void dsi_display_toggle_error_interrupt_status(struct dsi_display * display, bool enable)
|
||||
{
|
||||
int i = 0;
|
||||
struct dsi_display_ctrl *ctrl;
|
||||
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
if (!ctrl->ctrl)
|
||||
continue;
|
||||
dsi_ctrl_toggle_error_interrupt_status(ctrl->ctrl, enable);
|
||||
}
|
||||
}
|
||||
|
||||
int dsi_display_check_status(struct drm_connector *connector, void *display,
|
||||
bool te_check_override)
|
||||
{
|
||||
@@ -966,6 +979,11 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
|
||||
|
||||
dsi_display_set_ctrl_esd_check_flag(dsi_display, true);
|
||||
|
||||
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON);
|
||||
|
||||
/* Disable error interrupts while doing an ESD check */
|
||||
dsi_display_toggle_error_interrupt_status(dsi_display, false);
|
||||
|
||||
if (status_mode == ESD_MODE_REG_READ) {
|
||||
rc = dsi_display_status_reg_read(dsi_display);
|
||||
} else if (status_mode == ESD_MODE_SW_BTA) {
|
||||
@@ -990,7 +1008,11 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
|
||||
/* Handle Panel failures during display disable sequence */
|
||||
if (rc <=0)
|
||||
atomic_set(&panel->esd_recovery_pending, 1);
|
||||
else
|
||||
/* Enable error interrupts post an ESD success */
|
||||
dsi_display_toggle_error_interrupt_status(dsi_display, true);
|
||||
|
||||
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_OFF);
|
||||
release_panel_lock:
|
||||
dsi_panel_release_panel_lock(panel);
|
||||
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT, rc);
|
||||
@@ -1040,18 +1062,23 @@ static int dsi_display_cmd_rx(struct dsi_display *display,
|
||||
|
||||
flags = DSI_CTRL_CMD_READ;
|
||||
|
||||
dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON);
|
||||
dsi_display_toggle_error_interrupt_status(display, false);
|
||||
cmd->ctrl_flags = flags;
|
||||
dsi_display_set_cmd_tx_ctrl_flags(display, cmd);
|
||||
rc = dsi_ctrl_transfer_prepare(m_ctrl->ctrl, cmd->ctrl_flags);
|
||||
if (rc) {
|
||||
DSI_ERR("prepare for rx cmd transfer failed rc = %d\n", rc);
|
||||
goto release_panel_lock;
|
||||
goto enable_error_interrupts;
|
||||
}
|
||||
rc = dsi_ctrl_cmd_transfer(m_ctrl->ctrl, cmd);
|
||||
if (rc <= 0)
|
||||
DSI_ERR("rx cmd transfer failed rc = %d\n", rc);
|
||||
dsi_ctrl_transfer_unprepare(m_ctrl->ctrl, cmd->ctrl_flags);
|
||||
|
||||
enable_error_interrupts:
|
||||
dsi_display_toggle_error_interrupt_status(display, true);
|
||||
dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_OFF);
|
||||
release_panel_lock:
|
||||
dsi_panel_release_panel_lock(display->panel);
|
||||
return rc;
|
||||
@@ -3573,6 +3600,21 @@ static void dsi_display_ctrl_isr_configure(struct dsi_display *display, bool en)
|
||||
}
|
||||
}
|
||||
|
||||
static void dsi_display_cleanup_post_esd_failure(struct dsi_display *display)
|
||||
{
|
||||
int i = 0;
|
||||
struct dsi_display_ctrl *ctrl;
|
||||
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
if (!ctrl->ctrl)
|
||||
continue;
|
||||
|
||||
dsi_phy_lane_reset(ctrl->phy);
|
||||
dsi_ctrl_soft_reset(ctrl->ctrl);
|
||||
}
|
||||
}
|
||||
|
||||
int dsi_pre_clkoff_cb(void *priv,
|
||||
enum dsi_clk_type clk,
|
||||
enum dsi_lclk_type l_type,
|
||||
@@ -3584,6 +3626,14 @@ int dsi_pre_clkoff_cb(void *priv,
|
||||
|
||||
if ((clk & DSI_LINK_CLK) && (new_state == DSI_CLK_OFF) &&
|
||||
(l_type & DSI_LINK_LP_CLK)) {
|
||||
|
||||
/*
|
||||
* Clean up the DSI controller on a previous ESD failure. This requires a DSI
|
||||
* controller soft reset. Also reset PHY lanes before resetting controller.
|
||||
*/
|
||||
if (atomic_read(&display->panel->esd_recovery_pending))
|
||||
dsi_display_cleanup_post_esd_failure(display);
|
||||
|
||||
/*
|
||||
* If continuous clock is enabled then disable it
|
||||
* before entering into ULPS Mode.
|
||||
@@ -3777,6 +3827,13 @@ int dsi_post_clkoff_cb(void *priv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Reset PHY to clear the PHY status once the HS clocks are turned off */
|
||||
if ((clk_type & DSI_LINK_CLK) && (curr_state == DSI_CLK_OFF)
|
||||
&& (l_type == DSI_LINK_HS_CLK)) {
|
||||
if (atomic_read(&display->panel->esd_recovery_pending))
|
||||
dsi_display_phy_sw_reset(display);
|
||||
}
|
||||
|
||||
if ((clk_type & DSI_CORE_CLK) &&
|
||||
(curr_state == DSI_CLK_OFF)) {
|
||||
rc = dsi_display_phy_power_off(display);
|
||||
|
Reference in New Issue
Block a user