aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner.de@gmail.com>2016-09-17 08:25:38 -0400
committerAlex Deucher <alexander.deucher@amd.com>2016-10-04 11:15:58 -0400
commit73d4c23f5361928b12e7827e872612273cc1175a (patch)
treeb661a7a346cf474267b2ff442ccd04736c8d9be4
parentc2cbc38b9715bd8318062e600668fc30e5a3fbfa (diff)
drm/radeon: Slightly more robust flip completion handling for < DCE-4
Pre DCE4 hardware doesn't have (reliable) pageflip completion irqs, therefore we have to use the old polling method for flip completion handling in vblank irq. As vblank irqs fire a bit before start of vblank (when the linebuffer fifo read position reaches end of scanout), we have some fudge for flip completion handling in the last lines of active scanout. Old code assumed the threshold to be 99% of active scanout height, a ballpark estimate which worked ok. Since we know since a while how to calculate the actual threshold from linebuffer size, lets make use of it to get a more accurate threshold. This completion path is still prone to some races in corner cases, especially on pre-AVIVO hardware, so document them a bit better in the code comments. Acked-by: Michel Dänzer <michel.daenzer@amd.com> Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 890171f08987..50706464d456 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -321,16 +321,30 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id)
321 update_pending = radeon_page_flip_pending(rdev, crtc_id); 321 update_pending = radeon_page_flip_pending(rdev, crtc_id);
322 322
323 /* Has the pageflip already completed in crtc, or is it certain 323 /* Has the pageflip already completed in crtc, or is it certain
324 * to complete in this vblank? 324 * to complete in this vblank? GET_DISTANCE_TO_VBLANKSTART provides
325 * distance to start of "fudged earlier" vblank in vpos, distance to
326 * start of real vblank in hpos. vpos >= 0 && hpos < 0 means we are in
327 * the last few scanlines before start of real vblank, where the vblank
328 * irq can fire, so we have sampled update_pending a bit too early and
329 * know the flip will complete at leading edge of the upcoming real
330 * vblank. On pre-AVIVO hardware, flips also complete inside the real
331 * vblank, not only at leading edge, so if update_pending for hpos >= 0
332 * == inside real vblank, the flip will complete almost immediately.
333 * Note that this method of completion handling is still not 100% race
334 * free, as we could execute before the radeon_flip_work_func managed
335 * to run and set the RADEON_FLIP_SUBMITTED status, thereby we no-op,
336 * but the flip still gets programmed into hw and completed during
337 * vblank, leading to a delayed emission of the flip completion event.
338 * This applies at least to pre-AVIVO hardware, where flips are always
339 * completing inside vblank, not only at leading edge of vblank.
325 */ 340 */
326 if (update_pending && 341 if (update_pending &&
327 (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, 342 (DRM_SCANOUTPOS_VALID &
328 crtc_id, 343 radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id,
329 USE_REAL_VBLANKSTART, 344 GET_DISTANCE_TO_VBLANKSTART,
330 &vpos, &hpos, NULL, NULL, 345 &vpos, &hpos, NULL, NULL,
331 &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && 346 &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) &&
332 ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || 347 ((vpos >= 0 && hpos < 0) || (hpos >= 0 && !ASIC_IS_AVIVO(rdev)))) {
333 (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
334 /* crtc didn't flip in this target vblank interval, 348 /* crtc didn't flip in this target vblank interval,
335 * but flip is pending in crtc. Based on the current 349 * but flip is pending in crtc. Based on the current
336 * scanout position we know that the current frame is 350 * scanout position we know that the current frame is