aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 298ea1c453c3..2b9ba03a7c1a 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work)
403 struct drm_crtc *crtc = &radeon_crtc->base; 403 struct drm_crtc *crtc = &radeon_crtc->base;
404 unsigned long flags; 404 unsigned long flags;
405 int r; 405 int r;
406 int vpos, hpos, stat, min_udelay; 406 int vpos, hpos, stat, min_udelay = 0;
407 unsigned repcnt = 4;
407 struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; 408 struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id];
408 409
409 down_read(&rdev->exclusive_lock); 410 down_read(&rdev->exclusive_lock);
@@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
454 * In practice this won't execute very often unless on very fast 455 * In practice this won't execute very often unless on very fast
455 * machines because the time window for this to happen is very small. 456 * machines because the time window for this to happen is very small.
456 */ 457 */
457 for (;;) { 458 while (radeon_crtc->enabled && repcnt--) {
458 /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank 459 /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
459 * start in hpos, and to the "fudged earlier" vblank start in 460 * start in hpos, and to the "fudged earlier" vblank start in
460 * vpos. 461 * vpos.
@@ -472,10 +473,22 @@ static void radeon_flip_work_func(struct work_struct *__work)
472 /* Sleep at least until estimated real start of hw vblank */ 473 /* Sleep at least until estimated real start of hw vblank */
473 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 474 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
474 min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); 475 min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5);
476 if (min_udelay > vblank->framedur_ns / 2000) {
477 /* Don't wait ridiculously long - something is wrong */
478 repcnt = 0;
479 break;
480 }
475 usleep_range(min_udelay, 2 * min_udelay); 481 usleep_range(min_udelay, 2 * min_udelay);
476 spin_lock_irqsave(&crtc->dev->event_lock, flags); 482 spin_lock_irqsave(&crtc->dev->event_lock, flags);
477 }; 483 };
478 484
485 if (!repcnt)
486 DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, "
487 "framedur %d, linedur %d, stat %d, vpos %d, "
488 "hpos %d\n", work->crtc_id, min_udelay,
489 vblank->framedur_ns / 1000,
490 vblank->linedur_ns / 1000, stat, vpos, hpos);
491
479 /* do the flip (mmio) */ 492 /* do the flip (mmio) */
480 radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); 493 radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
481 494