diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0c201d684584..fe6538297872 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -5252,21 +5252,22 @@ static void intel_unpin_work_fn(struct work_struct *__work) | |||
5252 | } | 5252 | } |
5253 | 5253 | ||
5254 | static void do_intel_finish_page_flip(struct drm_device *dev, | 5254 | static void do_intel_finish_page_flip(struct drm_device *dev, |
5255 | struct drm_crtc *crtc, | 5255 | struct drm_crtc *crtc) |
5256 | int called_before_vblirq) | ||
5257 | { | 5256 | { |
5258 | drm_i915_private_t *dev_priv = dev->dev_private; | 5257 | drm_i915_private_t *dev_priv = dev->dev_private; |
5259 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 5258 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
5260 | struct intel_unpin_work *work; | 5259 | struct intel_unpin_work *work; |
5261 | struct drm_i915_gem_object *obj; | 5260 | struct drm_i915_gem_object *obj; |
5262 | struct drm_pending_vblank_event *e; | 5261 | struct drm_pending_vblank_event *e; |
5263 | struct timeval now; | 5262 | struct timeval tnow, tvbl; |
5264 | unsigned long flags; | 5263 | unsigned long flags; |
5265 | 5264 | ||
5266 | /* Ignore early vblank irqs */ | 5265 | /* Ignore early vblank irqs */ |
5267 | if (intel_crtc == NULL) | 5266 | if (intel_crtc == NULL) |
5268 | return; | 5267 | return; |
5269 | 5268 | ||
5269 | do_gettimeofday(&tnow); | ||
5270 | |||
5270 | spin_lock_irqsave(&dev->event_lock, flags); | 5271 | spin_lock_irqsave(&dev->event_lock, flags); |
5271 | work = intel_crtc->unpin_work; | 5272 | work = intel_crtc->unpin_work; |
5272 | if (work == NULL || !work->pending) { | 5273 | if (work == NULL || !work->pending) { |
@@ -5278,22 +5279,29 @@ static void do_intel_finish_page_flip(struct drm_device *dev, | |||
5278 | 5279 | ||
5279 | if (work->event) { | 5280 | if (work->event) { |
5280 | e = work->event; | 5281 | e = work->event; |
5281 | e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &now); | 5282 | e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl); |
5282 | 5283 | ||
5283 | /* Called before vblank count and timestamps have | 5284 | /* Called before vblank count and timestamps have |
5284 | * been updated for the vblank interval of flip | 5285 | * been updated for the vblank interval of flip |
5285 | * completion? Need to increment vblank count and | 5286 | * completion? Need to increment vblank count and |
5286 | * add one videorefresh duration to returned timestamp | 5287 | * add one videorefresh duration to returned timestamp |
5287 | * to account for this. | 5288 | * to account for this. We assume this happened if we |
5289 | * get called over 0.9 frame durations after the last | ||
5290 | * timestamped vblank. | ||
5291 | * | ||
5292 | * This calculation can not be used with vrefresh rates | ||
5293 | * below 5Hz (10Hz to be on the safe side) without | ||
5294 | * promoting to 64 integers. | ||
5288 | */ | 5295 | */ |
5289 | if (called_before_vblirq) { | 5296 | if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) > |
5297 | 9 * crtc->framedur_ns) { | ||
5290 | e->event.sequence++; | 5298 | e->event.sequence++; |
5291 | now = ns_to_timeval(timeval_to_ns(&now) + | 5299 | tvbl = ns_to_timeval(timeval_to_ns(&tvbl) + |
5292 | crtc->framedur_ns); | 5300 | crtc->framedur_ns); |
5293 | } | 5301 | } |
5294 | 5302 | ||
5295 | e->event.tv_sec = now.tv_sec; | 5303 | e->event.tv_sec = tvbl.tv_sec; |
5296 | e->event.tv_usec = now.tv_usec; | 5304 | e->event.tv_usec = tvbl.tv_usec; |
5297 | 5305 | ||
5298 | list_add_tail(&e->base.link, | 5306 | list_add_tail(&e->base.link, |
5299 | &e->base.file_priv->event_list); | 5307 | &e->base.file_priv->event_list); |
@@ -5321,8 +5329,7 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) | |||
5321 | drm_i915_private_t *dev_priv = dev->dev_private; | 5329 | drm_i915_private_t *dev_priv = dev->dev_private; |
5322 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; | 5330 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; |
5323 | 5331 | ||
5324 | /* Called after drm_handle_vblank has run for finish vblank. */ | 5332 | do_intel_finish_page_flip(dev, crtc); |
5325 | do_intel_finish_page_flip(dev, crtc, 0); | ||
5326 | } | 5333 | } |
5327 | 5334 | ||
5328 | void intel_finish_page_flip_plane(struct drm_device *dev, int plane) | 5335 | void intel_finish_page_flip_plane(struct drm_device *dev, int plane) |
@@ -5330,8 +5337,7 @@ void intel_finish_page_flip_plane(struct drm_device *dev, int plane) | |||
5330 | drm_i915_private_t *dev_priv = dev->dev_private; | 5337 | drm_i915_private_t *dev_priv = dev->dev_private; |
5331 | struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; | 5338 | struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; |
5332 | 5339 | ||
5333 | /* Called before drm_handle_vblank has run for finish vblank. */ | 5340 | do_intel_finish_page_flip(dev, crtc); |
5334 | do_intel_finish_page_flip(dev, crtc, 1); | ||
5335 | } | 5341 | } |
5336 | 5342 | ||
5337 | void intel_prepare_page_flip(struct drm_device *dev, int plane) | 5343 | void intel_prepare_page_flip(struct drm_device *dev, int plane) |