diff options
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.patch | 195 |
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 + |