+ for (i=0; i<data->dpm_table.sclk_table.count; i++) {
+ if (odn_table->odn_core_clock_dpm_levels.entries[i].clock !=
+
data->dpm_table.sclk_table.dpm_levels[i].value) {
+ data->need_update_smu7_dpm_table |=
DPMTABLE_OD_UPDATE_SCLK;
+ break;
+ }
+ }
+
+ for (i=0; i<data->dpm_table.sclk_table.count; i++) {
typo? sclk_table -> mclk_table?
+ if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock !=
+
data->dpm_table.mclk_table.dpm_levels[i].value) {
+ data->need_update_smu7_dpm_table |=
DPMTABLE_OD_UPDATE_MCLK;
+ break;
+ }
+ }
Regards,
Evan
________________________________
发件人: amd-gfx <[email protected]> 代表 Rex Zhu
<[email protected]>
发送时间: 2018年1月19日 16:10:09
收件人: [email protected]
抄送: Zhu, Rex
主题: [PATCH v2 5/7] drm/amd/pp: Implement edit_dpm_table on smu7
v2: - check clk against OverDrive limits from VBIOS
- set OD flag when user commit the setting.
Change-Id: If7b4f6a1a7049f5d13d47603d3446b66cf6e9d4a
Signed-off-by: Rex Zhu <[email protected]>
---
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 165 ++++++++++++++++++++++-
1 file changed, 164 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index 4ccc910..3ed4b4a 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -4808,6 +4808,169 @@ static int smu7_get_thermal_temperature_range(struct
pp_hwmgr *hwmgr,
return 0;
}
+static bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ uint32_t clk,
+ uint32_t voltage)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+
+ struct phm_ppt_v1_information *table_info =
+ (struct phm_ppt_v1_information *)(hwmgr->pptable);
+ uint32_t min_vddc;
+ struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
+
+ if (table_info == NULL)
+ return -EINVAL;
+
+ dep_sclk_table = table_info->vdd_dep_on_sclk;
+ min_vddc = dep_sclk_table->entries[0].vddc;
+
+ if (voltage < min_vddc || voltage > 2000) {
+ pr_info("OD voltage is out of range [%d - 2000] mV\n",
min_vddc);
+ return false;
+ }
+
+ if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
+ if (data->vbios_boot_state.sclk_bootup_value > clk ||
+ hwmgr->platform_descriptor.overdriveLimit.engineClock <
clk) {
+ pr_info("OD engine clock is out of range [%d - %d]
MHz\n",
+ data->vbios_boot_state.sclk_bootup_value,
+
hwmgr->platform_descriptor.overdriveLimit.engineClock / 100);
+ return false;
+ }
+ } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
+ if (data->vbios_boot_state.mclk_bootup_value > clk ||
+ hwmgr->platform_descriptor.overdriveLimit.memoryClock <
clk) {
+ pr_info("OD memory clock is out of range [%d - %d]
MHz\n",
+ data->vbios_boot_state.mclk_bootup_value/100,
+
hwmgr->platform_descriptor.overdriveLimit.memoryClock / 100);
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
+{
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+ struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
+ struct phm_ppt_v1_information *table_info =
+ (struct phm_ppt_v1_information *)(hwmgr->pptable);
+ uint32_t i;
+
+ struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
+ struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table;
+
+ if (table_info == NULL)
+ return;
+
+ for (i=0; i<data->dpm_table.sclk_table.count; i++) {
+ if (odn_table->odn_core_clock_dpm_levels.entries[i].clock !=
+
data->dpm_table.sclk_table.dpm_levels[i].value) {
+ data->need_update_smu7_dpm_table |=
DPMTABLE_OD_UPDATE_SCLK;
+ break;
+ }
+ }
+
+ for (i=0; i<data->dpm_table.sclk_table.count; i++) {
+ if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock !=
+
data->dpm_table.mclk_table.dpm_levels[i].value) {
+ data->need_update_smu7_dpm_table |=
DPMTABLE_OD_UPDATE_MCLK;
+ break;
+ }
+ }
+
+ dep_table = table_info->vdd_dep_on_mclk;
+ odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table
*)&(odn_table->vdd_dependency_on_mclk);
+
+ for (i=0; i<dep_table->count; i++) {
+ if (dep_table->entries[i].vddc !=
odn_dep_table->entries[i].vddc) {
+ data->need_update_smu7_dpm_table |=
DPMTABLE_OD_UPDATE_VDDC;
+ return;
+ }
+ }
+
+ dep_table = table_info->vdd_dep_on_sclk;
+ odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table
*)&(odn_table->vdd_dependency_on_sclk);
+ for (i=0; i<dep_table->count; i++) {
+ if (dep_table->entries[i].vddc !=
odn_dep_table->entries[i].vddc) {
+ data->need_update_smu7_dpm_table |=
DPMTABLE_OD_UPDATE_VDDC;
+ return;
+ }
+ }
+}
+
+static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
+ enum PP_OD_DPM_TABLE_COMMAND type,
+ long *input, uint32_t size)
+{
+ uint32_t i;
+ struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL;
+ struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend
= NULL;
+ struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+
+ uint32_t input_clk;
+ uint32_t input_vol;
+ uint32_t input_level;
+
+ PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
+ return -EINVAL);
+
+ if (!hwmgr->od_enabled) {
+ pr_info("OverDrive feature not enabled\n");
+ return -EINVAL;
+ }
+
+ if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
+ podn_dpm_table_in_backend =
&data->odn_dpm_table.odn_core_clock_dpm_levels;
+ podn_vdd_dep_in_backend =
&data->odn_dpm_table.vdd_dependency_on_sclk;
+ PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend &&
podn_vdd_dep_in_backend),
+ "Failed to get ODN SCLK and Voltage tables",
+ return -EINVAL);
+ } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
+ podn_dpm_table_in_backend =
&data->odn_dpm_table.odn_memory_clock_dpm_levels;
+ podn_vdd_dep_in_backend =
&data->odn_dpm_table.vdd_dependency_on_mclk;
+
+ PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend &&
podn_vdd_dep_in_backend),
+ "Failed to get ODN MCLK and Voltage tables",
+ return -EINVAL);
+ } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
+ smu7_odn_initial_default_setting(hwmgr);
+ return 0;
+ } else if (PP_OD_COMMIT_DPM_TABLE == type) {
+ smu7_check_dpm_table_updated(hwmgr);
+ return 0;
+ } else {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < size; i += 3) {
+ if (i + 3 > size || input[i] >=
podn_dpm_table_in_backend->num_of_pl) {
+ pr_info("invalid clock voltage input \n");
+ return 0;
+ }
+ input_level = input[i];
+ input_clk = input[i+1] * 100;
+ input_vol = input[i+2];
+
+ if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk,
input_vol)) {
+ podn_dpm_table_in_backend->entries[input_level].clock =
input_clk;
+ podn_vdd_dep_in_backend->entries[input_level].clk =
input_clk;
+ podn_dpm_table_in_backend->entries[input_level].vddc =
input_vol;
+ podn_vdd_dep_in_backend->entries[input_level].vddc =
input_vol;
+ } else {
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+
static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
.backend_init = &smu7_hwmgr_backend_init,
.backend_fini = &smu7_hwmgr_backend_fini,
@@ -4862,6 +5025,7 @@ static int smu7_get_thermal_temperature_range(struct
pp_hwmgr *hwmgr,
.notify_cac_buffer_info = smu7_notify_cac_buffer_info,
.get_max_high_clocks = smu7_get_max_high_clocks,
.get_thermal_temperature_range = smu7_get_thermal_temperature_range,
+ .odn_edit_dpm_table = smu7_odn_edit_dpm_table,
};
uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
@@ -4893,4 +5057,3 @@ int smu7_init_function_pointers(struct pp_hwmgr *hwmgr)
return ret;
}
-
--
1.9.1
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx