Explorar el Código

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

qctecmdr hace 3 años
padre
commit
24057ec69c
Se han modificado 4 ficheros con 95 adiciones y 20 borrados
  1. 17 19
      msm/dsi/dsi_ctrl.c
  2. 4 0
      msm/dsi/dsi_ctrl.h
  3. 16 0
      msm/dsi/dsi_ctrl_hw_cmn.c
  4. 58 1
      msm/dsi/dsi_display.c

+ 17 - 19
msm/dsi/dsi_ctrl.c

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

+ 4 - 0
msm/dsi/dsi_ctrl.h

@@ -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_ */

+ 16 - 0
msm/dsi/dsi_ctrl_hw_cmn.c

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

+ 58 - 1
msm/dsi/dsi_display.c

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