aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
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 /drivers/gpu
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')
-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
3 files changed, 31 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