req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
                req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
                break;
+       case DRM_CAP_TIMESTAMP_MONOTONIC:
+               req->value = drm_timestamp_monotonic;
+               break;
        default:
                return -EINVAL;
        }
 
 
                /* 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();
 
                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
 }
 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.
        }
 
        /* 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;
 }
                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);
 }
 
 unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
 EXPORT_SYMBOL(drm_timestamp_precision);
 
+/*
+ * Default to use monotonic timestamps for wait-for-vblank and page-flip
+ * complete events.
+ */
+unsigned int drm_timestamp_monotonic = 1;
+
 MODULE_AUTHOR(CORE_AUTHOR);
 MODULE_DESCRIPTION(CORE_DESC);
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output");
 MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]");
 MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
+MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
 
 module_param_named(debug, drm_debug, int, 0600);
 module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
 module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
+module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
 
 struct idr drm_minors_idr;
 
 
 
 extern unsigned int drm_vblank_offdelay;
 extern unsigned int drm_timestamp_precision;
+extern unsigned int drm_timestamp_monotonic;
 
 extern struct class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
 #define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
 #define DRM_CAP_DUMB_PREFER_SHADOW 0x4
 #define DRM_CAP_PRIME 0x5
+#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
 
 #define DRM_PRIME_CAP_IMPORT 0x1
 #define DRM_PRIME_CAP_EXPORT 0x2