From f81f202402640c27b38e1452dcb4d3e447043f48 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 28 Apr 2010 12:13:06 -0400 Subject: radeon: Try harder to ensure we reclock in vblank The vblank interrupt on r600 doesn't seem to be especially reliable, so perform some sanity checks before the actual reclock. Signed-off-by: Matthew Garrett Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r500_reg.h | 2 ++ drivers/gpu/drm/radeon/r600.c | 26 ++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_pm.c | 11 ++++++++++- 4 files changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index f5adf42a9d15..93c9a2bbccf8 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h @@ -351,6 +351,7 @@ #define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 #define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 #define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c +#define AVIVO_D1CRTC_STATUS_POSITION 0x60a0 #define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 @@ -489,6 +490,7 @@ #define AVIVO_D2CRTC_BLANK_CONTROL 0x6884 #define AVIVO_D2CRTC_INTERLACE_CONTROL 0x6888 #define AVIVO_D2CRTC_INTERLACE_STATUS 0x688c +#define AVIVO_D2CRTC_STATUS_POSITION 0x68a0 #define AVIVO_D2CRTC_FRAME_COUNT 0x68a4 #define AVIVO_D2CRTC_STEREO_CONTROL 0x68c4 diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 1696cc277d8b..d3a79e0a9125 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -289,8 +289,34 @@ void r600_set_power_state(struct radeon_device *rdev, bool static_switch) } } else { + u32 position; + u32 vbl; + radeon_sync_with_vblank(rdev); + if (!radeon_pm_in_vbl(rdev)) + return; + + if (rdev->pm.active_crtcs & (1 << 0)) { + vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); + position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); + position &= 0xfff; + vbl &= 0xfff; + + if (position < vbl && position > 1) + return; + } + + if (rdev->pm.active_crtcs & (1 << 1)) { + vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); + position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); + position &= 0xfff; + vbl &= 0xfff; + + if (position < vbl && position > 1) + return; + } + if (sclk != rdev->pm.current_sclk) { radeon_pm_debug_check_in_vbl(rdev, false); radeon_set_engine_clock(rdev, sclk); diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index bed84b316bba..93ac88eb6b3a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -175,6 +175,7 @@ void radeon_pm_fini(struct radeon_device *rdev); void radeon_pm_compute_clocks(struct radeon_device *rdev); void radeon_combios_get_power_modes(struct radeon_device *rdev); void radeon_atombios_get_power_modes(struct radeon_device *rdev); +bool radeon_pm_in_vbl(struct radeon_device *rdev); bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish); void radeon_sync_with_vblank(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 134b19537d11..88163e043fcf 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -387,7 +387,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) mutex_unlock(&rdev->pm.mutex); } -bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) +bool radeon_pm_in_vbl(struct radeon_device *rdev) { u32 stat_crtc = 0; bool in_vbl = true; @@ -446,6 +446,15 @@ bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) in_vbl = false; } } + + return in_vbl; +} + +bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) +{ + u32 stat_crtc = 0; + bool in_vbl = radeon_pm_in_vbl(rdev); + if (in_vbl == false) DRM_INFO("not in vbl for pm change %08x at %s\n", stat_crtc, finish ? "exit" : "entry"); -- cgit v1.2.2