|
@@ -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);
|