Ver Fonte

disp: msm: sde: update flush mask in fence error case

Add a new clear_flush_mask ops in sde_hw_ctl_ops.
Flush mask update to cancel the fence error frame with
the new ops.

Change-Id: I8d03d8e83a05a652789fb38e885a3c8497e4d262
Signed-off-by: GG Hou <[email protected]>
GG Hou há 2 anos atrás
pai
commit
ee2ee3b129
4 ficheiros alterados com 31 adições e 0 exclusões
  1. 11 0
      msm/sde/sde_encoder.c
  2. 2 0
      msm/sde/sde_encoder_phys.h
  3. 11 0
      msm/sde/sde_hw_ctl.c
  4. 7 0
      msm/sde/sde_hw_ctl.h

+ 11 - 0
msm/sde/sde_encoder.c

@@ -2225,6 +2225,11 @@ int sde_encoder_hw_fence_error_handle(struct drm_encoder *drm_enc)
 		}
 	}
 
+	if (phys_enc->hw_ctl->ops.clear_flush_mask) {
+		phys_enc->hw_ctl->ops.clear_flush_mask(phys_enc->hw_ctl, true);
+		SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_CASE2);
+	}
+
 	phys_enc->sde_hw_fence_error_status = false;
 	SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_EXIT);
 	return rc;
@@ -4234,6 +4239,12 @@ static inline void _sde_encoder_trigger_flush(struct drm_encoder *drm_enc,
 		ctl->ops.update_bitmask(ctl, SDE_HW_FLUSH_PERIPH, phys->hw_intf->idx, 1);
 	}
 
+	/* update flush mask to ignore fence error frame commit */
+	if (ctl->ops.clear_flush_mask && phys->fence_error_handle_in_progress) {
+		ctl->ops.clear_flush_mask(ctl, false);
+		SDE_EVT32(DRMID(drm_enc), SDE_EVTLOG_FUNC_CASE1);
+	}
+
 	if ((extra_flush && extra_flush->pending_flush_mask)
 			&& ctl->ops.update_pending_flush)
 		ctl->ops.update_pending_flush(ctl, extra_flush);

+ 2 - 0
msm/sde/sde_encoder_phys.h

@@ -132,6 +132,7 @@ struct sde_encoder_virt_ops {
  * @handle_post_kickoff:	Do any work necessary post-kickoff work
  * @trigger_flush:		Process flush event on physical encoder
  * @trigger_start:		Process start event on physical encoder
+ * @clear_flush_mask:		clear flush mask
  * @needs_single_flush:		Whether encoder slaves need to be flushed
  * @setup_misr:		Sets up MISR, enable and disables based on sysfs
  * @collect_misr:		Collects MISR data on frame update
@@ -186,6 +187,7 @@ struct sde_encoder_phys_ops {
 	void (*handle_post_kickoff)(struct sde_encoder_phys *phys_enc);
 	void (*trigger_flush)(struct sde_encoder_phys *phys_enc);
 	void (*trigger_start)(struct sde_encoder_phys *phys_enc);
+	void (*clear_flush_mask)(struct sde_encoder_phys *phys_enc, bool clear);
 	bool (*needs_single_flush)(struct sde_encoder_phys *phys_enc);
 
 	void (*setup_misr)(struct sde_encoder_phys *phys_encs,

+ 11 - 0
msm/sde/sde_hw_ctl.c

@@ -29,6 +29,7 @@
 #define CTL_SW_RESET                  0x030
 #define CTL_SW_RESET_OVERRIDE         0x060
 #define CTL_STATUS                    0x064
+#define CTL_FLUSH_MASK                0x090
 #define CTL_LAYER_EXTN_OFFSET         0x40
 #define CTL_ROT_TOP                   0x0C0
 #define CTL_ROT_FLUSH                 0x0C4
@@ -476,6 +477,15 @@ static inline int sde_hw_ctl_trigger_pending(struct sde_hw_ctl *ctx)
 	return 0;
 }
 
+static inline int sde_hw_ctl_clear_flush_mask(struct sde_hw_ctl *ctx, bool clear)
+{
+	if (!ctx)
+		return -EINVAL;
+
+	SDE_REG_WRITE(&ctx->hw, CTL_FLUSH_MASK, clear ? 0xffffffff : 0);
+	return 0;
+}
+
 static inline int sde_hw_ctl_clear_pending_flush(struct sde_hw_ctl *ctx)
 {
 	if (!ctx)
@@ -1476,6 +1486,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops,
 		ops->update_bitmask = sde_hw_ctl_update_bitmask;
 		ops->get_ctl_intf = sde_hw_ctl_get_intf;
 	}
+	ops->clear_flush_mask = sde_hw_ctl_clear_flush_mask;
 	ops->clear_pending_flush = sde_hw_ctl_clear_pending_flush;
 	ops->get_pending_flush = sde_hw_ctl_get_pending_flush;
 	ops->get_flush_register = sde_hw_ctl_get_flush_register;

+ 7 - 0
msm/sde/sde_hw_ctl.h

@@ -284,6 +284,13 @@ struct sde_hw_ctl_ops {
 	 */
 	void (*uidle_enable)(struct sde_hw_ctl *ctx, bool enable);
 
+	/**
+	 * clear flush mask
+	 * @ctx       : ctl path ctx pointer
+	 * @clear     : true to clear the flush mask
+	 */
+	int (*clear_flush_mask)(struct sde_hw_ctl *ctx, bool clear);
+
 	/**
 	 * Clear the value of the cached pending_flush_mask
 	 * No effect on hardware