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