diff options
author | Christian König <christian.koenig@amd.com> | 2013-04-18 15:25:59 +0200 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-04-23 17:45:44 -0400 |
commit | 55b51c88c5167ba0c95919cdd25b0bd376a3f0ea (patch) | |
tree | 43ec2ca11ed770e74436a028a3c5d244f1902f72 /drivers/gpu/drm/radeon/radeon_uvd.c | |
parent | 4ed108352d9b60a723a5071ed05e722826c2b72f (diff) | |
download | blackbird-op-linux-55b51c88c5167ba0c95919cdd25b0bd376a3f0ea.tar.gz blackbird-op-linux-55b51c88c5167ba0c95919cdd25b0bd376a3f0ea.zip |
drm/radeon: raise UVD clocks only on demand
That not only saves some power, but also solves problems with
older chips where an idle UVD block on higher clocks can
cause problems.
Signed-off-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_uvd.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_uvd.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 15580fb8546e..0312a7f4d768 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -36,6 +36,9 @@ #include "radeon.h" #include "r600d.h" +/* 1 second timeout */ +#define UVD_IDLE_TIMEOUT_MS 1000 + /* Firmware Names */ #define FIRMWARE_RV710 "radeon/RV710_uvd.bin" #define FIRMWARE_CYPRESS "radeon/CYPRESS_uvd.bin" @@ -47,6 +50,8 @@ MODULE_FIRMWARE(FIRMWARE_CYPRESS); MODULE_FIRMWARE(FIRMWARE_SUMO); MODULE_FIRMWARE(FIRMWARE_TAHITI); +static void radeon_uvd_idle_work_handler(struct work_struct *work); + int radeon_uvd_init(struct radeon_device *rdev) { struct platform_device *pdev; @@ -54,6 +59,8 @@ int radeon_uvd_init(struct radeon_device *rdev) const char *fw_name; int i, r; + INIT_DELAYED_WORK(&rdev->uvd.idle_work, radeon_uvd_idle_work_handler); + pdev = platform_device_register_simple("radeon_uvd", 0, NULL, 0); r = IS_ERR(pdev); if (r) { @@ -188,8 +195,6 @@ int radeon_uvd_resume(struct radeon_device *rdev) radeon_bo_unreserve(rdev->uvd.vcpu_bo); - radeon_set_uvd_clocks(rdev, 53300, 40000); - return 0; } @@ -666,3 +671,24 @@ int radeon_uvd_get_destroy_msg(struct radeon_device *rdev, int ring, return radeon_uvd_send_msg(rdev, ring, bo, fence); } + +static void radeon_uvd_idle_work_handler(struct work_struct *work) +{ + struct radeon_device *rdev = + container_of(work, struct radeon_device, uvd.idle_work.work); + + if (radeon_fence_count_emitted(rdev, R600_RING_TYPE_UVD_INDEX) == 0) + radeon_set_uvd_clocks(rdev, 0, 0); + else + schedule_delayed_work(&rdev->uvd.idle_work, + msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); +} + +void radeon_uvd_note_usage(struct radeon_device *rdev) +{ + bool set_clocks = !cancel_delayed_work_sync(&rdev->uvd.idle_work); + set_clocks &= schedule_delayed_work(&rdev->uvd.idle_work, + msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); + if (set_clocks) + radeon_set_uvd_clocks(rdev, 53300, 40000); +} |