[PATCH 3/3] drm/amd/powerplay: retrieve the updated clock table after OD

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

 



With OD settings applied, the clock table will be updated accordingly.
We need to retrieve the new clock tables then.

Change-Id: Iad4e95d3f195a0217456d41e495730578209062b
Signed-off-by: Evan Quan <evan.quan at amd.com>
---
 .../drm/amd/powerplay/hwmgr/vega20_hwmgr.c    | 114 ++++++++++++++----
 .../drm/amd/powerplay/hwmgr/vega20_hwmgr.h    |   2 +
 2 files changed, 90 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 491daf02467a..73fb3a41bd7e 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -516,6 +516,47 @@ static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr,
 	return ret;
 }
 
+static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr)
+{
+	struct vega20_hwmgr *data =
+			(struct vega20_hwmgr *)(hwmgr->backend);
+	struct vega20_single_dpm_table *dpm_table;
+	int ret = 0;
+
+	dpm_table = &(data->dpm_table.gfx_table);
+	if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
+		ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
+		PP_ASSERT_WITH_CODE(!ret,
+				"[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
+				return ret);
+	} else {
+		dpm_table->count = 1;
+		dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
+	}
+
+	return ret;
+}
+
+static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr)
+{
+	struct vega20_hwmgr *data =
+			(struct vega20_hwmgr *)(hwmgr->backend);
+	struct vega20_single_dpm_table *dpm_table;
+	int ret = 0;
+
+	dpm_table = &(data->dpm_table.mem_table);
+	if (data->smu_features[GNLD_DPM_UCLK].enabled) {
+		ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
+		PP_ASSERT_WITH_CODE(!ret,
+				"[SetupDefaultDpmTable] failed to get memclk dpm levels!",
+				return ret);
+	} else {
+		dpm_table->count = 1;
+		dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
+	}
+
+	return ret;
+}
 
 /*
  * This function is to initialize all DPM state tables
@@ -549,28 +590,16 @@ static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
 
 	/* gfxclk */
 	dpm_table = &(data->dpm_table.gfx_table);
-	if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
-		ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK);
-		PP_ASSERT_WITH_CODE(!ret,
-				"[SetupDefaultDpmTable] failed to get gfxclk dpm levels!",
-				return ret);
-	} else {
-		dpm_table->count = 1;
-		dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100;
-	}
+	ret = vega20_setup_gfxclk_dpm_table(hwmgr);
+	if (ret)
+		return ret;
 	vega20_init_dpm_state(&(dpm_table->dpm_state));
 
 	/* memclk */
 	dpm_table = &(data->dpm_table.mem_table);
-	if (data->smu_features[GNLD_DPM_UCLK].enabled) {
-		ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK);
-		PP_ASSERT_WITH_CODE(!ret,
-				"[SetupDefaultDpmTable] failed to get memclk dpm levels!",
-				return ret);
-	} else {
-		dpm_table->count = 1;
-		dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100;
-	}
+	ret = vega20_setup_memclk_dpm_table(hwmgr);
+	if (ret)
+		return ret;
 	vega20_init_dpm_state(&(dpm_table->dpm_state));
 
 	/* eclk */
@@ -1183,6 +1212,9 @@ static int vega20_od8_set_settings(
 {
 	OverDriveTable_t od_table;
 	int ret = 0;
+	struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
+	struct vega20_od8_single_setting *od8_settings =
+			data->od8_settings.od8_settings_array;
 
 	ret = vega20_copy_table_from_smc(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE);
 	PP_ASSERT_WITH_CODE(!ret,
@@ -1194,6 +1226,10 @@ static int vega20_od8_set_settings(
 		od_table.GfxclkFmin = (uint16_t)value;
 		break;
 	case OD8_SETTING_GFXCLK_FMAX:
+		if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value ||
+		    value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value)
+			return -EINVAL;
+
 		od_table.GfxclkFmax = (uint16_t)value;
 		break;
 	case OD8_SETTING_GFXCLK_FREQ1:
@@ -1215,6 +1251,9 @@ static int vega20_od8_set_settings(
 		od_table.GfxclkVolt3 = (uint16_t)value;
 		break;
 	case OD8_SETTING_UCLK_FMAX:
+		if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value ||
+		    value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value)
+			return -EINVAL;
 		od_table.UclkFmax = (uint16_t)value;
 		break;
 	case OD8_SETTING_POWER_PERCENTAGE:
@@ -1264,8 +1303,6 @@ static int vega20_set_sclk_od(
 		struct pp_hwmgr *hwmgr, uint32_t value)
 {
 	struct vega20_hwmgr *data = hwmgr->backend;
-	struct vega20_single_dpm_table *sclk_table =
-			&(data->dpm_table.gfx_table);
 	struct vega20_single_dpm_table *golden_sclk_table =
 			&(data->golden_dpm_table.gfx_table);
 	uint32_t od_sclk;
@@ -1280,8 +1317,8 @@ static int vega20_set_sclk_od(
 			"[SetSclkOD] failed to set od gfxclk!",
 			return ret);
 
-	/* refresh gfxclk table */
-	ret = vega20_setup_single_dpm_table(hwmgr, sclk_table, PPCLK_GFXCLK);
+	/* retrieve updated gfxclk table */
+	ret = vega20_setup_gfxclk_dpm_table(hwmgr);
 	PP_ASSERT_WITH_CODE(!ret,
 			"[SetSclkOD] failed to refresh gfxclk table!",
 			return ret);
@@ -1311,8 +1348,6 @@ static int vega20_set_mclk_od(
 		struct pp_hwmgr *hwmgr, uint32_t value)
 {
 	struct vega20_hwmgr *data = hwmgr->backend;
-	struct vega20_single_dpm_table *mclk_table =
-			&(data->dpm_table.mem_table);
 	struct vega20_single_dpm_table *golden_mclk_table =
 			&(data->golden_dpm_table.mem_table);
 	uint32_t od_mclk;
@@ -1327,8 +1362,8 @@ static int vega20_set_mclk_od(
 			"[SetMclkOD] failed to set od memclk!",
 			return ret);
 
-	/* refresh memclk table */
-	ret = vega20_setup_single_dpm_table(hwmgr, mclk_table, PPCLK_UCLK);
+	/* retrieve updated memclk table */
+	ret = vega20_setup_memclk_dpm_table(hwmgr);
 	PP_ASSERT_WITH_CODE(!ret,
 			"[SetMclkOD] failed to refresh memclk table!",
 			return ret);
@@ -2467,6 +2502,10 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
 				return -EINVAL;
 			}
 
+			if ((input_index == 0 && od_table->GfxclkFmin != input_clk) ||
+			    (input_index == 1 && od_table->GfxclkFmax != input_clk))
+				data->gfxclk_overdrive = true;
+
 			if (input_index == 0)
 				od_table->GfxclkFmin = input_clk;
 			else
@@ -2511,6 +2550,9 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
 				return -EINVAL;
 			}
 
+			if (input_index == 1 && od_table->UclkFmax != input_clk)
+				data->memclk_overdrive = true;
+
 			od_table->UclkFmax = input_clk;
 		}
 
@@ -2583,6 +2625,9 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
 		break;
 
 	case PP_OD_RESTORE_DEFAULT_TABLE:
+		data->gfxclk_overdrive = false;
+		data->memclk_overdrive = false;
+
 		ret = vega20_copy_table_from_smc(hwmgr,
 				(uint8_t *)od_table,
 				TABLE_OVERDRIVE);
@@ -2599,6 +2644,23 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
 				"Failed to import overdrive table!",
 				return ret);
 
+		/* retrieve updated gfxclk table */
+		if (data->gfxclk_overdrive) {
+			data->gfxclk_overdrive = false;
+
+			ret = vega20_setup_gfxclk_dpm_table(hwmgr);
+			if (ret)
+				return ret;
+		}
+
+		/* retrieve updated memclk table */
+		if (data->memclk_overdrive) {
+			data->memclk_overdrive = false;
+
+			ret = vega20_setup_memclk_dpm_table(hwmgr);
+			if (ret)
+				return ret;
+		}
 		break;
 
 	default:
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h
index b71a5f25c734..56fe6a0d42e8 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h
@@ -502,6 +502,8 @@ struct vega20_hwmgr {
 
 	/* ---- Overdrive next setting ---- */
 	struct vega20_odn_data         odn_data;
+	bool                           gfxclk_overdrive;
+	bool                           memclk_overdrive;
 
 	/* ---- Overdrive8 Setting ---- */
 	struct vega20_od8_settings     od8_settings;
-- 
2.19.0



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

  Powered by Linux