aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2012-10-23 14:53:26 -0400
committerDave Airlie <airlied@redhat.com>2012-11-20 01:06:16 -0500
commitc61eef726a78ae77b6ce223d01ea2130f465fe5c (patch)
tree7bd310556195005b5c4c1cbadadc9da1fbf5163c
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>
-rw-r--r--drivers/gpu/drm/drm_ioctl.c3
-rw-r--r--drivers/gpu/drm/drm_irq.c25
-rw-r--r--drivers/gpu/drm/drm_stub.c8
-rw-r--r--include/drm/drmP.h1
-rw-r--r--include/uapi/drm/drm.h1
5 files changed, 33 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 23dd97506f28..e77bd8b57df2 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -287,6 +287,9 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
287 req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; 287 req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
288 req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0; 288 req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
289 break; 289 break;
290 case DRM_CAP_TIMESTAMP_MONOTONIC:
291 req->value = drm_timestamp_monotonic;
292 break;
290 default: 293 default:
291 return -EINVAL; 294 return -EINVAL;
292 } 295 }
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index ef5b5f70735e..c0f0046d8078 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,
633 633
634 /* Get system timestamp after query. */ 634 /* Get system timestamp after query. */
635 etime = ktime_get(); 635 etime = ktime_get();
636 mono_time_offset = ktime_get_monotonic_offset(); 636 if (!drm_timestamp_monotonic)
637 mono_time_offset = ktime_get_monotonic_offset();
637 638
638 preempt_enable(); 639 preempt_enable();
639 640
@@ -691,7 +692,9 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
691 vbl_status |= 0x8; 692 vbl_status |= 0x8;
692 } 693 }
693 694
694 etime = ktime_sub(etime, mono_time_offset); 695 if (!drm_timestamp_monotonic)
696 etime = ktime_sub(etime, mono_time_offset);
697
695 /* save this only for debugging purposes */ 698 /* save this only for debugging purposes */
696 tv_etime = ktime_to_timeval(etime); 699 tv_etime = ktime_to_timeval(etime);
697 /* Subtract time delta from raw timestamp to get final 700 /* 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,
714} 717}
715EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); 718EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
716 719
720static struct timeval get_drm_timestamp(void)
721{
722 ktime_t now;
723
724 now = ktime_get();
725 if (!drm_timestamp_monotonic)
726 now = ktime_sub(now, ktime_get_monotonic_offset());
727
728 return ktime_to_timeval(now);
729}
730
717/** 731/**
718 * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent 732 * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
719 * vblank interval. 733 * vblank interval.
@@ -751,9 +765,9 @@ u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc,
751 } 765 }
752 766
753 /* GPU high precision timestamp query unsupported or failed. 767 /* GPU high precision timestamp query unsupported or failed.
754 * Return gettimeofday timestamp as best estimate. 768 * Return current monotonic/gettimeofday timestamp as best estimate.
755 */ 769 */
756 do_gettimeofday(tvblank); 770 *tvblank = get_drm_timestamp();
757 771
758 return 0; 772 return 0;
759} 773}
@@ -842,7 +856,8 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc,
842 seq = drm_vblank_count_and_time(dev, crtc, &now); 856 seq = drm_vblank_count_and_time(dev, crtc, &now);
843 } else { 857 } else {
844 seq = 0; 858 seq = 0;
845 do_gettimeofday(&now); 859
860 now = get_drm_timestamp();
846 } 861 }
847 send_vblank_event(dev, e, seq, &now); 862 send_vblank_event(dev, e, seq, &now);
848} 863}
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 6fcdd8ebcb3d..200e104f1fa0 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -46,16 +46,24 @@ EXPORT_SYMBOL(drm_vblank_offdelay);
46unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ 46unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
47EXPORT_SYMBOL(drm_timestamp_precision); 47EXPORT_SYMBOL(drm_timestamp_precision);
48 48
49/*
50 * Default to use monotonic timestamps for wait-for-vblank and page-flip
51 * complete events.
52 */
53unsigned int drm_timestamp_monotonic = 1;
54
49MODULE_AUTHOR(CORE_AUTHOR); 55MODULE_AUTHOR(CORE_AUTHOR);
50MODULE_DESCRIPTION(CORE_DESC); 56MODULE_DESCRIPTION(CORE_DESC);
51MODULE_LICENSE("GPL and additional rights"); 57MODULE_LICENSE("GPL and additional rights");
52MODULE_PARM_DESC(debug, "Enable debug output"); 58MODULE_PARM_DESC(debug, "Enable debug output");
53MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); 59MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
54MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); 60MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
61MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
55 62
56module_param_named(debug, drm_debug, int, 0600); 63module_param_named(debug, drm_debug, int, 0600);
57module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); 64module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
58module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); 65module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
66module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
59 67
60struct idr drm_minors_idr; 68struct idr drm_minors_idr;
61 69
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 29eb23799aa4..fad21c927a38 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1505,6 +1505,7 @@ extern unsigned int drm_debug;
1505 1505
1506extern unsigned int drm_vblank_offdelay; 1506extern unsigned int drm_vblank_offdelay;
1507extern unsigned int drm_timestamp_precision; 1507extern unsigned int drm_timestamp_precision;
1508extern unsigned int drm_timestamp_monotonic;
1508 1509
1509extern struct class *drm_class; 1510extern struct class *drm_class;
1510extern struct proc_dir_entry *drm_proc_root; 1511extern struct proc_dir_entry *drm_proc_root;
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 1e3481edf062..8d1e2bbee83a 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -778,6 +778,7 @@ struct drm_event_vblank {
778#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3 778#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
779#define DRM_CAP_DUMB_PREFER_SHADOW 0x4 779#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
780#define DRM_CAP_PRIME 0x5 780#define DRM_CAP_PRIME 0x5
781#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
781 782
782#define DRM_PRIME_CAP_IMPORT 0x1 783#define DRM_PRIME_CAP_IMPORT 0x1
783#define DRM_PRIME_CAP_EXPORT 0x2 784#define DRM_PRIME_CAP_EXPORT 0x2