diff --git a/drivers/gpu/drm/radeon/avivod.h b/drivers/gpu/drm/radeon/avivod.h index d4e6e6e4a93..3c391e7e9fd 100644 --- a/drivers/gpu/drm/radeon/avivod.h +++ b/drivers/gpu/drm/radeon/avivod.h @@ -30,11 +30,13 @@ #define D1CRTC_CONTROL 0x6080 #define CRTC_EN (1 << 0) +#define D1CRTC_STATUS 0x609c #define D1CRTC_UPDATE_LOCK 0x60E8 #define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 #define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 #define D2CRTC_CONTROL 0x6880 +#define D2CRTC_STATUS 0x689c #define D2CRTC_UPDATE_LOCK 0x68E8 #define D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910 #define D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918 diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index f0234351fd5..6dbfdf48a5f 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -22,6 +22,7 @@ */ #include "drmP.h" #include "radeon.h" +#include "avivod.h" #define RADEON_IDLE_LOOP_MS 100 #define RADEON_RECLOCK_DELAY_MS 200 @@ -283,6 +284,28 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) mutex_unlock(&rdev->pm.mutex); } +static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish) +{ + u32 stat_crtc1 = 0, stat_crtc2 = 0; + bool in_vbl = true; + + if (ASIC_IS_AVIVO(rdev)) { + if (rdev->pm.active_crtcs & (1 << 0)) { + stat_crtc1 = RREG32(D1CRTC_STATUS); + if (!(stat_crtc1 & 1)) + in_vbl = false; + } + if (rdev->pm.active_crtcs & (1 << 1)) { + stat_crtc2 = RREG32(D2CRTC_STATUS); + if (!(stat_crtc2 & 1)) + in_vbl = false; + } + } + if (in_vbl == false) + DRM_INFO("not in vbl for pm change %08x %08x at %s\n", stat_crtc1, + stat_crtc2, finish ? "exit" : "entry"); + return in_vbl; +} static void radeon_pm_set_clocks_locked(struct radeon_device *rdev) { /*radeon_fence_wait_last(rdev);*/ @@ -299,7 +322,11 @@ static void radeon_pm_set_clocks_locked(struct radeon_device *rdev) DRM_ERROR("%s: PM_ACTION_NONE\n", __func__); break; } + + /* check if we are in vblank */ + radeon_pm_debug_check_in_vbl(rdev, false); radeon_set_power_state(rdev); + radeon_pm_debug_check_in_vbl(rdev, true); rdev->pm.planned_action = PM_ACTION_NONE; }