summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2012-10-23 18:53:26 +0000
committerDave Airlie <airlied@redhat.com>2012-11-20 16:06:16 +1000
commitc61eef726a78ae77b6ce223d01ea2130f465fe5c (patch)
tree7bd310556195005b5c4c1cbadadc9da1fbf5163c /drivers/gpu/drm/drm_irq.c
parente62f2f5acba1d466da047983ae16f6b96b68b310 (diff)
drm: add support for monotonic vblank timestamps
Jumps in the vblank and page flip event timestamps cause trouble for clients, so we should avoid them. The timestamp we get currently with gettimeofday can jump, so use instead monotonic timestamps. For backward compatibility use a module flag to revert back to using gettimeofday timestamps. Add also a DRM_CAP_TIMESTAMP_MONOTONIC flag that is simply a read only version of the module flag, so that clients can query this without depending on sysfs. Signed-off-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index ef5b5f70735..c0f0046d807 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -633,7 +633,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
/* Get system timestamp after query. */
etime = ktime_get();
- mono_time_offset = ktime_get_monotonic_offset();
+ if (!drm_timestamp_monotonic)
+ mono_time_offset = ktime_get_monotonic_offset();
preempt_enable();
@@ -691,7 +692,9 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
vbl_status |= 0x8;
}
- etime = ktime_sub(etime, mono_time_offset);
+ if (!drm_timestamp_monotonic)
+ etime = ktime_sub(etime, mono_time_offset);
+
/* save this only for debugging purposes */
tv_etime = ktime_to_timeval(etime);
/* Subtract time delta from raw timestamp to get final
@@ -714,6 +717,17 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
}
EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
+static struct timeval get_drm_timestamp(void)
+{
+ ktime_t now;
+
+ now = ktime_get();
+ if (!drm_timestamp_monotonic)
+ now = ktime_sub(now, ktime_get_monotonic_offset());
+
+ return ktime_to_timeval(now);
+}
+
/**
* drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
* vblank interval.
@@ -751,9 +765,9 @@ u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
}
/* GPU high precision timestamp query unsupported or failed.
- * Return gettimeofday timestamp as best estimate.
+ * Return current monotonic/gettimeofday timestamp as best estimate.
*/
- do_gettimeofday(tvblank);
+ *tvblank = get_drm_timestamp();
return 0;
}
@@ -842,7 +856,8 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc,
seq = drm_vblank_count_and_time(dev, crtc, &now);
} else {
seq = 0;
- do_gettimeofday(&now);
+
+ now = get_drm_timestamp();
}
send_vblank_event(dev, e, seq, &now);
}