Explorar o código

disp: msm: sde: update retire-fence with precise vsync timestamp

Retire fence for frames are signaled based on vsync. Use the HW
vsync timestamp counter to calculate the precise vsync timestamp
and update the retire fence signal timestamp. This will offset
all IRQ and SW delays and sends the precise timestamp. Avoid
calculating the timestamp on error or panel dead events and
set the current ktime for those cases.

Change-Id: Ic762f7cd6daead9c8fdcb0f8aad6386cf980407d
Signed-off-by: Veera Sundaram Sankaran <[email protected]>
Veera Sundaram Sankaran %!s(int64=4) %!d(string=hai) anos
pai
achega
b965fdcee5
Modificáronse 3 ficheiros con 25 adicións e 12 borrados
  1. 2 2
      msm/sde/sde_crtc.c
  2. 21 8
      msm/sde/sde_encoder.c
  3. 2 2
      msm/sde/sde_encoder.h

+ 2 - 2
msm/sde/sde_crtc.c

@@ -2279,7 +2279,7 @@ static void _sde_crtc_dest_scaler_setup(struct drm_crtc *crtc)
 	}
 }
 
-static void sde_crtc_frame_event_cb(void *data, u32 event)
+static void sde_crtc_frame_event_cb(void *data, u32 event, ktime_t ts)
 {
 	struct drm_crtc *crtc = (struct drm_crtc *)data;
 	struct sde_crtc *sde_crtc;
@@ -2349,9 +2349,9 @@ static void sde_crtc_frame_event_cb(void *data, u32 event)
 	}
 
 	fevent->event = event;
+	fevent->ts = ts;
 	fevent->crtc = crtc;
 	fevent->connector = cb_data->connector;
-	fevent->ts = ktime_get();
 	kthread_queue_work(&priv->event_thread[crtc_id].worker, &fevent->work);
 }
 

+ 21 - 8
msm/sde/sde_encoder.c

@@ -3225,7 +3225,7 @@ void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc,
 }
 
 void sde_encoder_register_frame_event_callback(struct drm_encoder *drm_enc,
-			void (*frame_event_cb)(void *, u32 event),
+			void (*frame_event_cb)(void *, u32 event, ktime_t ts),
 			struct drm_crtc *crtc)
 {
 	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
@@ -3252,14 +3252,16 @@ static void sde_encoder_frame_done_callback(
 		struct sde_encoder_phys *ready_phys, u32 event)
 {
 	struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
+	struct sde_kms *sde_kms = sde_encoder_get_kms(&sde_enc->base);
 	unsigned int i;
 	bool trigger = true;
 	bool is_cmd_mode = false;
 	enum sde_rm_topology_name topology = SDE_RM_TOPOLOGY_NONE;
+	ktime_t ts = 0;
 
-	if (!drm_enc || !sde_enc->cur_master) {
-		SDE_ERROR("invalid param: drm_enc %pK, cur_master %pK\n",
-				drm_enc, drm_enc ? sde_enc->cur_master : 0);
+	if (!sde_kms || !sde_enc->cur_master) {
+		SDE_ERROR("invalid param: sde_kms %pK, cur_master %pK\n",
+				sde_kms, sde_enc->cur_master);
 		return;
 	}
 
@@ -3268,6 +3270,19 @@ static void sde_encoder_frame_done_callback(
 	if (sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE))
 		is_cmd_mode = true;
 
+	/* get precise vsync timestamp for retire fence, if precise vsync timestamp is enabled */
+	if (sde_kms->catalog->has_precise_vsync_ts
+	    && (event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE)
+	    && (!(event & (SDE_ENCODER_FRAME_EVENT_ERROR | SDE_ENCODER_FRAME_EVENT_PANEL_DEAD))))
+		ts = sde_encoder_calc_last_vsync_timestamp(drm_enc);
+
+	/*
+	 * get current ktime for other events and when precise timestamp is not
+	 * available for retire-fence
+	 */
+	if (!ts)
+		ts = ktime_get();
+
 	if (event & (SDE_ENCODER_FRAME_EVENT_DONE
 			| SDE_ENCODER_FRAME_EVENT_ERROR
 			| SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) && is_cmd_mode) {
@@ -3301,15 +3316,13 @@ static void sde_encoder_frame_done_callback(
 		if (trigger) {
 			if (sde_enc->crtc_frame_event_cb)
 				sde_enc->crtc_frame_event_cb(
-					&sde_enc->crtc_frame_event_cb_data,
-					event);
+					&sde_enc->crtc_frame_event_cb_data, event, ts);
 			for (i = 0; i < sde_enc->num_phys_encs; i++)
 				atomic_add_unless(&sde_enc->frame_done_cnt[i],
 						-1, 0);
 		}
 	} else if (sde_enc->crtc_frame_event_cb) {
-		sde_enc->crtc_frame_event_cb(
-				&sde_enc->crtc_frame_event_cb_data, event);
+		sde_enc->crtc_frame_event_cb(&sde_enc->crtc_frame_event_cb_data, event, ts);
 	}
 }
 

+ 2 - 2
msm/sde/sde_encoder.h

@@ -226,7 +226,7 @@ struct sde_encoder_virt {
 	struct dentry *debugfs_root;
 	struct mutex enc_lock;
 	atomic_t frame_done_cnt[MAX_PHYS_ENCODERS_PER_VIRTUAL];
-	void (*crtc_frame_event_cb)(void *data, u32 event);
+	void (*crtc_frame_event_cb)(void *data, u32 event, ktime_t ts);
 	struct sde_kms_frame_event_cb_data crtc_frame_event_cb_data;
 
 	struct sde_rsc_client *rsc_client;
@@ -300,7 +300,7 @@ void sde_encoder_register_vblank_callback(struct drm_encoder *encoder,
  * @crtc:	pointer to drm_crtc object interested in frame events
  */
 void sde_encoder_register_frame_event_callback(struct drm_encoder *encoder,
-		void (*cb)(void *, u32), struct drm_crtc *crtc);
+		void (*cb)(void *, u32, ktime_t), struct drm_crtc *crtc);
 
 /**
  * sde_encoder_get_rsc_client - gets the rsc client state for primary