ソースを参照

Merge "disp: msm: reset lm blend stages for missing vsync"

qctecmdr 3 年 前
コミット
f1ae36dfab

+ 3 - 3
msm/sde/sde_crtc.c

@@ -3979,7 +3979,7 @@ int sde_crtc_reset_hw(struct drm_crtc *crtc, struct drm_crtc_state *old_state,
 			continue;
 
 		if (sde_encoder_get_intf_mode(encoder) == INTF_MODE_VIDEO)
-			sde_encoder_kickoff(encoder, false, true);
+			sde_encoder_kickoff(encoder, true);
 	}
 
 	/* panic the device if VBIF is not in good state */
@@ -4086,7 +4086,7 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc,
 		if (encoder->crtc != crtc)
 			continue;
 
-		sde_encoder_kickoff(encoder, false, true);
+		sde_encoder_kickoff(encoder, true);
 	}
 	sde_crtc->kickoff_in_progress = false;
 
@@ -7061,7 +7061,7 @@ void __sde_crtc_static_cache_read_work(struct kthread_work *work)
 		sde_plane_ctl_flush(plane, ctl, true);
 
 	/* kickoff encoder and wait for VBLANK */
-	sde_encoder_kickoff(drm_enc, false, false);
+	sde_encoder_kickoff(drm_enc, false);
 	sde_encoder_wait_for_event(drm_enc, MSM_ENC_VBLANK);
 
 	SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT);

+ 14 - 45
msm/sde/sde_encoder.c

@@ -3225,6 +3225,19 @@ void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
 	ctl->ops.clear_pending_flush(ctl);
 }
 
+void sde_encoder_helper_phys_reset(struct sde_encoder_phys *phys_enc)
+{
+	struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
+	struct sde_ctl_flush_cfg cfg;
+
+	ctl->ops.reset(ctl);
+	sde_encoder_helper_reset_mixers(phys_enc, NULL);
+	ctl->ops.get_pending_flush(ctl, &cfg);
+	SDE_EVT32(DRMID(phys_enc->parent), cfg.pending_flush_mask);
+	ctl->ops.trigger_flush(ctl);
+	ctl->ops.trigger_start(ctl);
+}
+
 static enum sde_intf sde_encoder_get_intf(struct sde_mdss_cfg *catalog,
 		enum sde_intf_type type, u32 controller_id)
 {
@@ -4357,47 +4370,7 @@ end:
 	return ret;
 }
 
-/**
- * _sde_encoder_reset_ctl_hw - reset h/w configuration for all ctl's associated
- *	with the specified encoder, and unstage all pipes from it
- * @encoder:	encoder pointer
- * Returns: 0 on success
- */
-static int _sde_encoder_reset_ctl_hw(struct drm_encoder *drm_enc)
-{
-	struct sde_encoder_virt *sde_enc;
-	struct sde_encoder_phys *phys;
-	unsigned int i;
-	int rc = 0;
-
-	if (!drm_enc) {
-		SDE_ERROR("invalid encoder\n");
-		return -EINVAL;
-	}
-
-	sde_enc = to_sde_encoder_virt(drm_enc);
-
-	SDE_ATRACE_BEGIN("encoder_release_lm");
-	SDE_DEBUG_ENC(sde_enc, "\n");
-
-	for (i = 0; i < sde_enc->num_phys_encs; i++) {
-		phys = sde_enc->phys_encs[i];
-		if (!phys)
-			continue;
-
-		SDE_EVT32(DRMID(drm_enc), phys->intf_idx - INTF_0);
-
-		rc = sde_encoder_helper_reset_mixers(phys, NULL);
-		if (rc)
-			SDE_EVT32(DRMID(drm_enc), rc, SDE_EVTLOG_ERROR);
-	}
-
-	SDE_ATRACE_END("encoder_release_lm");
-	return rc;
-}
-
-void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool is_error,
-		bool config_changed)
+void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool config_changed)
 {
 	struct sde_encoder_virt *sde_enc;
 	struct sde_encoder_phys *phys;
@@ -4412,10 +4385,6 @@ void sde_encoder_kickoff(struct drm_encoder *drm_enc, bool is_error,
 
 	SDE_DEBUG_ENC(sde_enc, "\n");
 
-	/* create a 'no pipes' commit to release buffers on errors */
-	if (is_error)
-		_sde_encoder_reset_ctl_hw(drm_enc);
-
 	if (sde_enc->delay_kickoff) {
 		u32 loop_count = 20;
 		u32 sleep = DELAY_KICKOFF_POLL_TIMEOUT_US / loop_count;

+ 1 - 4
msm/sde/sde_encoder.h

@@ -325,12 +325,9 @@ void sde_encoder_trigger_kickoff_pending(struct drm_encoder *encoder);
  * sde_encoder_kickoff - trigger a double buffer flip of the ctl path
  *	(i.e. ctl flush and start) immediately.
  * @encoder:	encoder pointer
- * @is_error:	whether the current commit needs to be aborted and replaced
- *		with a 'safe' commit
  * @config_changed: if true new configuration is applied on the control path
  */
-void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error,
-		bool config_changed);
+void sde_encoder_kickoff(struct drm_encoder *encoder, bool config_changed);
 
 /**
  * sde_encoder_wait_for_event - Waits for encoder events

+ 7 - 0
msm/sde/sde_encoder_phys.h

@@ -804,6 +804,13 @@ static inline bool sde_encoder_phys_needs_single_flush(
 void sde_encoder_helper_phys_disable(struct sde_encoder_phys *phys_enc,
 		struct sde_encoder_phys_wb *wb_enc);
 
+/**
+ * sde_encoder_helper_phys_reset - helper function to reset virt encoder
+ *                 if vsync is missing on phys encoder
+ * @phys_enc: Pointer to physical encoder structure
+ */
+void sde_encoder_helper_phys_reset(struct sde_encoder_phys *phys_enc);
+
 /**
  * sde_encoder_helper_setup_misr - helper function to setup misr
  * @phys_enc: Pointer to physical encoder structure

+ 13 - 1
msm/sde/sde_encoder_phys_vid.c

@@ -920,6 +920,18 @@ static int sde_encoder_phys_vid_wait_for_vblank(
 	return _sde_encoder_phys_vid_wait_for_vblank(phys_enc, true);
 }
 
+static int sde_encoder_phys_vid_wait_for_commit_done(
+		struct sde_encoder_phys *phys_enc)
+{
+	int rc;
+
+	rc =  _sde_encoder_phys_vid_wait_for_vblank(phys_enc, true);
+	if (rc)
+		sde_encoder_helper_phys_reset(phys_enc);
+
+	return rc;
+}
+
 static int sde_encoder_phys_vid_wait_for_vblank_no_notify(
 		struct sde_encoder_phys *phys_enc)
 {
@@ -1310,7 +1322,7 @@ static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops)
 	ops->destroy = sde_encoder_phys_vid_destroy;
 	ops->get_hw_resources = sde_encoder_phys_vid_get_hw_resources;
 	ops->control_vblank_irq = sde_encoder_phys_vid_control_vblank_irq;
-	ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_vblank;
+	ops->wait_for_commit_done = sde_encoder_phys_vid_wait_for_commit_done;
 	ops->wait_for_vblank = sde_encoder_phys_vid_wait_for_vblank_no_notify;
 	ops->wait_for_tx_complete = sde_encoder_phys_vid_wait_for_vblank;
 	ops->irq_control = sde_encoder_phys_vid_irq_control;