Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/radeon: Support DRM_MODE_PAGE_FLIP_ASYNC

When this flag is set, we program the hardware to execute the flip
during horizontal blank (i.e. for the next scanline) instead of during
vertical blank (i.e. for the next frame).

Currently this is only supported on ASICs which have a page flip
completion interrupt (>= R600), and only if the use_pflipirq parameter
has value 2 (the default).

Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Michel Dänzer <michel.daenzer@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Michel Dänzer and committed by
Alex Deucher
c63dd758 a4333b4c

+35 -24
+11 -13
drivers/gpu/drm/radeon/atombios_crtc.c
··· 1375 1375 break; 1376 1376 } 1377 1377 1378 + /* Make sure surface address is updated at vertical blank rather than 1379 + * horizontal blank 1380 + */ 1381 + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0); 1382 + 1378 1383 WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 1379 1384 upper_32_bits(fb_location)); 1380 1385 WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, ··· 1432 1427 WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, 1433 1428 (viewport_w << 16) | viewport_h); 1434 1429 1435 - /* pageflip setup */ 1436 - /* make sure flip is at vb rather than hb */ 1437 - tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); 1438 - tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; 1439 - WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); 1440 - 1441 1430 /* set pageflip to happen only at start of vblank interval (front porch) */ 1442 1431 WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3); 1443 1432 ··· 1465 1466 uint64_t fb_location; 1466 1467 uint32_t fb_format, fb_pitch_pixels, tiling_flags; 1467 1468 u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; 1468 - u32 tmp, viewport_w, viewport_h; 1469 + u32 viewport_w, viewport_h; 1469 1470 int r; 1470 1471 bool bypass_lut = false; 1471 1472 ··· 1580 1581 else 1581 1582 WREG32(AVIVO_D2VGA_CONTROL, 0); 1582 1583 1584 + /* Make sure surface address is update at vertical blank rather than 1585 + * horizontal blank 1586 + */ 1587 + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0); 1588 + 1583 1589 if (rdev->family >= CHIP_RV770) { 1584 1590 if (radeon_crtc->crtc_id) { 1585 1591 WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); ··· 1630 1626 viewport_h = (crtc->mode.vdisplay + 1) & ~1; 1631 1627 WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, 1632 1628 (viewport_w << 16) | viewport_h); 1633 - 1634 - /* pageflip setup */ 1635 - /* make sure flip is at vb rather than hb */ 1636 - tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); 1637 - tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; 1638 - WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); 1639 1629 1640 1630 /* set pageflip to happen only at start of vblank interval (front porch) */ 1641 1631 WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
+4 -1
drivers/gpu/drm/radeon/evergreen.c
··· 1407 1407 * Triggers the actual pageflip by updating the primary 1408 1408 * surface base address (evergreen+). 1409 1409 */ 1410 - void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) 1410 + void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, 1411 + bool async) 1411 1412 { 1412 1413 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 1413 1414 1414 1415 /* update the scanout addresses */ 1416 + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 1417 + async ? EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0); 1415 1418 WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 1416 1419 upper_32_bits(crtc_base)); 1417 1420 WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+1 -1
drivers/gpu/drm/radeon/r100.c
··· 153 153 * bit to go high, when it does, we release the lock, and allow the 154 154 * double buffered update to take place. 155 155 */ 156 - void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) 156 + void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async) 157 157 { 158 158 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 159 159 u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
+3 -2
drivers/gpu/drm/radeon/radeon.h
··· 746 746 struct drm_pending_vblank_event *event; 747 747 struct radeon_bo *old_rbo; 748 748 struct fence *fence; 749 + bool async; 749 750 }; 750 751 751 752 struct r500_irq_stat_regs { ··· 2001 2000 } dpm; 2002 2001 /* pageflipping */ 2003 2002 struct { 2004 - void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); 2003 + void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base, bool async); 2005 2004 bool (*page_flip_pending)(struct radeon_device *rdev, int crtc); 2006 2005 } pflip; 2007 2006 }; ··· 2778 2777 #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) 2779 2778 #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) 2780 2779 #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) 2781 - #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) 2780 + #define radeon_page_flip(rdev, crtc, base, async) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base), (async)) 2782 2781 #define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc)) 2783 2782 #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) 2784 2783 #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev))
+5 -4
drivers/gpu/drm/radeon/radeon_asic.h
··· 138 138 extern void r100_pm_init_profile(struct radeon_device *rdev); 139 139 extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); 140 140 extern void r100_page_flip(struct radeon_device *rdev, int crtc, 141 - u64 crtc_base); 141 + u64 crtc_base, bool async); 142 142 extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc); 143 143 extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); 144 144 extern int r100_mc_wait_for_idle(struct radeon_device *rdev); ··· 250 250 extern void rs600_pm_prepare(struct radeon_device *rdev); 251 251 extern void rs600_pm_finish(struct radeon_device *rdev); 252 252 extern void rs600_page_flip(struct radeon_device *rdev, int crtc, 253 - u64 crtc_base); 253 + u64 crtc_base, bool async); 254 254 extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc); 255 255 void rs600_set_safe_registers(struct radeon_device *rdev); 256 256 extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); ··· 464 464 int rv770_suspend(struct radeon_device *rdev); 465 465 int rv770_resume(struct radeon_device *rdev); 466 466 void rv770_pm_misc(struct radeon_device *rdev); 467 - void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); 467 + void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base, 468 + bool async); 468 469 bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc); 469 470 void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); 470 471 void r700_cp_stop(struct radeon_device *rdev); ··· 535 534 int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); 536 535 int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); 537 536 extern void evergreen_page_flip(struct radeon_device *rdev, int crtc, 538 - u64 crtc_base); 537 + u64 crtc_base, bool async); 539 538 extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc); 540 539 extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); 541 540 void evergreen_disable_interrupt_state(struct radeon_device *rdev);
+5 -1
drivers/gpu/drm/radeon/radeon_display.c
··· 490 490 vblank->linedur_ns / 1000, stat, vpos, hpos); 491 491 492 492 /* do the flip (mmio) */ 493 - radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); 493 + radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base, work->async); 494 494 495 495 radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED; 496 496 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); ··· 525 525 work->rdev = rdev; 526 526 work->crtc_id = radeon_crtc->crtc_id; 527 527 work->event = event; 528 + work->async = (page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0; 528 529 529 530 /* schedule unpin of the old buffer */ 530 531 old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); ··· 1630 1629 rdev->mode_info.mode_config_initialized = true; 1631 1630 1632 1631 rdev->ddev->mode_config.funcs = &radeon_mode_funcs; 1632 + 1633 + if (radeon_use_pflipirq == 2 && rdev->family >= CHIP_R600) 1634 + rdev->ddev->mode_config.async_page_flip = true; 1633 1635 1634 1636 if (ASIC_IS_DCE5(rdev)) { 1635 1637 rdev->ddev->mode_config.max_width = 16384;
+3 -1
drivers/gpu/drm/radeon/rs600.c
··· 110 110 } 111 111 } 112 112 113 - void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) 113 + void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async) 114 114 { 115 115 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 116 116 u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); ··· 121 121 WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); 122 122 123 123 /* update the scanout addresses */ 124 + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 125 + async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0); 124 126 WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 125 127 (u32)crtc_base); 126 128 WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
+3 -1
drivers/gpu/drm/radeon/rv770.c
··· 801 801 return reference_clock; 802 802 } 803 803 804 - void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) 804 + void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async) 805 805 { 806 806 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 807 807 u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); ··· 812 812 WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); 813 813 814 814 /* update the scanout addresses */ 815 + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 816 + async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0); 815 817 if (radeon_crtc->crtc_id) { 816 818 WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); 817 819 WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));