aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2013-08-23 11:56:26 -0400
committerChristian König <christian.koenig@amd.com>2014-02-18 10:11:41 -0500
commit03afe6f6480f2544d6cd18866556f1f76bb05f14 (patch)
tree3a3d690eebc5a34439fe9d8b4e961bd26a3bf08a
parent4233290519c779e44a01816cf825f6df067a0886 (diff)
drm/radeon/dpm: enable dynamic vce state switching v2
enable vce states when vce is active. When vce is active, it adjusts the currently selected state (performance, battery, uvd, etc.) v2: add code comments Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_pm.c17
-rw-r--r--drivers/gpu/drm/radeon/radeon_vce.c62
4 files changed, 85 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 693a8fccd94d..540624e7491c 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1518,6 +1518,7 @@ struct radeon_dpm {
1518}; 1518};
1519 1519
1520void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable); 1520void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable);
1521void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable);
1521 1522
1522struct radeon_pm { 1523struct radeon_pm {
1523 struct mutex mutex; 1524 struct mutex mutex;
@@ -1638,6 +1639,7 @@ struct radeon_vce {
1638 unsigned fb_version; 1639 unsigned fb_version;
1639 atomic_t handles[RADEON_MAX_VCE_HANDLES]; 1640 atomic_t handles[RADEON_MAX_VCE_HANDLES];
1640 struct drm_file *filp[RADEON_MAX_VCE_HANDLES]; 1641 struct drm_file *filp[RADEON_MAX_VCE_HANDLES];
1642 struct delayed_work idle_work;
1641}; 1643};
1642 1644
1643int radeon_vce_init(struct radeon_device *rdev); 1645int radeon_vce_init(struct radeon_device *rdev);
@@ -1649,6 +1651,7 @@ int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
1649int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, 1651int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
1650 uint32_t handle, struct radeon_fence **fence); 1652 uint32_t handle, struct radeon_fence **fence);
1651void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp); 1653void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp);
1654void radeon_vce_note_usage(struct radeon_device *rdev);
1652int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi); 1655int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi);
1653int radeon_vce_cs_parse(struct radeon_cs_parser *p); 1656int radeon_vce_cs_parse(struct radeon_cs_parser *p);
1654bool radeon_vce_semaphore_emit(struct radeon_device *rdev, 1657bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 701ee7981b5c..f28a8d82fa19 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -347,6 +347,9 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
347 347
348 if (parser->ring == R600_RING_TYPE_UVD_INDEX) 348 if (parser->ring == R600_RING_TYPE_UVD_INDEX)
349 radeon_uvd_note_usage(rdev); 349 radeon_uvd_note_usage(rdev);
350 else if ((parser->ring == TN_RING_TYPE_VCE1_INDEX) ||
351 (parser->ring == TN_RING_TYPE_VCE2_INDEX))
352 radeon_vce_note_usage(rdev);
350 353
351 radeon_cs_sync_rings(parser); 354 radeon_cs_sync_rings(parser);
352 r = radeon_ib_schedule(rdev, &parser->ib, NULL); 355 r = radeon_ib_schedule(rdev, &parser->ib, NULL);
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
index a4687e7b45f8..4ad9af9fc517 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -968,6 +968,23 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
968 } 968 }
969} 969}
970 970
971void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable)
972{
973 if (enable) {
974 mutex_lock(&rdev->pm.mutex);
975 rdev->pm.dpm.vce_active = true;
976 /* XXX select vce level based on ring/task */
977 rdev->pm.dpm.vce_level = RADEON_VCE_LEVEL_AC_ALL;
978 mutex_unlock(&rdev->pm.mutex);
979 } else {
980 mutex_lock(&rdev->pm.mutex);
981 rdev->pm.dpm.vce_active = false;
982 mutex_unlock(&rdev->pm.mutex);
983 }
984
985 radeon_pm_compute_clocks(rdev);
986}
987
971static void radeon_pm_suspend_old(struct radeon_device *rdev) 988static void radeon_pm_suspend_old(struct radeon_device *rdev)
972{ 989{
973 mutex_lock(&rdev->pm.mutex); 990 mutex_lock(&rdev->pm.mutex);
diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
index f46563b60921..d130432e313a 100644
--- a/drivers/gpu/drm/radeon/radeon_vce.c
+++ b/drivers/gpu/drm/radeon/radeon_vce.c
@@ -34,11 +34,16 @@
34#include "radeon_asic.h" 34#include "radeon_asic.h"
35#include "sid.h" 35#include "sid.h"
36 36
37/* 1 second timeout */
38#define VCE_IDLE_TIMEOUT_MS 1000
39
37/* Firmware Names */ 40/* Firmware Names */
38#define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin" 41#define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin"
39 42
40MODULE_FIRMWARE(FIRMWARE_BONAIRE); 43MODULE_FIRMWARE(FIRMWARE_BONAIRE);
41 44
45static void radeon_vce_idle_work_handler(struct work_struct *work);
46
42/** 47/**
43 * radeon_vce_init - allocate memory, load vce firmware 48 * radeon_vce_init - allocate memory, load vce firmware
44 * 49 *
@@ -55,6 +60,8 @@ int radeon_vce_init(struct radeon_device *rdev)
55 uint8_t start, mid, end; 60 uint8_t start, mid, end;
56 int i, r; 61 int i, r;
57 62
63 INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler);
64
58 switch (rdev->family) { 65 switch (rdev->family) {
59 case CHIP_BONAIRE: 66 case CHIP_BONAIRE:
60 case CHIP_KAVERI: 67 case CHIP_KAVERI:
@@ -220,6 +227,59 @@ int radeon_vce_resume(struct radeon_device *rdev)
220} 227}
221 228
222/** 229/**
230 * radeon_vce_idle_work_handler - power off VCE
231 *
232 * @work: pointer to work structure
233 *
234 * power of VCE when it's not used any more
235 */
236static void radeon_vce_idle_work_handler(struct work_struct *work)
237{
238 struct radeon_device *rdev =
239 container_of(work, struct radeon_device, vce.idle_work.work);
240
241 if ((radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE1_INDEX) == 0) &&
242 (radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE2_INDEX) == 0)) {
243 if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
244 radeon_dpm_enable_vce(rdev, false);
245 } else {
246 radeon_set_vce_clocks(rdev, 0, 0);
247 }
248 } else {
249 schedule_delayed_work(&rdev->vce.idle_work,
250 msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS));
251 }
252}
253
254/**
255 * radeon_vce_note_usage - power up VCE
256 *
257 * @rdev: radeon_device pointer
258 *
259 * Make sure VCE is powerd up when we want to use it
260 */
261void radeon_vce_note_usage(struct radeon_device *rdev)
262{
263 bool streams_changed = false;
264 bool set_clocks = !cancel_delayed_work_sync(&rdev->vce.idle_work);
265 set_clocks &= schedule_delayed_work(&rdev->vce.idle_work,
266 msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS));
267
268 if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
269 /* XXX figure out if the streams changed */
270 streams_changed = false;
271 }
272
273 if (set_clocks || streams_changed) {
274 if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
275 radeon_dpm_enable_vce(rdev, true);
276 } else {
277 radeon_set_vce_clocks(rdev, 53300, 40000);
278 }
279 }
280}
281
282/**
223 * radeon_vce_free_handles - free still open VCE handles 283 * radeon_vce_free_handles - free still open VCE handles
224 * 284 *
225 * @rdev: radeon_device pointer 285 * @rdev: radeon_device pointer
@@ -235,6 +295,8 @@ void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp)
235 if (!handle || rdev->vce.filp[i] != filp) 295 if (!handle || rdev->vce.filp[i] != filp)
236 continue; 296 continue;
237 297
298 radeon_vce_note_usage(rdev);
299
238 r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX, 300 r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX,
239 handle, NULL); 301 handle, NULL);
240 if (r) 302 if (r)