@@ -844,10 +844,9 @@ bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc,
844844EXPORT_SYMBOL (drm_crtc_vblank_helper_get_vblank_timestamp );
845845
846846/**
847- * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
848- * vblank interval
849- * @dev: DRM device
850- * @pipe: index of CRTC whose vblank timestamp to retrieve
847+ * drm_crtc_get_last_vbltimestamp - retrieve raw timestamp for the most
848+ * recent vblank interval
849+ * @crtc: CRTC whose vblank timestamp to retrieve
851850 * @tvblank: Pointer to target time which should receive the timestamp
852851 * @in_vblank_irq:
853852 * True when called from drm_crtc_handle_vblank(). Some drivers
@@ -865,19 +864,16 @@ EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp);
865864 * True if timestamp is considered to be very precise, false otherwise.
866865 */
867866static bool
868- drm_get_last_vbltimestamp (struct drm_device * dev , unsigned int pipe ,
869- ktime_t * tvblank , bool in_vblank_irq )
867+ drm_crtc_get_last_vbltimestamp (struct drm_crtc * crtc , ktime_t * tvblank ,
868+ bool in_vblank_irq )
870869{
871- struct drm_crtc * crtc = drm_crtc_from_index (dev , pipe );
872870 bool ret = false;
873871
874872 /* Define requested maximum error on timestamps (nanoseconds). */
875873 int max_error = (int ) drm_timestamp_precision * 1000 ;
876874
877875 /* Query driver if possible and precision timestamping enabled. */
878876 if (crtc && crtc -> funcs -> get_vblank_timestamp && max_error > 0 ) {
879- struct drm_crtc * crtc = drm_crtc_from_index (dev , pipe );
880-
881877 ret = crtc -> funcs -> get_vblank_timestamp (crtc , & max_error ,
882878 tvblank , in_vblank_irq );
883879 }
@@ -891,6 +887,15 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
891887 return ret ;
892888}
893889
890+ static bool
891+ drm_get_last_vbltimestamp (struct drm_device * dev , unsigned int pipe ,
892+ ktime_t * tvblank , bool in_vblank_irq )
893+ {
894+ struct drm_crtc * crtc = drm_crtc_from_index (dev , pipe );
895+
896+ return drm_crtc_get_last_vbltimestamp (crtc , tvblank , in_vblank_irq );
897+ }
898+
894899/**
895900 * drm_crtc_vblank_count - retrieve "cooked" vblank counter value
896901 * @crtc: which counter to retrieve
@@ -980,6 +985,36 @@ u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
980985}
981986EXPORT_SYMBOL (drm_crtc_vblank_count_and_time );
982987
988+ /**
989+ * drm_crtc_next_vblank_start - calculate the time of the next vblank
990+ * @crtc: the crtc for which to calculate next vblank time
991+ * @vblanktime: pointer to time to receive the next vblank timestamp.
992+ *
993+ * Calculate the expected time of the start of the next vblank period,
994+ * based on time of previous vblank and frame duration
995+ */
996+ int drm_crtc_next_vblank_start (struct drm_crtc * crtc , ktime_t * vblanktime )
997+ {
998+ unsigned int pipe = drm_crtc_index (crtc );
999+ struct drm_vblank_crtc * vblank = & crtc -> dev -> vblank [pipe ];
1000+ struct drm_display_mode * mode = & vblank -> hwmode ;
1001+ u64 vblank_start ;
1002+
1003+ if (!vblank -> framedur_ns || !vblank -> linedur_ns )
1004+ return - EINVAL ;
1005+
1006+ if (!drm_crtc_get_last_vbltimestamp (crtc , vblanktime , false))
1007+ return - EINVAL ;
1008+
1009+ vblank_start = DIV_ROUND_DOWN_ULL (
1010+ (u64 )vblank -> framedur_ns * mode -> crtc_vblank_start ,
1011+ mode -> crtc_vtotal );
1012+ * vblanktime = ktime_add (* vblanktime , ns_to_ktime (vblank_start ));
1013+
1014+ return 0 ;
1015+ }
1016+ EXPORT_SYMBOL (drm_crtc_next_vblank_start );
1017+
9831018static void send_vblank_event (struct drm_device * dev ,
9841019 struct drm_pending_vblank_event * e ,
9851020 u64 seq , ktime_t now )
0 commit comments