From b965fdcee5358b42cd2d7a8ee1a45d05e4d24042 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Mon, 28 Sep 2020 12:26:52 -0700 Subject: [PATCH] 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 --- msm/sde/sde_crtc.c | 4 ++-- msm/sde/sde_encoder.c | 29 +++++++++++++++++++++-------- msm/sde/sde_encoder.h | 4 ++-- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index a87ed19e80..6fb56208ce 100644 --- a/msm/sde/sde_crtc.c +++ b/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); } diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 27cc33b046..55fe39c268 100644 --- a/msm/sde/sde_encoder.c +++ b/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); } } diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index 2051e5732e..6f9559aafd 100644 --- a/msm/sde/sde_encoder.h +++ b/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