aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4416-drm-amdgpu-navi10-implement-sclk-mclk-OD-via-pp_od_c.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4416-drm-amdgpu-navi10-implement-sclk-mclk-OD-via-pp_od_c.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4416-drm-amdgpu-navi10-implement-sclk-mclk-OD-via-pp_od_c.patch274
1 files changed, 274 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4416-drm-amdgpu-navi10-implement-sclk-mclk-OD-via-pp_od_c.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4416-drm-amdgpu-navi10-implement-sclk-mclk-OD-via-pp_od_c.patch
new file mode 100644
index 00000000..55d0d6bd
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4416-drm-amdgpu-navi10-implement-sclk-mclk-OD-via-pp_od_c.patch
@@ -0,0 +1,274 @@
+From a3047065b91b159276dfcb41c6477fd27916c5d0 Mon Sep 17 00:00:00 2001
+From: Matt Coffin <mcoffin13@gmail.com>
+Date: Fri, 8 Nov 2019 14:28:06 -0700
+Subject: [PATCH 4416/4736] drm/amdgpu/navi10: implement sclk/mclk OD via
+ pp_od_clk_voltage
+
+[Why]
+Before this patch, there was no way to use pp_od_clk_voltage on navi
+
+[How]
+Similar to the vega20 implementation, but using the common smc_v11_0
+headers, implemented the pp_od_clk_voltage API for navi10's pptable
+implementation
+
+Reviewed-by: Evan Quan <evan.quan@amd.com>
+Signed-off-by: Matt Coffin <mcoffin13@gmail.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +
+ drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 180 ++++++++++++++++++
+ drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 27 +++
+ 3 files changed, 209 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
+index 36028e9d1011..0ec6ed0456e0 100644
+--- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
++++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
+@@ -251,4 +251,6 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_
+
+ int smu_v11_0_override_pcie_parameters(struct smu_context *smu);
+
++int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool initialize, size_t overdrive_table_size);
++
+ #endif
+diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+index 010be21bee5b..5c4c1f416f3e 100644
+--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
++++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+@@ -1648,10 +1648,188 @@ static int navi10_update_pcie_parameters(struct smu_context *smu,
+ SMU_MSG_OverridePcieParameters,
+ smu_pcie_arg);
+ }
++ return ret;
++}
++
++static inline void navi10_dump_od_table(OverDriveTable_t *od_table) {
++ pr_debug("OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax);
++ pr_debug("OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1);
++ pr_debug("OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2);
++ pr_debug("OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3);
++ pr_debug("OD: UclkFmax: %d\n", od_table->UclkFmax);
++ pr_debug("OD: OverDrivePct: %d\n", od_table->OverDrivePct);
++}
++
++static inline bool navi10_od_feature_is_supported(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_ID feature)
++{
++ return od_table->cap[feature];
++}
++
++static int navi10_od_setting_check_range(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODSETTING_ID setting, uint32_t value)
++{
++ if (value < od_table->min[setting]) {
++ pr_warn("OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]);
++ return -EINVAL;
++ }
++ if (value > od_table->max[setting]) {
++ pr_warn("OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int navi10_setup_od_limits(struct smu_context *smu) {
++ struct smu_11_0_overdrive_table *overdrive_table = NULL;
++ struct smu_11_0_powerplay_table *powerplay_table = NULL;
++
++ if (!smu->smu_table.power_play_table) {
++ pr_err("powerplay table uninitialized!\n");
++ return -ENOENT;
++ }
++ powerplay_table = (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
++ overdrive_table = &powerplay_table->overdrive_table;
++ if (!smu->od_settings) {
++ smu->od_settings = kmemdup(overdrive_table, sizeof(struct smu_11_0_overdrive_table), GFP_KERNEL);
++ } else {
++ memcpy(smu->od_settings, overdrive_table, sizeof(struct smu_11_0_overdrive_table));
++ }
++ return 0;
++}
++
++static int navi10_set_default_od_settings(struct smu_context *smu, bool initialize) {
++ OverDriveTable_t *od_table;
++ int ret = 0;
++
++ ret = smu_v11_0_set_default_od_settings(smu, initialize, sizeof(OverDriveTable_t));
++ if (ret)
++ return ret;
++
++ if (initialize) {
++ ret = navi10_setup_od_limits(smu);
++ if (ret) {
++ pr_err("Failed to retrieve board OD limits\n");
++ return ret;
++ }
++
++ }
++
++ od_table = (OverDriveTable_t *)smu->smu_table.overdrive_table;
++ if (od_table) {
++ navi10_dump_od_table(od_table);
++ }
+
+ return ret;
+ }
+
++static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) {
++ int i;
++ int ret = 0;
++ struct smu_table_context *table_context = &smu->smu_table;
++ OverDriveTable_t *od_table;
++ struct smu_11_0_overdrive_table *od_settings;
++ od_table = (OverDriveTable_t *)table_context->overdrive_table;
++
++ if (!smu->od_enabled) {
++ pr_warn("OverDrive is not enabled!\n");
++ return -EINVAL;
++ }
++
++ if (!smu->od_settings) {
++ pr_err("OD board limits are not set!\n");
++ return -ENOENT;
++ }
++
++ od_settings = smu->od_settings;
++
++ switch (type) {
++ case PP_OD_EDIT_SCLK_VDDC_TABLE:
++ if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODFEATURE_GFXCLK_LIMITS)) {
++ pr_warn("GFXCLK_LIMITS not supported!\n");
++ return -ENOTSUPP;
++ }
++ if (!table_context->overdrive_table) {
++ pr_err("Overdrive is not initialized\n");
++ return -EINVAL;
++ }
++ for (i = 0; i < size; i += 2) {
++ if (i + 2 > size) {
++ pr_info("invalid number of input parameters %d\n", size);
++ return -EINVAL;
++ }
++ switch (input[i]) {
++ case 0:
++ freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN;
++ freq_ptr = &od_table->GfxclkFmin;
++ if (input[i + 1] > od_table->GfxclkFmax) {
++ pr_info("GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n",
++ input[i + 1],
++ od_table->GfxclkFmin);
++ return -EINVAL;
++ }
++ break;
++ case 1:
++ freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX;
++ freq_ptr = &od_table->GfxclkFmax;
++ if (input[i + 1] < od_table->GfxclkFmin) {
++ pr_info("GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n",
++ input[i + 1],
++ od_table->GfxclkFmax);
++ return -EINVAL;
++ }
++ break;
++ default:
++ pr_info("Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]);
++ pr_info("Supported indices: [0:min,1:max]\n");
++ return -EINVAL;
++ }
++ ret = navi10_od_setting_check_range(od_settings, freq_setting, input[i + 1]);
++ if (ret)
++ return ret;
++ *freq_ptr = input[i + 1];
++ }
++ break;
++ case PP_OD_EDIT_MCLK_VDDC_TABLE:
++ if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODFEATURE_UCLK_MAX)) {
++ pr_warn("UCLK_MAX not supported!\n");
++ return -ENOTSUPP;
++ }
++ if (size < 2) {
++ pr_info("invalid number of parameters: %d\n", size);
++ return -EINVAL;
++ }
++ if (input[0] != 1) {
++ pr_info("Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]);
++ pr_info("Supported indices: [1:max]\n");
++ return -EINVAL;
++ }
++ ret = navi10_od_setting_check_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]);
++ if (ret)
++ return ret;
++ od_table->UclkFmax = input[1];
++ break;
++ case PP_OD_COMMIT_DPM_TABLE:
++ navi10_dump_od_table(od_table);
++ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true);
++ if (ret) {
++ pr_err("Failed to import overdrive table!\n");
++ return ret;
++ }
++ // no lock needed because smu_od_edit_dpm_table has it
++ ret = smu_handle_task(smu, smu->smu_dpm.dpm_level,
++ AMD_PP_TASK_READJUST_POWER_STATE,
++ false);
++ if (ret) {
++ return ret;
++ }
++ break;
++ case PP_OD_EDIT_VDDC_CURVE:
++ // TODO: implement
++ return -ENOSYS;
++ default:
++ return -ENOSYS;
++ }
++ return ret;
++}
+
+ static const struct pptable_funcs navi10_ppt_funcs = {
+ .tables_init = navi10_tables_init,
+@@ -1741,6 +1919,8 @@ static const struct pptable_funcs navi10_ppt_funcs = {
+ .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq,
+ .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
+ .override_pcie_parameters = smu_v11_0_override_pcie_parameters,
++ .set_default_od_settings = navi10_set_default_od_settings,
++ .od_edit_dpm_table = navi10_od_edit_dpm_table,
+ };
+
+ void navi10_set_ppt_funcs(struct smu_context *smu)
+diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+index 9ebc00a97096..13ae44ca3504 100644
+--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
++++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+@@ -1778,3 +1778,30 @@ int smu_v11_0_override_pcie_parameters(struct smu_context *smu)
+ return ret;
+
+ }
++
++int smu_v11_0_set_default_od_settings(struct smu_context *smu, bool initialize, size_t overdrive_table_size)
++{
++ struct smu_table_context *table_context = &smu->smu_table;
++ int ret = 0;
++
++ if (initialize) {
++ if (table_context->overdrive_table) {
++ return -EINVAL;
++ }
++ table_context->overdrive_table = kzalloc(overdrive_table_size, GFP_KERNEL);
++ if (!table_context->overdrive_table) {
++ return -ENOMEM;
++ }
++ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, false);
++ if (ret) {
++ pr_err("Failed to export overdrive table!\n");
++ return ret;
++ }
++ }
++ ret = smu_update_table(smu, SMU_TABLE_OVERDRIVE, 0, table_context->overdrive_table, true);
++ if (ret) {
++ pr_err("Failed to import overdrive table!\n");
++ return ret;
++ }
++ return ret;
++}
+--
+2.17.1
+