浏览代码

Merge "disp: msm: sde: compute timeouts based on refresh rate"

qctecmdr 3 年之前
父节点
当前提交
4ec64c1672

+ 19 - 0
msm/sde/sde_crtc.c

@@ -2681,6 +2681,25 @@ u32 sde_crtc_get_dfps_maxfps(struct drm_crtc *crtc)
 	return 0;
 }
 
+struct drm_encoder *sde_crtc_get_src_encoder_of_clone(struct drm_crtc *crtc)
+{
+	struct drm_encoder *enc;
+	struct sde_crtc *sde_crtc;
+
+	if (!crtc || !crtc->dev)
+		return NULL;
+
+	sde_crtc = to_sde_crtc(crtc);
+	drm_for_each_encoder_mask(enc, crtc->dev, sde_crtc->cached_encoder_mask) {
+		if (sde_encoder_in_clone_mode(enc))
+			continue;
+
+		return enc;
+	}
+
+	return NULL;
+}
+
 static void sde_crtc_vblank_cb(void *data, ktime_t ts)
 {
 	struct drm_crtc *crtc = (struct drm_crtc *)data;

+ 6 - 0
msm/sde/sde_crtc.h

@@ -1057,4 +1057,10 @@ void _sde_crtc_clear_dim_layers_v1(struct drm_crtc_state *state);
  */
 void sde_crtc_cancel_delayed_work(struct drm_crtc *crtc);
 
+/*
+ * sde_crtc_get_src_encoder_of_clone- find source encoder of a clone mode encoder
+ * @cstate:      Pointer to DRM crtc object
+ */
+struct drm_encoder *sde_crtc_get_src_encoder_of_clone(struct drm_crtc *crtc);
+
 #endif /* _SDE_CRTC_H_ */

+ 27 - 1
msm/sde/sde_encoder.c

@@ -61,7 +61,7 @@
 		(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
 		##__VA_ARGS__)
 
-
+#define SEC_TO_MILLI_SEC		1000
 
 #define MISR_BUFF_SIZE			256
 
@@ -4482,6 +4482,32 @@ void sde_encoder_get_transfer_time(struct drm_encoder *drm_enc,
 	*transfer_time_us = info->mdp_transfer_time_us;
 }
 
+u32 sde_encoder_helper_get_kickoff_timeout_ms(struct drm_encoder *drm_enc)
+{
+	struct drm_encoder *src_enc = drm_enc;
+	struct sde_encoder_virt *sde_enc;
+	u32 fps;
+
+	if (!drm_enc) {
+		SDE_ERROR("invalid encoder\n");
+		return DEFAULT_KICKOFF_TIMEOUT_MS;
+	}
+
+	if (sde_encoder_in_clone_mode(drm_enc))
+		src_enc = sde_crtc_get_src_encoder_of_clone(drm_enc->crtc);
+
+	if (!src_enc)
+		return DEFAULT_KICKOFF_TIMEOUT_MS;
+
+	sde_enc = to_sde_encoder_virt(src_enc);
+	fps = sde_enc->mode_info.frame_rate;
+
+	if (!fps || fps >= DEFAULT_TIMEOUT_FPS_THRESHOLD)
+		return DEFAULT_KICKOFF_TIMEOUT_MS;
+	else
+		return (SEC_TO_MILLI_SEC / fps) * 2;
+}
+
 int sde_encoder_get_avr_status(struct drm_encoder *drm_enc)
 {
 	struct sde_encoder_virt *sde_enc;

+ 3 - 0
msm/sde/sde_encoder.h

@@ -51,6 +51,9 @@
 #define IDLE_POWERCOLLAPSE_DURATION	(66 - 16/2)
 #define IDLE_POWERCOLLAPSE_IN_EARLY_WAKEUP (200 - 16/2)
 
+/* below this fps limit, timeouts are adjusted based on fps */
+#define DEFAULT_TIMEOUT_FPS_THRESHOLD            24
+
 /**
  * Encoder functions and data types
  * @intfs:	Interfaces this encoder is using, INTF_MODE_NONE if unused

+ 10 - 2
msm/sde/sde_encoder_phys.h

@@ -22,8 +22,7 @@
 #define SDE_ENCODER_NAME_MAX	16
 
 /* wait for at most 2 vsync for lowest refresh rate (24hz) */
-#define KICKOFF_TIMEOUT_MS		84
-#define KICKOFF_TIMEOUT_JIFFIES		msecs_to_jiffies(KICKOFF_TIMEOUT_MS)
+#define DEFAULT_KICKOFF_TIMEOUT_MS		84
 
 #define MAX_TE_PROFILE_COUNT		5
 /**
@@ -286,6 +285,7 @@ struct sde_encoder_irq {
  * @pending_retire_fence_cnt:   Atomic counter tracking the pending retire
  *                              fences that have to be signalled.
  * @pending_kickoff_wq:		Wait queue for blocking until kickoff completes
+ * @kickoff_timeout_ms:		kickoff timeout in mill seconds
  * @irq:			IRQ tracking structures
  * @has_intf_te:		Interface TE configuration support
  * @cont_splash_enabled:	Variable to store continuous splash settings.
@@ -332,6 +332,7 @@ struct sde_encoder_phys {
 	atomic_t pending_kickoff_cnt;
 	atomic_t pending_retire_fence_cnt;
 	wait_queue_head_t pending_kickoff_wq;
+	u32 kickoff_timeout_ms;
 	struct sde_encoder_irq irq[INTR_IDX_MAX];
 	bool has_intf_te;
 	bool cont_splash_enabled;
@@ -539,6 +540,13 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
 void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
 		struct sde_hw_pp_vsync_info *info);
 
+/**
+ * sde_encoder_helper_get_kickoff_timeout_ms- get the kickoff timeout value based on fps
+ * @drm_enc: Pointer to drm encoder structure
+ * Returns: Kickoff timeout in milli seconds
+ */
+u32 sde_encoder_helper_get_kickoff_timeout_ms(struct drm_encoder *drm_enc);
+
 /**
  * sde_encoder_helper_trigger_flush - control flush helper function
  *	This helper function may be optionally specified by physical

+ 16 - 9
msm/sde/sde_encoder_phys_cmd.c

@@ -37,11 +37,13 @@
 #define AUTOREFRESH_SEQ2_POLL_TIMEOUT	1000000
 
 static inline int _sde_encoder_phys_cmd_get_idle_timeout(
-		struct sde_encoder_phys_cmd *cmd_enc)
+		struct sde_encoder_phys *phys_enc)
 {
+	u32 timeout = phys_enc->kickoff_timeout_ms;
+	struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
+
 	return cmd_enc->autorefresh.cfg.frame_count ?
-			cmd_enc->autorefresh.cfg.frame_count *
-			KICKOFF_TIMEOUT_MS : KICKOFF_TIMEOUT_MS;
+			cmd_enc->autorefresh.cfg.frame_count * timeout : timeout;
 }
 
 static inline bool sde_encoder_phys_cmd_is_master(
@@ -450,6 +452,9 @@ static void sde_encoder_phys_cmd_mode_set(
 	}
 
 	_sde_encoder_phys_cmd_setup_irq_hw_idx(phys_enc);
+
+	phys_enc->kickoff_timeout_ms =
+		sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
 }
 
 static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
@@ -708,7 +713,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
 
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
-	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
+	wait_info.timeout_ms = phys_enc->kickoff_timeout_ms;
 
 	/* slave encoder doesn't enable for ppsplit */
 	if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
@@ -748,7 +753,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done(
 
 	wait_info.wq = &cmd_enc->autorefresh.kickoff_wq;
 	wait_info.atomic_cnt = &cmd_enc->autorefresh.kickoff_cnt;
-	wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(cmd_enc);
+	wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(phys_enc);
 
 	/* wait for autorefresh kickoff to start */
 	ret = sde_encoder_helper_wait_for_irq(phys_enc,
@@ -1427,11 +1432,11 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
 	}
 	ctl = phys_enc->hw_ctl;
 	c_conn = to_sde_connector(phys_enc->connector);
-	timeout_ms = KICKOFF_TIMEOUT_MS;
+	timeout_ms = phys_enc->kickoff_timeout_ms;
 
 	if (c_conn->lp_mode == SDE_MODE_DPMS_LP1 ||
 		c_conn->lp_mode == SDE_MODE_DPMS_LP2)
-		timeout_ms = (KICKOFF_TIMEOUT_MS) * 2;
+		timeout_ms = timeout_ms * 2;
 
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
@@ -1649,7 +1654,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank(
 
 	wait_info.wq = &cmd_enc->pending_vblank_wq;
 	wait_info.atomic_cnt = &cmd_enc->pending_vblank_cnt;
-	wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(cmd_enc);
+	wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(phys_enc);
 
 	atomic_inc(&cmd_enc->pending_vblank_cnt);
 
@@ -1696,6 +1701,7 @@ static void _sde_encoder_autorefresh_disable_seq1(
 		struct sde_encoder_phys *phys_enc)
 {
 	int trial = 0;
+	u32 timeout_ms = phys_enc->kickoff_timeout_ms;
 	struct sde_encoder_phys_cmd *cmd_enc =
 				to_sde_encoder_phys_cmd(phys_enc);
 
@@ -1712,7 +1718,7 @@ static void _sde_encoder_autorefresh_disable_seq1(
 	do {
 		udelay(AUTOREFRESH_SEQ1_POLL_TIME);
 		if ((trial * AUTOREFRESH_SEQ1_POLL_TIME)
-				> (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
+				> (timeout_ms * USEC_PER_MSEC)) {
 			SDE_ERROR_CMDENC(cmd_enc,
 					"disable autorefresh failed\n");
 
@@ -1954,6 +1960,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
 	phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
 	cmd_enc->stream_sel = 0;
 	phys_enc->enable_state = SDE_ENC_DISABLED;
+	phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
 	sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
 	phys_enc->comp_type = p->comp_type;
 

+ 5 - 1
msm/sde/sde_encoder_phys_vid.c

@@ -656,6 +656,9 @@ static void sde_encoder_phys_vid_mode_set(
 	}
 
 	_sde_encoder_phys_vid_setup_irq_hw_idx(phys_enc);
+
+	phys_enc->kickoff_timeout_ms =
+		sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
 }
 
 static int sde_encoder_phys_vid_control_vblank_irq(
@@ -888,7 +891,7 @@ static int _sde_encoder_phys_vid_wait_for_vblank(
 
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
-	wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
+	wait_info.timeout_ms = phys_enc->kickoff_timeout_ms;
 
 	/* Wait for kickoff to complete */
 	ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
@@ -1360,6 +1363,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
 	phys_enc->enc_spinlock = p->enc_spinlock;
 	phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
 	phys_enc->comp_type = p->comp_type;
+	phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
 	for (i = 0; i < INTR_IDX_MAX; i++) {
 		irq = &phys_enc->irq[i];
 		INIT_LIST_HEAD(&irq->cb.list);

+ 5 - 2
msm/sde/sde_encoder_phys_wb.c

@@ -1402,6 +1402,9 @@ static void sde_encoder_phys_wb_mode_set(
 			PTR_ERR(phys_enc->hw_cdm));
 		phys_enc->hw_cdm = NULL;
 	}
+
+	phys_enc->kickoff_timeout_ms =
+		sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
 }
 
 static int sde_encoder_phys_wb_frame_timeout(struct sde_encoder_phys *phys_enc)
@@ -1508,7 +1511,7 @@ static int _sde_encoder_phys_wb_wait_for_commit_done(
 	wait_info.wq = &phys_enc->pending_kickoff_wq;
 	wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
 	wait_info.timeout_ms = max_t(u32, wb_enc->wbdone_timeout,
-		KICKOFF_TIMEOUT_MS);
+			phys_enc->kickoff_timeout_ms);
 	rc = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_WB_DONE,
 		&wait_info);
 	if (rc == -ETIMEDOUT && _sde_encoder_phys_wb_is_idle(phys_enc)) {
@@ -2037,9 +2040,9 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init(
 		ret = -ENOMEM;
 		goto fail_alloc;
 	}
-	wb_enc->wbdone_timeout = KICKOFF_TIMEOUT_MS;
 
 	phys_enc = &wb_enc->base;
+	phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
 
 	if (p->sde_kms->vbif[VBIF_NRT]) {
 		wb_enc->aspace[SDE_IOMMU_DOMAIN_UNSECURE] =