[PATCH 3/5] drm/amd/pp: Implement edit_dpm_table on smu7

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Change-Id: Ib7414e1afc49d7b313188349b396aeac3a5054b7
Signed-off-by: Rex Zhu <Rex.Zhu at amd.com>
---
 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 121 ++++++++++++++++++++++-
 1 file changed, 120 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..0d14299 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -4808,6 +4808,125 @@ 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_ODN_DPM_TABLE_TYPE type,
+					uint32_t clk,
+					uint32_t voltage)
+{
+	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+
+	if (hwmgr->dyn_state.max_clock_voltage_on_ac.vddc * 120 / 100 < voltage)
+		return false;
+
+	if (type == PP_ODN_SCLK_VDDC_TABLE) {
+		if (data->vbios_boot_state.sclk_bootup_value > clk ||
+			hwmgr->dyn_state.max_clock_voltage_on_ac.sclk * 120 / 100 < clk)
+			return false;
+	} else if (type == PP_ODN_MCLK_VDDC_TABLE) {
+		if (data->vbios_boot_state.mclk_bootup_value > clk ||
+			hwmgr->dyn_state.max_clock_voltage_on_ac.mclk * 120 / 100 < clk)
+			return false;
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
+static void smu7_check_vddc_updated(struct pp_hwmgr *hwmgr,
+		struct phm_ppt_v1_clock_voltage_dependency_table *dep_table,
+		struct smu7_odn_clock_voltage_dependency_table *odn_vdd_dep)
+{
+	int i;
+	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
+
+	if (dep_table->count == 0)
+		return;
+
+	for (i = 0; i < dep_table->count; i++) {
+		if (dep_table->entries[i].vddc != odn_vdd_dep->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_ODN_DPM_TABLE_TYPE type,
+					long *input, uint32_t size)
+{
+	uint32_t i;
+	phm_ppt_v1_clock_voltage_dependency_table *pgolden_vdd_dep_table = NULL;
+	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);
+	struct phm_ppt_v1_information *table_info =
+			(struct phm_ppt_v1_information *)hwmgr->pptable;
+	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 (PP_ODN_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);
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+	} else if (PP_ODN_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);
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+	} else if (PP_ODN_RESET_DEFAULT_TABLE == type) {
+		smu7_odn_initial_default_setting(hwmgr);
+		data->need_update_smu7_dpm_table = DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK;
+		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 {
+			pr_info("invaid input clk/voltage");
+		}
+	}
+
+	if (hwmgr->pp_table_version == PP_TABLE_V1)
+		pgolden_vdd_dep_table = PP_ODN_MCLK_VDDC_TABLE == type ?
+					table_info->vdd_dep_on_mclk:
+					table_info->vdd_dep_on_sclk;
+
+	PP_ASSERT_WITH_CODE(pgolden_vdd_dep_table
+				&& pgolden_vdd_dep_table->count > 0,
+			"Invalid golden_vdd_dep_table",
+			return -EINVAL);
+
+	smu7_check_vddc_updated(hwmgr, pgolden_vdd_dep_table, podn_vdd_dep_in_backend);
+
+	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 +4981,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 +5013,3 @@ int smu7_init_function_pointers(struct pp_hwmgr *hwmgr)
 
 	return ret;
 }
-
-- 
1.9.1



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux