diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/1458-drm-amd-powerplay-add-sys-interface-to-set-pp_od_clk.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/1458-drm-amd-powerplay-add-sys-interface-to-set-pp_od_clk.patch | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/1458-drm-amd-powerplay-add-sys-interface-to-set-pp_od_clk.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/1458-drm-amd-powerplay-add-sys-interface-to-set-pp_od_clk.patch new file mode 100644 index 00000000..2a9433f2 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/1458-drm-amd-powerplay-add-sys-interface-to-set-pp_od_clk.patch @@ -0,0 +1,338 @@ +From 03981b1fc9e3d8b81a77f602a366e7ac0bc51dad Mon Sep 17 00:00:00 2001 +From: Likun Gao <Likun.Gao@amd.com> +Date: Mon, 21 Jan 2019 14:58:38 +0800 +Subject: [PATCH 1458/2940] drm/amd/powerplay: add sys interface to set + pp_od_clk_voltage for smu + +Add sys interface to set pp_od_clk_voltage for smu. + +Signed-off-by: Likun Gao <Likun.Gao@amd.com> +Reviewed-by: Huang Rui <ray.huang@amd.com> +Reviewed-by: Kevin Wang <kevin1.wang@amd.com> +Acked-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 30 ++- + .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 7 + + drivers/gpu/drm/amd/powerplay/vega20_ppt.c | 223 ++++++++++++++++++ + 3 files changed, 250 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +index eb17ab94e4bf..925f3898c2f4 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +@@ -649,19 +649,29 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, + tmp_str++; + } + +- if (adev->powerplay.pp_funcs->odn_edit_dpm_table) +- ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, +- parameter, parameter_size); ++ if (is_support_sw_smu(adev)) { ++ ret = smu_od_edit_dpm_table(&adev->smu, type, ++ parameter, parameter_size); + +- if (ret) +- return -EINVAL; ++ if (ret) ++ return -EINVAL; ++ } else { ++ if (adev->powerplay.pp_funcs->odn_edit_dpm_table) ++ ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, ++ parameter, parameter_size); + +- if (type == PP_OD_COMMIT_DPM_TABLE) { +- if (adev->powerplay.pp_funcs->dispatch_tasks) { +- amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); +- return count; +- } else { ++ if (ret) + return -EINVAL; ++ ++ if (type == PP_OD_COMMIT_DPM_TABLE) { ++ if (adev->powerplay.pp_funcs->dispatch_tasks) { ++ amdgpu_dpm_dispatch_task(adev, ++ AMD_PP_TASK_READJUST_POWER_STATE, ++ NULL); ++ return count; ++ } else { ++ return -EINVAL; ++ } + } + } + +diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +index c3bc9a7e3f48..a0bfc378cdc0 100644 +--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h ++++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +@@ -310,6 +310,8 @@ struct smu_table_context + uint32_t *od_settings_min; + void *overdrive_table; + void *od8_settings; ++ bool od_gfxclk_update; ++ bool od_memclk_update; + }; + + struct smu_dpm_context { +@@ -417,6 +419,9 @@ struct pptable_funcs { + int (*set_od_percentage)(struct smu_context *smu, + enum pp_clock_type type, + uint32_t value); ++ int (*od_edit_dpm_table)(struct smu_context *smu, ++ enum PP_OD_DPM_TABLE_COMMAND type, ++ long *input, uint32_t size); + int (*get_clock_by_type_with_latency)(struct smu_context *smu, + enum amd_pp_clock_type type, + struct +@@ -603,6 +608,8 @@ struct smu_funcs + ((smu)->ppt_funcs->get_od_percentage ? (smu)->ppt_funcs->get_od_percentage((smu), (type)) : 0) + #define smu_set_od_percentage(smu, type, value) \ + ((smu)->ppt_funcs->set_od_percentage ? (smu)->ppt_funcs->set_od_percentage((smu), (type), (value)) : 0) ++#define smu_od_edit_dpm_table(smu, type, input, size) \ ++ ((smu)->ppt_funcs->od_edit_dpm_table ? (smu)->ppt_funcs->od_edit_dpm_table((smu), (type), (input), (size)) : 0) + #define smu_start_thermal_control(smu) \ + ((smu)->funcs->start_thermal_control? (smu)->funcs->start_thermal_control((smu)) : 0) + #define smu_read_sensor(smu, sensor, data, size) \ +diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c +index d025f54285ed..ff44ef89204a 100644 +--- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c ++++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c +@@ -1985,6 +1985,228 @@ static int vega20_set_od_percentage(struct smu_context *smu, + return 0; + } + ++static int vega20_odn_edit_dpm_table(struct smu_context *smu, ++ enum PP_OD_DPM_TABLE_COMMAND type, ++ long *input, uint32_t size) ++{ ++ struct smu_table_context *table_context = &smu->smu_table; ++ OverDriveTable_t *od_table = ++ (OverDriveTable_t *)(table_context->overdrive_table); ++ struct smu_dpm_context *smu_dpm = &smu->smu_dpm; ++ struct vega20_dpm_table *dpm_table = NULL; ++ struct vega20_single_dpm_table *single_dpm_table; ++ struct vega20_od8_settings *od8_settings = ++ (struct vega20_od8_settings *)table_context->od8_settings; ++ struct pp_clock_levels_with_latency clocks; ++ int32_t input_index, input_clk, input_vol, i; ++ int od8_id, ret; ++ ++ dpm_table = smu_dpm->dpm_context; ++ ++ if (!input) { ++ pr_warn("NULL user input for clock and voltage\n"); ++ return -EINVAL; ++ } ++ ++ switch (type) { ++ case PP_OD_EDIT_SCLK_VDDC_TABLE: ++ if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id && ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id)) { ++ pr_info("Sclk min/max frequency overdrive not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ for (i = 0; i < size; i += 2) { ++ if (i + 2 > size) { ++ pr_info("invalid number of input parameters %d\n", size); ++ return -EINVAL; ++ } ++ ++ input_index = input[i]; ++ input_clk = input[i + 1]; ++ ++ if (input_index != 0 && input_index != 1) { ++ pr_info("Invalid index %d\n", input_index); ++ pr_info("Support min/max sclk frequency settingonly which index by 0/1\n"); ++ return -EINVAL; ++ } ++ ++ if (input_clk < od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value || ++ input_clk > od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value) { ++ pr_info("clock freq %d is not within allowed range [%d - %d]\n", ++ input_clk, ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].min_value, ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].max_value); ++ return -EINVAL; ++ } ++ ++ if (input_index == 0 && od_table->GfxclkFmin != input_clk) { ++ od_table->GfxclkFmin = input_clk; ++ table_context->od_gfxclk_update = true; ++ } else if (input_index == 1 && od_table->GfxclkFmax != input_clk) { ++ od_table->GfxclkFmax = input_clk; ++ table_context->od_gfxclk_update = true; ++ } ++ } ++ ++ break; ++ ++ case PP_OD_EDIT_MCLK_VDDC_TABLE: ++ if (!od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id) { ++ pr_info("Mclk max frequency overdrive not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ single_dpm_table = &(dpm_table->mem_table); ++ ret = vega20_get_clk_table(smu, &clocks, single_dpm_table); ++ if (ret) { ++ pr_err("Attempt to get memory clk levels Failed!"); ++ return ret; ++ } ++ ++ for (i = 0; i < size; i += 2) { ++ if (i + 2 > size) { ++ pr_info("invalid number of input parameters %d\n", ++ size); ++ return -EINVAL; ++ } ++ ++ input_index = input[i]; ++ input_clk = input[i + 1]; ++ ++ if (input_index != 1) { ++ pr_info("Invalid index %d\n", input_index); ++ pr_info("Support max Mclk frequency setting only which index by 1\n"); ++ return -EINVAL; ++ } ++ ++ if (input_clk < clocks.data[0].clocks_in_khz / 1000 || ++ input_clk > od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value) { ++ pr_info("clock freq %d is not within allowed range [%d - %d]\n", ++ input_clk, ++ clocks.data[0].clocks_in_khz / 1000, ++ od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].max_value); ++ return -EINVAL; ++ } ++ ++ if (input_index == 1 && od_table->UclkFmax != input_clk) { ++ table_context->od_gfxclk_update = true; ++ od_table->UclkFmax = input_clk; ++ } ++ } ++ ++ break; ++ ++ case PP_OD_EDIT_VDDC_CURVE: ++ if (!(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id && ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id && ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id && ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && ++ od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { ++ pr_info("Voltage curve calibrate not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ ++ for (i = 0; i < size; i += 3) { ++ if (i + 3 > size) { ++ pr_info("invalid number of input parameters %d\n", ++ size); ++ return -EINVAL; ++ } ++ ++ input_index = input[i]; ++ input_clk = input[i + 1]; ++ input_vol = input[i + 2]; ++ ++ if (input_index > 2) { ++ pr_info("Setting for point %d is not supported\n", ++ input_index + 1); ++ pr_info("Three supported points index by 0, 1, 2\n"); ++ return -EINVAL; ++ } ++ ++ od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index; ++ if (input_clk < od8_settings->od8_settings_array[od8_id].min_value || ++ input_clk > od8_settings->od8_settings_array[od8_id].max_value) { ++ pr_info("clock freq %d is not within allowed range [%d - %d]\n", ++ input_clk, ++ od8_settings->od8_settings_array[od8_id].min_value, ++ od8_settings->od8_settings_array[od8_id].max_value); ++ return -EINVAL; ++ } ++ ++ od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index; ++ if (input_vol < od8_settings->od8_settings_array[od8_id].min_value || ++ input_vol > od8_settings->od8_settings_array[od8_id].max_value) { ++ pr_info("clock voltage %d is not within allowed range [%d- %d]\n", ++ input_vol, ++ od8_settings->od8_settings_array[od8_id].min_value, ++ od8_settings->od8_settings_array[od8_id].max_value); ++ return -EINVAL; ++ } ++ ++ switch (input_index) { ++ case 0: ++ od_table->GfxclkFreq1 = input_clk; ++ od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE; ++ break; ++ case 1: ++ od_table->GfxclkFreq2 = input_clk; ++ od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE; ++ break; ++ case 2: ++ od_table->GfxclkFreq3 = input_clk; ++ od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE; ++ break; ++ } ++ } ++ ++ break; ++ ++ case PP_OD_RESTORE_DEFAULT_TABLE: ++ ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, false); ++ if (ret) { ++ pr_err("Failed to export over drive table!\n"); ++ return ret; ++ } ++ ++ break; ++ ++ case PP_OD_COMMIT_DPM_TABLE: ++ ret = smu_update_table(smu, TABLE_OVERDRIVE, table_context->overdrive_table, true); ++ if (ret) { ++ pr_err("Failed to import over drive table!\n"); ++ return ret; ++ } ++ ++ /* retrieve updated gfxclk table */ ++ if (table_context->od_gfxclk_update) { ++ table_context->od_gfxclk_update = false; ++ single_dpm_table = &(dpm_table->gfx_table); ++ ++ if (smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT)) { ++ ret = vega20_set_single_dpm_table(smu, single_dpm_table, ++ PPCLK_GFXCLK); ++ if (ret) { ++ pr_err("[Setoverdrive] failed to refresh dpm table!\n"); ++ return ret; ++ } ++ } else { ++ single_dpm_table->count = 1; ++ single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; ++ } ++ } ++ ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static const struct pptable_funcs vega20_ppt_funcs = { + .alloc_dpm_context = vega20_allocate_dpm_context, + .store_powerplay_table = vega20_store_powerplay_table, +@@ -2006,6 +2228,7 @@ static const struct pptable_funcs vega20_ppt_funcs = { + .force_performance_level = vega20_force_performance_level, + .update_specified_od8_value = vega20_update_specified_od8_value, + .set_od_percentage = vega20_set_od_percentage, ++ .od_edit_dpm_table = vega20_odn_edit_dpm_table, + }; + + void vega20_set_ppt_funcs(struct smu_context *smu) +-- +2.17.1 + |