Merge "disp: msm: dsi: implement ESD recovery cleanup"

This commit is contained in:
qctecmdr
2021-11-02 14:52:25 -07:00
committed by Gerrit - the friendly Code Review server
4 changed files with 95 additions and 20 deletions

View File

@@ -448,9 +448,7 @@ static void dsi_ctrl_post_cmd_transfer(struct dsi_ctrl *dsi_ctrl)
if (rc) if (rc)
DSI_CTRL_ERR(dsi_ctrl, "failed to disable command engine\n"); DSI_CTRL_ERR(dsi_ctrl, "failed to disable command engine\n");
if (dsi_ctrl->pending_cmd_flags & DSI_CTRL_CMD_READ) 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); dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, false);
mutex_unlock(&dsi_ctrl->ctrl_lock); mutex_unlock(&dsi_ctrl->ctrl_lock);
@@ -1909,16 +1907,18 @@ static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl)
return rc; 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 (!enable) {
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0);
} else {
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE && 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.bllp_lp11_en &&
!dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en) !dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en)
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00A0);
0xFF00A0);
else else
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
0xFF00E0); }
} }
static int dsi_ctrl_drv_state_init(struct dsi_ctrl *dsi_ctrl) 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->host_config.common_config);
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0); 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); 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->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", DSI_CTRL_DEBUG(dsi_ctrl, "Host initialization complete, skip op: %d\n",
skip_op); skip_op);
@@ -3417,9 +3417,7 @@ int dsi_ctrl_transfer_prepare(struct dsi_ctrl *dsi_ctrl, u32 flags)
mutex_lock(&dsi_ctrl->ctrl_lock); mutex_lock(&dsi_ctrl->ctrl_lock);
if (flags & DSI_CTRL_CMD_READ) if (!(flags & DSI_CTRL_CMD_READ))
mask |= BIT(DSI_FIFO_UNDERFLOW);
dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, true); dsi_ctrl_mask_error_status_interrupts(dsi_ctrl, mask, true);
rc = dsi_ctrl_set_cmd_engine_state(dsi_ctrl, DSI_CTRL_ENGINE_ON, false); rc = dsi_ctrl_set_cmd_engine_state(dsi_ctrl, DSI_CTRL_ENGINE_ON, false);

View File

@@ -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); 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_ */ #endif /* _DSI_CTRL_H_ */

View File

@@ -1411,6 +1411,22 @@ void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
{ {
u32 int_ctrl = 0; u32 int_ctrl = 0;
u32 int_mask0 = 0x7FFF3BFF; 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); int_ctrl = DSI_R32(ctrl, DSI_INT_CTRL);
if (errors) if (errors)

View File

@@ -921,6 +921,19 @@ static int dsi_display_status_check_te(struct dsi_display *display,
return rc; 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, int dsi_display_check_status(struct drm_connector *connector, void *display,
bool te_check_override) 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_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) { if (status_mode == ESD_MODE_REG_READ) {
rc = dsi_display_status_reg_read(dsi_display); rc = dsi_display_status_reg_read(dsi_display);
} else if (status_mode == ESD_MODE_SW_BTA) { } 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 */ /* Handle Panel failures during display disable sequence */
if (rc <=0) if (rc <=0)
atomic_set(&panel->esd_recovery_pending, 1); 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: release_panel_lock:
dsi_panel_release_panel_lock(panel); dsi_panel_release_panel_lock(panel);
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT, rc); 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; 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; cmd->ctrl_flags = flags;
dsi_display_set_cmd_tx_ctrl_flags(display, cmd); dsi_display_set_cmd_tx_ctrl_flags(display, cmd);
rc = dsi_ctrl_transfer_prepare(m_ctrl->ctrl, cmd->ctrl_flags); rc = dsi_ctrl_transfer_prepare(m_ctrl->ctrl, cmd->ctrl_flags);
if (rc) { if (rc) {
DSI_ERR("prepare for rx cmd transfer failed rc = %d\n", 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); rc = dsi_ctrl_cmd_transfer(m_ctrl->ctrl, cmd);
if (rc <= 0) if (rc <= 0)
DSI_ERR("rx cmd transfer failed rc = %d\n", rc); DSI_ERR("rx cmd transfer failed rc = %d\n", rc);
dsi_ctrl_transfer_unprepare(m_ctrl->ctrl, cmd->ctrl_flags); 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: release_panel_lock:
dsi_panel_release_panel_lock(display->panel); dsi_panel_release_panel_lock(display->panel);
return rc; 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, int dsi_pre_clkoff_cb(void *priv,
enum dsi_clk_type clk, enum dsi_clk_type clk,
enum dsi_lclk_type l_type, 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) && if ((clk & DSI_LINK_CLK) && (new_state == DSI_CLK_OFF) &&
(l_type & DSI_LINK_LP_CLK)) { (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 * If continuous clock is enabled then disable it
* before entering into ULPS Mode. * before entering into ULPS Mode.
@@ -3777,6 +3827,13 @@ int dsi_post_clkoff_cb(void *priv,
return -EINVAL; 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) && if ((clk_type & DSI_CORE_CLK) &&
(curr_state == DSI_CLK_OFF)) { (curr_state == DSI_CLK_OFF)) {
rc = dsi_display_phy_power_off(display); rc = dsi_display_phy_power_off(display);