From e5d03ac2b8bd6d738c8e1ed6ea9a6a164ce86d3c Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 23 Dec 2016 14:39:41 +0800 Subject: drm/amd/powerplay: Unify dpm level defines Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index bda9e3de191e..d8de7eb84f52 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -4336,13 +4336,13 @@ static u32 ci_get_lowest_enabled_level(struct amdgpu_device *adev, static int ci_dpm_force_performance_level(struct amdgpu_device *adev, - enum amdgpu_dpm_forced_level level) + enum amd_dpm_forced_level level) { struct ci_power_info *pi = ci_get_pi(adev); u32 tmp, levels, i; int ret; - if (level == AMDGPU_DPM_FORCED_LEVEL_HIGH) { + if (level == AMD_DPM_FORCED_LEVEL_HIGH) { if ((!pi->pcie_dpm_key_disabled) && pi->dpm_level_enable_mask.pcie_dpm_enable_mask) { levels = 0; @@ -4403,7 +4403,7 @@ static int ci_dpm_force_performance_level(struct amdgpu_device *adev, } } } - } else if (level == AMDGPU_DPM_FORCED_LEVEL_LOW) { + } else if (level == AMD_DPM_FORCED_LEVEL_LOW) { if ((!pi->sclk_dpm_key_disabled) && pi->dpm_level_enable_mask.sclk_dpm_enable_mask) { levels = ci_get_lowest_enabled_level(adev, @@ -4452,7 +4452,7 @@ static int ci_dpm_force_performance_level(struct amdgpu_device *adev, udelay(1); } } - } else if (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) { + } else if (level == AMD_DPM_FORCED_LEVEL_AUTO) { if (!pi->pcie_dpm_key_disabled) { PPSMC_Result smc_result; @@ -6262,7 +6262,7 @@ static int ci_dpm_sw_init(void *handle) /* default to balanced state */ adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; - adev->pm.dpm.forced_level = AMDGPU_DPM_FORCED_LEVEL_AUTO; + adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO; adev->pm.default_sclk = adev->clock.default_sclk; adev->pm.default_mclk = adev->clock.default_mclk; adev->pm.current_sclk = adev->clock.default_sclk; @@ -6572,7 +6572,7 @@ static int ci_dpm_force_clock_level(struct amdgpu_device *adev, struct ci_power_info *pi = ci_get_pi(adev); if (adev->pm.dpm.forced_level - != AMDGPU_DPM_FORCED_LEVEL_MANUAL) + != AMD_DPM_FORCED_LEVEL_MANUAL) return -EINVAL; switch (type) { -- cgit From 9d273495e691f9473db6b2ae2da41515d53a70e9 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Wed, 28 Dec 2016 11:09:00 +0800 Subject: drm/amdgpu: delete dead definitions of dpm_ip_funcs Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 9 --------- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 9 --------- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 8 -------- 3 files changed, 26 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index d8de7eb84f52..ab7d2bb71dad 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6739,12 +6739,3 @@ static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev) adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; adev->pm.dpm.thermal.irq.funcs = &ci_dpm_irq_funcs; } - -const struct amdgpu_ip_block_version ci_dpm_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &ci_dpm_ip_funcs, -}; diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index 91f885ba2946..90c2af381cbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -3307,12 +3307,3 @@ static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev) adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; adev->pm.dpm.thermal.irq.funcs = &kv_dpm_irq_funcs; } - -const struct amdgpu_ip_block_version kv_dpm_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 7, - .minor = 0, - .rev = 0, - .funcs = &kv_dpm_ip_funcs, -}; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 738ebc125569..4f12da1e7ebf 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -8072,11 +8072,3 @@ static void si_dpm_set_irq_funcs(struct amdgpu_device *adev) adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs; } -const struct amdgpu_ip_block_version si_dpm_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &si_dpm_ip_funcs, -}; -- cgit From 3bd58979648fd105258934fb9f0fea1d73341d08 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 23 Dec 2016 15:24:37 +0800 Subject: drm/amd/powerplay: add profiling mode in dpm level In some case, App need to run under max stable clock. so export profiling mode: GFX CG was disabled. and user can select the max stable clock of the device. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 4 ++-- drivers/gpu/drm/amd/include/amd_shared.h | 1 + drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 3 ++- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 3 ++- 5 files changed, 24 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index ccf50b8b854b..0345fbbfff4e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -124,6 +124,7 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, (level & AMD_DPM_FORCED_LEVEL_LOW) ? "low" : (level & AMD_DPM_FORCED_LEVEL_HIGH) ? "high" : (level & AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" : + (level & AMD_DPM_FORCED_LEVEL_PROFILING) ? "profiling" : "unknown")); } @@ -135,6 +136,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; enum amd_dpm_forced_level level; + enum amd_dpm_forced_level current_level; int ret = 0; /* Can't force performance level when the card is off */ @@ -142,6 +144,8 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) return -EINVAL; + current_level = amdgpu_dpm_get_performance_level(adev); + if (strncmp("low", buf, strlen("low")) == 0) { level = AMD_DPM_FORCED_LEVEL_LOW; } else if (strncmp("high", buf, strlen("high")) == 0) { @@ -150,11 +154,24 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, level = AMD_DPM_FORCED_LEVEL_AUTO; } else if (strncmp("manual", buf, strlen("manual")) == 0) { level = AMD_DPM_FORCED_LEVEL_MANUAL; + } else if (strncmp("profile", buf, strlen("profile")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILING; } else { count = -EINVAL; goto fail; } + if (current_level == level) + return 0; + + if (level == AMD_DPM_FORCED_LEVEL_PROFILING) + amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILING && + current_level == AMD_DPM_FORCED_LEVEL_PROFILING) + amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + if (adev->pp_enabled) amdgpu_dpm_force_performance_level(adev, level); else { diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index ab7d2bb71dad..9a544ad41f4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6571,8 +6571,8 @@ static int ci_dpm_force_clock_level(struct amdgpu_device *adev, { struct ci_power_info *pi = ci_get_pi(adev); - if (adev->pm.dpm.forced_level - != AMD_DPM_FORCED_LEVEL_MANUAL) + if (!(adev->pm.dpm.forced_level & + (AMD_DPM_FORCED_LEVEL_MANUAL | AMD_DPM_FORCED_LEVEL_PROFILING))) return -EINVAL; switch (type) { diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index c92532caa05d..92138a9f6f93 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -85,6 +85,7 @@ enum amd_dpm_forced_level { AMD_DPM_FORCED_LEVEL_MANUAL = 0x2, AMD_DPM_FORCED_LEVEL_LOW = 0x4, AMD_DPM_FORCED_LEVEL_HIGH = 0x8, + AMD_DPM_FORCED_LEVEL_PROFILING = 0x10, }; enum amd_powergating_state { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 9bb94af731a9..f4ff236af96a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1644,7 +1644,8 @@ static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr, static int cz_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask) { - if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) + if (!(hwmgr->dpm_level & + (AMD_DPM_FORCED_LEVEL_MANUAL | AMD_DPM_FORCED_LEVEL_PROFILING))) return -EINVAL; switch (type) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 9232c118534a..8bd1e9669fd7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -4031,7 +4031,8 @@ static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) + if (!(hwmgr->dpm_level & + (AMD_DPM_FORCED_LEVEL_MANUAL | AMD_DPM_FORCED_LEVEL_PROFILING))) return -EINVAL; switch (type) { -- cgit From 570272d2296ce42b7d0b4c5afa5b668100930507 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 6 Jan 2017 13:32:49 +0800 Subject: drm/amdgpu: extend profiling mode. in profiling mode, powerplay will fix power state as stable as possible.and disable gfx cg and LBPW feature. profile_standard: as a prerequisite, ensure power and thermal sustainable, set clocks ratio as close to the highest clock ratio as possible. profile_min_sclk: fix mclk as profile_normal, set lowest sclk profile_min_mclk: fix sclk as profile_normal, set lowest mclk profile_peak: set highest sclk and mclk, power and thermal not sustainable profile_exit: exit profile mode. enable gfx cg/lbpw feature. Signed-off-by: Rex Zhu Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 38 ++++--- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 5 +- drivers/gpu/drm/amd/include/amd_shared.h | 6 +- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 3 +- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 127 ++++++++++++++++++++++- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 6 files changed, 154 insertions(+), 26 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 9abd8f6705c0..f35893c19531 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -142,12 +142,15 @@ static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, level = amdgpu_dpm_get_performance_level(adev); return snprintf(buf, PAGE_SIZE, "%s\n", - (level & (AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : - (level & AMD_DPM_FORCED_LEVEL_LOW) ? "low" : - (level & AMD_DPM_FORCED_LEVEL_HIGH) ? "high" : - (level & AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" : - (level & AMD_DPM_FORCED_LEVEL_PROFILING) ? "profiling" : - "unknown")); + (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : + (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : + (level == AMD_DPM_FORCED_LEVEL_HIGH) ? "high" : + (level == AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) ? "profile_standard" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) ? "profile_min_sclk" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) ? "profile_min_mclk" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) ? "profile_peak" : + "unknown"); } static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, @@ -176,9 +179,17 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, level = AMD_DPM_FORCED_LEVEL_AUTO; } else if (strncmp("manual", buf, strlen("manual")) == 0) { level = AMD_DPM_FORCED_LEVEL_MANUAL; - } else if (strncmp("profile", buf, strlen("profile")) == 0) { - level = AMD_DPM_FORCED_LEVEL_PROFILING; - } else { + } else if (strncmp("profile_exit", buf, strlen("profile_exit")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_EXIT; + } else if (strncmp("profile_standard", buf, strlen("profile_standard")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD; + } else if (strncmp("profile_min_sclk", buf, strlen("profile_min_sclk")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK; + } else if (strncmp("profile_min_mclk", buf, strlen("profile_min_mclk")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK; + } else if (strncmp("profile_peak", buf, strlen("profile_peak")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + } else { count = -EINVAL; goto fail; } @@ -186,14 +197,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, if (current_level == level) return count; - if (level == AMD_DPM_FORCED_LEVEL_PROFILING) - amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - else if (level != AMD_DPM_FORCED_LEVEL_PROFILING && - current_level == AMD_DPM_FORCED_LEVEL_PROFILING) - amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - if (adev->pp_enabled) amdgpu_dpm_force_performance_level(adev, level); else { @@ -210,6 +213,7 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, adev->pm.dpm.forced_level = level; mutex_unlock(&adev->pm.mutex); } + fail: return count; } diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 9a544ad41f4c..ece94eeb638e 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6571,8 +6571,9 @@ static int ci_dpm_force_clock_level(struct amdgpu_device *adev, { struct ci_power_info *pi = ci_get_pi(adev); - if (!(adev->pm.dpm.forced_level & - (AMD_DPM_FORCED_LEVEL_MANUAL | AMD_DPM_FORCED_LEVEL_PROFILING))) + if (adev->pm.dpm.forced_level & (AMD_DPM_FORCED_LEVEL_AUTO | + AMD_DPM_FORCED_LEVEL_LOW | + AMD_DPM_FORCED_LEVEL_HIGH)) return -EINVAL; switch (type) { diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 5fffe6f72640..43f45adeccd1 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -85,7 +85,11 @@ enum amd_dpm_forced_level { AMD_DPM_FORCED_LEVEL_MANUAL = 0x2, AMD_DPM_FORCED_LEVEL_LOW = 0x4, AMD_DPM_FORCED_LEVEL_HIGH = 0x8, - AMD_DPM_FORCED_LEVEL_PROFILING = 0x10, + AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD = 0x10, + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK = 0x20, + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK = 0x40, + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK = 0x80, + AMD_DPM_FORCED_LEVEL_PROFILE_EXIT = 0x100, }; enum amd_powergating_state { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index c15af0b6797c..a4cde3d778b8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1650,8 +1650,7 @@ static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr, static int cz_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask) { - if (!(hwmgr->dpm_level & - (AMD_DPM_FORCED_LEVEL_MANUAL | AMD_DPM_FORCED_LEVEL_PROFILING))) + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) return -EINVAL; switch (type) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 3777996b36dc..6c661bb7e2f3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -90,6 +90,8 @@ enum DPM_EVENT_SRC { }; static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic); +static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask); static struct smu7_power_state *cast_phw_smu7_power_state( struct pp_hw_power_state *hw_ps) @@ -2488,36 +2490,152 @@ static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr) } return 0; +} + +static int smu7_get_profiling_clk(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, + uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *pcie_mask) +{ + uint32_t percentage; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table; + int32_t tmp_mclk; + int32_t tmp_sclk; + int32_t count; + + if (golden_dpm_table->mclk_table.count < 1) + return -EINVAL; + + percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value / + golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; + + if (golden_dpm_table->mclk_table.count == 1) { + percentage = 70; + tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; + *mclk_mask = golden_dpm_table->mclk_table.count - 1; + } else { + tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value; + *mclk_mask = golden_dpm_table->mclk_table.count - 2; + } + + tmp_sclk = tmp_mclk * percentage / 100; + + if (hwmgr->pp_table_version == PP_TABLE_V0) { + for (count = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; + count >= 0; count--) { + if (tmp_sclk >= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk) { + tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk; + *sclk_mask = count; + break; + } + } + if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) + *sclk_mask = 0; + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + *sclk_mask = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; + } else if (hwmgr->pp_table_version == PP_TABLE_V1) { + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + for (count = table_info->vdd_dep_on_sclk->count-1; count >= 0; count--) { + if (tmp_sclk >= table_info->vdd_dep_on_sclk->entries[count].clk) { + tmp_sclk = table_info->vdd_dep_on_sclk->entries[count].clk; + *sclk_mask = count; + break; + } + } + if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) + *sclk_mask = 0; + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) + *mclk_mask = 0; + else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + *mclk_mask = golden_dpm_table->mclk_table.count - 1; + + *pcie_mask = data->dpm_table.pcie_speed_table.count - 1; + return 0; } + static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level) { int ret = 0; + uint32_t sclk_mask = 0; + uint32_t mclk_mask = 0; + uint32_t pcie_mask = 0; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + + if (level == hwmgr->dpm_level) + return ret; + + if (!(hwmgr->dpm_level & profile_mode_mask)) { + /* enter profile mode, save current level, disable gfx cg*/ + if (level & profile_mode_mask) { + hwmgr->saved_dpm_level = hwmgr->dpm_level; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } + } else { + /* exit profile mode, restore level, enable gfx cg*/ + if (!(level & profile_mode_mask)) { + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) + level = hwmgr->saved_dpm_level; + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + } + } switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: ret = smu7_force_dpm_highest(hwmgr); if (ret) return ret; + hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_LOW: ret = smu7_force_dpm_lowest(hwmgr); if (ret) return ret; + hwmgr->dpm_level = level; break; case AMD_DPM_FORCED_LEVEL_AUTO: ret = smu7_unforce_dpm_levels(hwmgr); if (ret) return ret; + hwmgr->dpm_level = level; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); + if (ret) + return ret; + hwmgr->dpm_level = level; + smu7_force_clock_level(hwmgr, PP_SCLK, 1<dpm_level = level; + if (level & (AMD_DPM_FORCED_LEVEL_PROFILE_PEAK | AMD_DPM_FORCED_LEVEL_HIGH)) + smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + else + smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); - return ret; + return 0; } static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr) @@ -4051,8 +4169,9 @@ static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - if (!(hwmgr->dpm_level & - (AMD_DPM_FORCED_LEVEL_MANUAL | AMD_DPM_FORCED_LEVEL_PROFILING))) + if (hwmgr->dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO | + AMD_DPM_FORCED_LEVEL_LOW | + AMD_DPM_FORCED_LEVEL_HIGH)) return -EINVAL; switch (type) { diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 27217a7ae039..7275a29293eb 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -612,6 +612,7 @@ struct pp_hwmgr { uint32_t num_vce_state_tables; enum amd_dpm_forced_level dpm_level; + enum amd_dpm_forced_level saved_dpm_level; bool block_hw_access; struct phm_gfx_arbiter gfx_arbiter; struct phm_acp_arbiter acp_arbiter; -- cgit From a1970a6382b8781380de9494b2e256aa85814b79 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 12 Jan 2017 21:50:18 +0800 Subject: drm/amdgpu: refine ci uvd dpm code. Fix up the powergating logic. Signed-off-by: Rex Zhu Ack-by: Tom St Denis Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index ece94eeb638e..9498e78b90d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -889,7 +889,16 @@ static void ci_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) pi->uvd_power_gated = gate; - ci_update_uvd_dpm(adev, gate); + if (gate) { + /* stop the UVD block */ + amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + ci_update_uvd_dpm(adev, gate); + } else { + amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_UNGATE); + ci_update_uvd_dpm(adev, gate); + } } static bool ci_dpm_vblank_too_short(struct amdgpu_device *adev) -- cgit From bac601ec00d306728aed18f0a09f10c58d5acaba Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Fri, 3 Feb 2017 17:33:11 +0800 Subject: drm/amdgpu: fix uvd can't initialized when dpm disabled on Ci. need to start smc when dpm disabled. otherwise, uvd can't get response from smu. so uvd ring test and ib test will timeout. Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 9498e78b90d7..a947022bfee8 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -2210,7 +2210,6 @@ static void ci_clear_vc(struct amdgpu_device *adev) static int ci_upload_firmware(struct amdgpu_device *adev) { - struct ci_power_info *pi = ci_get_pi(adev); int i, ret; if (amdgpu_ci_is_smc_running(adev)) { @@ -2227,7 +2226,7 @@ static int ci_upload_firmware(struct amdgpu_device *adev) amdgpu_ci_stop_smc_clock(adev); amdgpu_ci_reset_smc(adev); - ret = amdgpu_ci_load_smc_ucode(adev, pi->sram_end); + ret = amdgpu_ci_load_smc_ucode(adev, SMC_RAM_END); return ret; @@ -6278,13 +6277,13 @@ static int ci_dpm_sw_init(void *handle) adev->pm.current_mclk = adev->clock.default_mclk; adev->pm.int_thermal_type = THERMAL_TYPE_NONE; - if (amdgpu_dpm == 0) - return 0; - ret = ci_dpm_init_microcode(adev); if (ret) return ret; + if (amdgpu_dpm == 0) + return 0; + INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); mutex_lock(&adev->pm.mutex); ret = ci_dpm_init(adev); @@ -6328,8 +6327,15 @@ static int ci_dpm_hw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (!amdgpu_dpm) + if (!amdgpu_dpm) { + ret = ci_upload_firmware(adev); + if (ret) { + DRM_ERROR("ci_upload_firmware failed\n"); + return ret; + } + ci_dpm_start_smc(adev); return 0; + } mutex_lock(&adev->pm.mutex); ci_dpm_setup_asic(adev); @@ -6351,6 +6357,8 @@ static int ci_dpm_hw_fini(void *handle) mutex_lock(&adev->pm.mutex); ci_dpm_disable(adev); mutex_unlock(&adev->pm.mutex); + } else { + ci_dpm_stop_smc(adev); } return 0; -- cgit From beeea9819d1b85ea4f4beb09d176de9889079c75 Mon Sep 17 00:00:00 2001 From: Rex Zhu Date: Thu, 26 Jan 2017 16:25:05 +0800 Subject: drm/amdgpu: refine code for VCE2.0 and related dpm code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: clean up vce cg function. use sw cg when vce stoped. 1. implement vce_stop function. 2. not start vce when hw_init. 3. refine vce cg/pg code. 4. delete bypass mode. Signed-off-by: Rex Zhu Acked-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 12 ++- drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 9 -- drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 39 ++------ drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 163 +++++++++++++++++++-------------- 4 files changed, 111 insertions(+), 112 deletions(-) (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index a61882ddc804..95e026a4a2de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1142,12 +1142,22 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) /* XXX select vce level based on ring/task */ adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; mutex_unlock(&adev->pm.mutex); + amdgpu_pm_compute_clocks(adev); + amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_UNGATE); } else { + amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_GATE); mutex_lock(&adev->pm.mutex); adev->pm.dpm.vce_active = false; mutex_unlock(&adev->pm.mutex); + amdgpu_pm_compute_clocks(adev); } - amdgpu_pm_compute_clocks(adev); + } } diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index a947022bfee8..f97ecb49972e 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -4256,12 +4256,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev, if (amdgpu_current_state->evclk != amdgpu_new_state->evclk) { if (amdgpu_new_state->evclk) { - /* turn the clocks on when encoding */ - ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_UNGATE); - if (ret) - return ret; - pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(adev); tmp = RREG32_SMC(ixDPM_TABLE_475); tmp &= ~DPM_TABLE_475__VceBootLevel_MASK; @@ -4273,9 +4267,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev, ret = ci_enable_vce_dpm(adev, false); if (ret) return ret; - /* turn the clocks off when not encoding */ - ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_GATE); } } return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index 8159a2dbe427..f5a343cb0010 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -1550,11 +1550,6 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev, if (amdgpu_new_state->evclk > 0 && amdgpu_current_state->evclk == 0) { kv_dpm_powergate_vce(adev, false); - /* turn the clocks on when encoding */ - ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_UNGATE); - if (ret) - return ret; if (pi->caps_stable_p_state) pi->vce_boot_level = table->count - 1; else @@ -1573,15 +1568,9 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev, amdgpu_kv_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_VCEDPM_SetEnabledMask, (1 << pi->vce_boot_level)); - kv_enable_vce_dpm(adev, true); } else if (amdgpu_new_state->evclk == 0 && amdgpu_current_state->evclk > 0) { kv_enable_vce_dpm(adev, false); - /* turn the clocks off when not encoding */ - ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_GATE); - if (ret) - return ret; kv_dpm_powergate_vce(adev, true); } @@ -1713,32 +1702,19 @@ static void kv_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) static void kv_dpm_powergate_vce(struct amdgpu_device *adev, bool gate) { struct kv_power_info *pi = kv_get_pi(adev); - int ret; if (pi->vce_power_gated == gate) return; pi->vce_power_gated = gate; - if (gate) { - if (pi->caps_vce_pg) { - /* shutdown the VCE block */ - ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_GATE); - /* XXX: check for errors */ - /* power off the VCE block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF); - } - } else { - if (pi->caps_vce_pg) { - /* power on the VCE block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); - /* re-init the VCE block */ - ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_UNGATE); - /* XXX: check for errors */ - } - } + if (!pi->caps_vce_pg) + return; + + if (gate) + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF); + else + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); } static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate) @@ -2996,7 +2972,6 @@ static int kv_dpm_late_init(void *handle) kv_dpm_powergate_acp(adev, true); kv_dpm_powergate_samu(adev, true); - kv_dpm_powergate_vce(adev, true); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index 38ed903dd6f8..13c794961073 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -46,6 +46,11 @@ static void vce_v2_0_mc_resume(struct amdgpu_device *adev); static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev); static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev); static int vce_v2_0_wait_for_idle(void *handle); +static void vce_v2_0_init_cg(struct amdgpu_device *adev); +static void vce_v2_0_disable_cg(struct amdgpu_device *adev); +static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable, + bool sw_cg); + /** * vce_v2_0_ring_get_rptr - get read pointer * @@ -152,11 +157,14 @@ static int vce_v2_0_start(struct amdgpu_device *adev) struct amdgpu_ring *ring; int r; - vce_v2_0_mc_resume(adev); - /* set BUSY flag */ WREG32_P(mmVCE_STATUS, 1, ~1); + vce_v2_0_init_cg(adev); + vce_v2_0_disable_cg(adev); + + vce_v2_0_mc_resume(adev); + ring = &adev->vce.ring[0]; WREG32(mmVCE_RB_RPTR, ring->wptr); WREG32(mmVCE_RB_WPTR, ring->wptr); @@ -189,6 +197,54 @@ static int vce_v2_0_start(struct amdgpu_device *adev) return 0; } +static int vce_v2_0_stop(struct amdgpu_device *adev) +{ + int i, j; + int status; + + if (vce_v2_0_lmi_clean(adev)) { + DRM_INFO("vce is not idle \n"); + return 0; + } +/* + for (i = 0; i < 10; ++i) { + for (j = 0; j < 100; ++j) { + status = RREG32(mmVCE_FW_REG_STATUS); + if (!(status & 1)) + break; + mdelay(1); + } + break; + } +*/ + if (vce_v2_0_wait_for_idle(adev)) { + DRM_INFO("VCE is busy, Can't set clock gateing"); + return 0; + } + + /* Stall UMC and register bus before resetting VCPU */ + WREG32_P(mmVCE_LMI_CTRL2, 1 << 8, ~(1 << 8)); + + for (i = 0; i < 10; ++i) { + for (j = 0; j < 100; ++j) { + status = RREG32(mmVCE_LMI_STATUS); + if (status & 0x240) + break; + mdelay(1); + } + break; + } + + WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x80001); + + /* put LMI, VCPU, RBC etc... into reset */ + WREG32_P(mmVCE_SOFT_RESET, 1, ~0x1); + + WREG32(mmVCE_STATUS, 0); + + return 0; +} + static int vce_v2_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -254,11 +310,8 @@ static int vce_v2_0_hw_init(void *handle) int r, i; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = vce_v2_0_start(adev); - /* this error mean vcpu not in running state, so just skip ring test, not stop driver initialize */ - if (r) - return 0; - + amdgpu_asic_set_vce_clocks(adev, 10000, 10000); + vce_v2_0_enable_mgcg(adev, true, false); for (i = 0; i < adev->vce.num_rings; i++) adev->vce.ring[i].ready = false; @@ -349,50 +402,40 @@ static void vce_v2_0_set_sw_cg(struct amdgpu_device *adev, bool gated) static void vce_v2_0_set_dyn_cg(struct amdgpu_device *adev, bool gated) { - if (vce_v2_0_wait_for_idle(adev)) { - DRM_INFO("VCE is busy, Can't set clock gateing"); - return; - } - - WREG32_P(mmVCE_LMI_CTRL2, 0x100, ~0x100); + u32 orig, tmp; - if (vce_v2_0_lmi_clean(adev)) { - DRM_INFO("LMI is busy, Can't set clock gateing"); - return; - } - - WREG32_P(mmVCE_VCPU_CNTL, 0, ~VCE_VCPU_CNTL__CLK_EN_MASK); - WREG32_P(mmVCE_SOFT_RESET, - VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, - ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); - WREG32(mmVCE_STATUS, 0); +/* LMI_MC/LMI_UMC always set in dynamic, + * set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0} + */ + tmp = RREG32(mmVCE_CLOCK_GATING_B); + tmp &= ~0x00060006; - if (gated) - WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0); - /* LMI_MC/LMI_UMC always set in dynamic, set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0} */ +/* Exception for ECPU, IH, SEM, SYS blocks needs to be turned on/off by SW */ if (gated) { - /* Force CLOCK OFF , set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {*, 1} */ - WREG32(mmVCE_CLOCK_GATING_B, 0xe90010); + tmp |= 0xe10000; + WREG32(mmVCE_CLOCK_GATING_B, tmp); } else { - /* Force CLOCK ON, set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {1, 0} */ - WREG32(mmVCE_CLOCK_GATING_B, 0x800f1); + tmp |= 0xe1; + tmp &= ~0xe10000; + WREG32(mmVCE_CLOCK_GATING_B, tmp); } - /* Set VCE_UENC_CLOCK_GATING always in dynamic mode {*_FORCE_ON, *_FORCE_OFF} = {0, 0}*/; - WREG32(mmVCE_UENC_CLOCK_GATING, 0x40); + orig = tmp = RREG32(mmVCE_UENC_CLOCK_GATING); + tmp &= ~0x1fe000; + tmp &= ~0xff000000; + if (tmp != orig) + WREG32(mmVCE_UENC_CLOCK_GATING, tmp); + + orig = tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING); + tmp &= ~0x3fc; + if (tmp != orig) + WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp); /* set VCE_UENC_REG_CLOCK_GATING always in dynamic mode */ WREG32(mmVCE_UENC_REG_CLOCK_GATING, 0x00); - WREG32_P(mmVCE_LMI_CTRL2, 0, ~0x100); - if(!gated) { - WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, ~VCE_VCPU_CNTL__CLK_EN_MASK); - mdelay(100); - WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK); - - vce_v2_0_firmware_loaded(adev); - WREG32_P(mmVCE_STATUS, 0, ~VCE_STATUS__JOB_BUSY_MASK); - } + if(gated) + WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0); } static void vce_v2_0_disable_cg(struct amdgpu_device *adev) @@ -400,10 +443,9 @@ static void vce_v2_0_disable_cg(struct amdgpu_device *adev) WREG32(mmVCE_CGTT_CLK_OVERRIDE, 7); } -static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable) +static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable, + bool sw_cg) { - bool sw_cg = false; - if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) { if (sw_cg) vce_v2_0_set_sw_cg(adev, true); @@ -473,8 +515,6 @@ static void vce_v2_0_mc_resume(struct amdgpu_device *adev) WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100); WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1); - - vce_v2_0_init_cg(adev); } static bool vce_v2_0_is_idle(void *handle) @@ -539,33 +579,20 @@ static int vce_v2_0_process_interrupt(struct amdgpu_device *adev, return 0; } -static void vce_v2_0_set_bypass_mode(struct amdgpu_device *adev, bool enable) -{ - u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL); - - if (enable) - tmp |= GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK; - else - tmp &= ~GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK; - - WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp); -} - - static int vce_v2_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { bool gate = false; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - bool enable = (state == AMD_CG_STATE_GATE) ? true : false; - + bool sw_cg = false; - vce_v2_0_set_bypass_mode(adev, enable); + struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (state == AMD_CG_STATE_GATE) + if (state == AMD_CG_STATE_GATE) { gate = true; + sw_cg = true; + } - vce_v2_0_enable_mgcg(adev, gate); + vce_v2_0_enable_mgcg(adev, gate, sw_cg); return 0; } @@ -582,12 +609,8 @@ static int vce_v2_0_set_powergating_state(void *handle, */ struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE)) - return 0; - if (state == AMD_PG_STATE_GATE) - /* XXX do we need a vce_v2_0_stop()? */ - return 0; + return vce_v2_0_stop(adev); else return vce_v2_0_start(adev); } -- cgit