Skip to content

Commit

Permalink
radeon: Try harder to ensure we reclock in vblank
Browse files Browse the repository at this point in the history
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 <mjg@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Matthew Garrett authored and Dave Airlie committed May 18, 2010
1 parent 612e06c commit f81f202
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 1 deletion.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/radeon/r500_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
26 changes: 26 additions & 0 deletions drivers/gpu/drm/radeon/r600.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/radeon/radeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
11 changes: 10 additions & 1 deletion drivers/gpu/drm/radeon/radeon_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down

0 comments on commit f81f202

Please sign in to comment.