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