Browse Source

disp: msm: sde: request hard reset on vsync timeout

During frame updates if vsync timeout happens, the probable reason
is pixel_clock is turned off. In such a case the recent update is
not applied on hw and can lead to issues. For example if a pipe
was detached it will not get detached since this update will not
take place.
This change detects the timeout and requests a hard reset from user mode
driver so as to ensure that all the displays are power off and footswitch
is turned off. This will ensure dpu hardware gets reset.

Change-Id: Ic9bade88b6502feb7334d239eaf669977233dbac
Signed-off-by: Abhijit Kulkarni <[email protected]>
Abhijit Kulkarni 4 years ago
parent
commit
91a070feb3
1 changed files with 10 additions and 1 deletions
  1. 10 1
      msm/sde/sde_encoder_phys_vid.c

+ 10 - 1
msm/sde/sde_encoder_phys_vid.c

@@ -877,12 +877,15 @@ static int _sde_encoder_phys_vid_wait_for_vblank(
 	u32 event = SDE_ENCODER_FRAME_EVENT_ERROR |
 	u32 event = SDE_ENCODER_FRAME_EVENT_ERROR |
 		SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE |
 		SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE |
 		SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
 		SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
+	struct drm_connector *conn;
 
 
 	if (!phys_enc) {
 	if (!phys_enc) {
 		pr_err("invalid encoder\n");
 		pr_err("invalid encoder\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
+	conn = phys_enc->connector;
+
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
 	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
 	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
 	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
@@ -893,10 +896,16 @@ static int _sde_encoder_phys_vid_wait_for_vblank(
 
 
 	if (notify && (ret == -ETIMEDOUT) &&
 	if (notify && (ret == -ETIMEDOUT) &&
 	    atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0) &&
 	    atomic_add_unless(&phys_enc->pending_retire_fence_cnt, -1, 0) &&
-	    phys_enc->parent_ops.handle_frame_done)
+	    phys_enc->parent_ops.handle_frame_done) {
 		phys_enc->parent_ops.handle_frame_done(
 		phys_enc->parent_ops.handle_frame_done(
 			phys_enc->parent, phys_enc, event);
 			phys_enc->parent, phys_enc, event);
 
 
+		if (sde_encoder_recovery_events_enabled(phys_enc->parent))
+			sde_connector_event_notify(conn,
+				DRM_EVENT_SDE_HW_RECOVERY,
+				sizeof(uint8_t), SDE_RECOVERY_HARD_RESET);
+	}
+
 	SDE_EVT32(DRMID(phys_enc->parent), event, notify, ret,
 	SDE_EVT32(DRMID(phys_enc->parent), event, notify, ret,
 			ret ? SDE_EVTLOG_FATAL : 0);
 			ret ? SDE_EVTLOG_FATAL : 0);
 	return ret;
 	return ret;