aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-amd/0038-drm-radeon-dpm-enable-dynamic-vce-state-switching-v2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-amd/0038-drm-radeon-dpm-enable-dynamic-vce-state-switching-v2.patch')
-rw-r--r--common/recipes-kernel/linux/linux-amd/0038-drm-radeon-dpm-enable-dynamic-vce-state-switching-v2.patch195
1 files changed, 195 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-amd/0038-drm-radeon-dpm-enable-dynamic-vce-state-switching-v2.patch b/common/recipes-kernel/linux/linux-amd/0038-drm-radeon-dpm-enable-dynamic-vce-state-switching-v2.patch
new file mode 100644
index 00000000..9834a582
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-amd/0038-drm-radeon-dpm-enable-dynamic-vce-state-switching-v2.patch
@@ -0,0 +1,195 @@
+From ac2d716ed1a3a0c722da697eec4f9e3081deee95 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Fri, 23 Aug 2013 11:56:26 -0400
+Subject: [PATCH 38/60] drm/radeon/dpm: enable dynamic vce state switching v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+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>
+---
+ drivers/gpu/drm/radeon/radeon.h | 3 ++
+ drivers/gpu/drm/radeon/radeon_cs.c | 3 ++
+ drivers/gpu/drm/radeon/radeon_pm.c | 17 ++++++++++
+ drivers/gpu/drm/radeon/radeon_vce.c | 62 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 85 insertions(+)
+
+diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
+index fb5ffa4..a4d6f82 100644
+--- a/drivers/gpu/drm/radeon/radeon.h
++++ b/drivers/gpu/drm/radeon/radeon.h
+@@ -1518,6 +1518,7 @@ struct radeon_dpm {
+ };
+
+ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable);
++void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable);
+
+ struct radeon_pm {
+ struct mutex mutex;
+@@ -1639,6 +1640,7 @@ struct radeon_vce {
+ unsigned fb_version;
+ atomic_t handles[RADEON_MAX_VCE_HANDLES];
+ struct drm_file *filp[RADEON_MAX_VCE_HANDLES];
++ struct delayed_work idle_work;
+ };
+
+ int radeon_vce_init(struct radeon_device *rdev);
+@@ -1650,6 +1652,7 @@ int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
+ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
+ uint32_t handle, struct radeon_fence **fence);
+ void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp);
++void radeon_vce_note_usage(struct radeon_device *rdev);
+ int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi);
+ int radeon_vce_cs_parse(struct radeon_cs_parser *p);
+ bool 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 9d4e25d..848266c 100644
+--- a/drivers/gpu/drm/radeon/radeon_cs.c
++++ b/drivers/gpu/drm/radeon/radeon_cs.c
+@@ -407,6 +407,9 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
+
+ if (parser->ring == R600_RING_TYPE_UVD_INDEX)
+ radeon_uvd_note_usage(rdev);
++ else if ((parser->ring == TN_RING_TYPE_VCE1_INDEX) ||
++ (parser->ring == TN_RING_TYPE_VCE2_INDEX))
++ radeon_vce_note_usage(rdev);
+
+ radeon_cs_sync_rings(parser);
+ 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 f8afbf9..5f3a536 100644
+--- a/drivers/gpu/drm/radeon/radeon_pm.c
++++ b/drivers/gpu/drm/radeon/radeon_pm.c
+@@ -985,6 +985,23 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable)
+ }
+ }
+
++void radeon_dpm_enable_vce(struct radeon_device *rdev, bool enable)
++{
++ if (enable) {
++ mutex_lock(&rdev->pm.mutex);
++ rdev->pm.dpm.vce_active = true;
++ /* XXX select vce level based on ring/task */
++ rdev->pm.dpm.vce_level = RADEON_VCE_LEVEL_AC_ALL;
++ mutex_unlock(&rdev->pm.mutex);
++ } else {
++ mutex_lock(&rdev->pm.mutex);
++ rdev->pm.dpm.vce_active = false;
++ mutex_unlock(&rdev->pm.mutex);
++ }
++
++ radeon_pm_compute_clocks(rdev);
++}
++
+ static void radeon_pm_suspend_old(struct radeon_device *rdev)
+ {
+ mutex_lock(&rdev->pm.mutex);
+diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c
+index f46563b..d130432 100644
+--- a/drivers/gpu/drm/radeon/radeon_vce.c
++++ b/drivers/gpu/drm/radeon/radeon_vce.c
+@@ -34,11 +34,16 @@
+ #include "radeon_asic.h"
+ #include "sid.h"
+
++/* 1 second timeout */
++#define VCE_IDLE_TIMEOUT_MS 1000
++
+ /* Firmware Names */
+ #define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin"
+
+ MODULE_FIRMWARE(FIRMWARE_BONAIRE);
+
++static void radeon_vce_idle_work_handler(struct work_struct *work);
++
+ /**
+ * radeon_vce_init - allocate memory, load vce firmware
+ *
+@@ -55,6 +60,8 @@ int radeon_vce_init(struct radeon_device *rdev)
+ uint8_t start, mid, end;
+ int i, r;
+
++ INIT_DELAYED_WORK(&rdev->vce.idle_work, radeon_vce_idle_work_handler);
++
+ switch (rdev->family) {
+ case CHIP_BONAIRE:
+ case CHIP_KAVERI:
+@@ -220,6 +227,59 @@ int radeon_vce_resume(struct radeon_device *rdev)
+ }
+
+ /**
++ * radeon_vce_idle_work_handler - power off VCE
++ *
++ * @work: pointer to work structure
++ *
++ * power of VCE when it's not used any more
++ */
++static void radeon_vce_idle_work_handler(struct work_struct *work)
++{
++ struct radeon_device *rdev =
++ container_of(work, struct radeon_device, vce.idle_work.work);
++
++ if ((radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE1_INDEX) == 0) &&
++ (radeon_fence_count_emitted(rdev, TN_RING_TYPE_VCE2_INDEX) == 0)) {
++ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
++ radeon_dpm_enable_vce(rdev, false);
++ } else {
++ radeon_set_vce_clocks(rdev, 0, 0);
++ }
++ } else {
++ schedule_delayed_work(&rdev->vce.idle_work,
++ msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS));
++ }
++}
++
++/**
++ * radeon_vce_note_usage - power up VCE
++ *
++ * @rdev: radeon_device pointer
++ *
++ * Make sure VCE is powerd up when we want to use it
++ */
++void radeon_vce_note_usage(struct radeon_device *rdev)
++{
++ bool streams_changed = false;
++ bool set_clocks = !cancel_delayed_work_sync(&rdev->vce.idle_work);
++ set_clocks &= schedule_delayed_work(&rdev->vce.idle_work,
++ msecs_to_jiffies(VCE_IDLE_TIMEOUT_MS));
++
++ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
++ /* XXX figure out if the streams changed */
++ streams_changed = false;
++ }
++
++ if (set_clocks || streams_changed) {
++ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
++ radeon_dpm_enable_vce(rdev, true);
++ } else {
++ radeon_set_vce_clocks(rdev, 53300, 40000);
++ }
++ }
++}
++
++/**
+ * radeon_vce_free_handles - free still open VCE handles
+ *
+ * @rdev: radeon_device pointer
+@@ -235,6 +295,8 @@ void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp)
+ if (!handle || rdev->vce.filp[i] != filp)
+ continue;
+
++ radeon_vce_note_usage(rdev);
++
+ r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX,
+ handle, NULL);
+ if (r)
+--
+1.9.1
+