Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0136db7d authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "drm/msm/sde: add recovery mechanism if TE signal not received"

parents 0043cf40 979009e7
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -694,7 +694,7 @@ static int dsi_display_status_check_te(struct dsi_display *display)
	reinit_completion(&display->esd_te_gate);
	if (!wait_for_completion_timeout(&display->esd_te_gate,
				esd_te_timeout)) {
		pr_err("ESD check failed\n");
		pr_err("TE check failed\n");
		rc = -EINVAL;
	}

@@ -703,7 +703,7 @@ static int dsi_display_status_check_te(struct dsi_display *display)
	return rc;
}

int dsi_display_check_status(void *display)
int dsi_display_check_status(void *display, bool te_check_override)
{
	struct dsi_display *dsi_display = display;
	struct dsi_panel *panel;
@@ -713,18 +713,20 @@ int dsi_display_check_status(void *display)
	if (dsi_display == NULL)
		return -EINVAL;

	panel = dsi_display->panel;

	status_mode = panel->esd_config.status_mode;

	mutex_lock(&dsi_display->display_lock);

	panel = dsi_display->panel;
	if (!panel->panel_initialized) {
		pr_debug("Panel not initialized\n");
		mutex_unlock(&dsi_display->display_lock);
		return rc;
	}

	if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio))
		status_mode = ESD_MODE_PANEL_TE;
	else
		status_mode = panel->esd_config.status_mode;

	dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
		DSI_ALL_CLKS, DSI_CLK_ON);

+2 −1
Original line number Diff line number Diff line
@@ -581,8 +581,9 @@ int dsi_display_set_backlight(void *display, u32 bl_lvl);
/**
 * dsi_display_check_status() - check if panel is dead or alive
 * @display:            Handle to display.
 * @te_check_override:	Whether check for TE from panel or default check
 */
int dsi_display_check_status(void *display);
int dsi_display_check_status(void *display, bool te_check_override);

/**
 * dsi_display_cmd_transfer() - transfer command to the panel
+51 −12
Original line number Diff line number Diff line
@@ -1731,12 +1731,59 @@ sde_connector_best_encoder(struct drm_connector *connector)
	return c_conn->encoder;
}

static void _sde_connector_report_panel_dead(struct sde_connector *conn)
{
	struct drm_event event;
	bool panel_dead = true;

	if (!conn)
		return;

	event.type = DRM_EVENT_PANEL_DEAD;
	event.length = sizeof(bool);
	msm_mode_object_event_notify(&conn->base.base,
		conn->base.dev, &event, (u8 *)&panel_dead);
	sde_encoder_display_failure_notification(conn->encoder);
	SDE_EVT32(SDE_EVTLOG_ERROR);
	SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n",
			conn->base.base.id, conn->encoder->base.id);
}

int sde_connector_esd_status(struct drm_connector *conn)
{
	struct sde_connector *sde_conn = NULL;
	int ret = 0;

	if (!conn)
		return ret;

	sde_conn = to_sde_connector(conn);
	if (!sde_conn || !sde_conn->ops.check_status)
		return ret;

	/* protect this call with ESD status check call */
	mutex_lock(&sde_conn->lock);
	ret = sde_conn->ops.check_status(sde_conn->display, true);
	mutex_unlock(&sde_conn->lock);

	if (ret <= 0) {
		/* cancel if any pending esd work */
		sde_connector_schedule_status_work(conn, false);
		_sde_connector_report_panel_dead(sde_conn);
		ret = -ETIMEDOUT;
	} else {
		SDE_DEBUG("Successfully received TE from panel\n");
		ret = 0;
	}
	SDE_EVT32(ret);

	return ret;
}

static void sde_connector_check_status_work(struct work_struct *work)
{
	struct sde_connector *conn;
	struct drm_event event;
	int rc = 0;
	bool panel_dead = false;

	conn = container_of(to_delayed_work(work),
			struct sde_connector, status_work);
@@ -1753,7 +1800,7 @@ static void sde_connector_check_status_work(struct work_struct *work)
		return;
	}

	rc = conn->ops.check_status(conn->display);
	rc = conn->ops.check_status(conn->display, false);
	mutex_unlock(&conn->lock);

	if (conn->force_panel_dead) {
@@ -1777,15 +1824,7 @@ static void sde_connector_check_status_work(struct work_struct *work)
	}

status_dead:
	SDE_EVT32(rc, SDE_EVTLOG_ERROR);
	SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n",
			conn->base.base.id, conn->encoder->base.id);
	panel_dead = true;
	event.type = DRM_EVENT_PANEL_DEAD;
	event.length = sizeof(bool);
	msm_mode_object_event_notify(&conn->base.base,
		conn->base.dev, &event, (u8 *)&panel_dead);
	sde_encoder_display_failure_notification(conn->encoder);
	_sde_connector_report_panel_dead(conn);
}

static const struct drm_connector_helper_funcs sde_connector_helper_ops = {
+9 −1
Original line number Diff line number Diff line
@@ -228,9 +228,10 @@ struct sde_connector_ops {
	/**
	 * check_status - check status of connected display panel
	 * @display: Pointer to private display handle
	 * @te_check_override: Whether check TE from panel or default check
	 * Returns: positive value for success, negetive or zero for failure
	 */
	int (*check_status)(void *display);
	int (*check_status)(void *display, bool te_check_override);

	/**
	 * cmd_transfer - Transfer command to the connected display panel
@@ -770,4 +771,11 @@ void sde_connector_helper_bridge_disable(struct drm_connector *connector);
 */
int sde_connector_get_panel_vfp(struct drm_connector *connector,
	struct drm_display_mode *mode);

/**
 * sde_connector_esd_status - helper function to check te status
 * @connector: Pointer to DRM connector object
 */
int sde_connector_esd_status(struct drm_connector *connector);

#endif /* _SDE_CONNECTOR_H_ */
+7 −2
Original line number Diff line number Diff line
@@ -473,6 +473,10 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
			atomic_read(&phys_enc->pending_kickoff_cnt),
			frame_event);

	/* check if panel is still sending TE signal or not */
	if (sde_connector_esd_status(phys_enc->connector))
		goto exit;

	if (cmd_enc->pp_timeout_report_cnt >= PP_TIMEOUT_MAX_TRIALS) {
		cmd_enc->pp_timeout_report_cnt = PP_TIMEOUT_MAX_TRIALS;
		frame_event |= SDE_ENCODER_FRAME_EVENT_PANEL_DEAD;
@@ -490,11 +494,12 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
		SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FATAL);
	}

	atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);

	/* request a ctl reset before the next kickoff */
	phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET;

exit:
	atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);

	if (phys_enc->parent_ops.handle_frame_done)
		phys_enc->parent_ops.handle_frame_done(
				phys_enc->parent, phys_enc, frame_event);