Commit 18d7ab98 authored by Evan Quan's avatar Evan Quan Committed by Alex Deucher
Browse files

drm/amd/powerplay: support custom power profile setting



Support custom power profile mode settings on Arcturus.

Signed-off-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c103c5a3
Loading
Loading
Loading
Loading
+126 −6
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ static struct smu_11_0_cmn2aisc_mapping arcturus_table_map[SMU_TABLE_COUNT] = {
	TAB_MAP(DRIVER_SMU_CONFIG),
	TAB_MAP(OVERDRIVE),
	TAB_MAP(I2C_COMMANDS),
	TAB_MAP(ACTIVITY_MONITOR_COEFF),
};

static struct smu_11_0_cmn2aisc_mapping arcturus_pwr_src_map[SMU_POWER_SOURCE_COUNT] = {
@@ -302,6 +303,10 @@ static int arcturus_tables_init(struct smu_context *smu, struct smu_table *table
	SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
			       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);

	SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
		       sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
		       AMDGPU_GEM_DOMAIN_VRAM);

	smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
	if (!smu_table->metrics_table)
		return -ENOMEM;
@@ -1313,6 +1318,7 @@ static int arcturus_get_power_limit(struct smu_context *smu,
static int arcturus_get_power_profile_mode(struct smu_context *smu,
					   char *buf)
{
	DpmActivityMonitorCoeffInt_t activity_monitor;
	static const char *profile_name[] = {
					"BOOTUP_DEFAULT",
					"3D_FULL_SCREEN",
@@ -1322,13 +1328,34 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
					"COMPUTE",
					"CUSTOM"};
	static const char *title[] = {
			"PROFILE_INDEX(NAME)"};
			"PROFILE_INDEX(NAME)",
			"CLOCK_TYPE(NAME)",
			"FPS",
			"UseRlcBusy",
			"MinActiveFreqType",
			"MinActiveFreq",
			"BoosterFreqType",
			"BoosterFreq",
			"PD_Data_limit_c",
			"PD_Data_error_coeff",
			"PD_Data_error_rate_coeff"};
	uint32_t i, size = 0;
	int16_t workload_type = 0;
	int result = 0;
	uint32_t smu_version;

	if (!smu->pm_enabled || !buf)
	if (!buf)
		return -EINVAL;

	result = smu_get_smc_version(smu, NULL, &smu_version);
	if (result)
		return result;

	if (smu_version >= 0x360d00)
		size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n",
			title[0], title[1], title[2], title[3], title[4], title[5],
			title[6], title[7], title[8], title[9], title[10]);
	else
		size += sprintf(buf + size, "%16s\n",
			title[0]);

@@ -1341,8 +1368,50 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
		if (workload_type < 0)
			continue;

		if (smu_version >= 0x360d00) {
			result = smu_update_table(smu,
						  SMU_TABLE_ACTIVITY_MONITOR_COEFF,
						  workload_type,
						  (void *)(&activity_monitor),
						  false);
			if (result) {
				pr_err("[%s] Failed to get activity monitor!", __func__);
				return result;
			}
		}

		size += sprintf(buf + size, "%2d %14s%s\n",
			i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");

		if (smu_version >= 0x360d00) {
			size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
				" ",
				0,
				"GFXCLK",
				activity_monitor.Gfx_FPS,
				activity_monitor.Gfx_UseRlcBusy,
				activity_monitor.Gfx_MinActiveFreqType,
				activity_monitor.Gfx_MinActiveFreq,
				activity_monitor.Gfx_BoosterFreqType,
				activity_monitor.Gfx_BoosterFreq,
				activity_monitor.Gfx_PD_Data_limit_c,
				activity_monitor.Gfx_PD_Data_error_coeff,
				activity_monitor.Gfx_PD_Data_error_rate_coeff);

			size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
				" ",
				1,
				"UCLK",
				activity_monitor.Mem_FPS,
				activity_monitor.Mem_UseRlcBusy,
				activity_monitor.Mem_MinActiveFreqType,
				activity_monitor.Mem_MinActiveFreq,
				activity_monitor.Mem_BoosterFreqType,
				activity_monitor.Mem_BoosterFreq,
				activity_monitor.Mem_PD_Data_limit_c,
				activity_monitor.Mem_PD_Data_error_coeff,
				activity_monitor.Mem_PD_Data_error_rate_coeff);
		}
	}

	return size;
@@ -1352,18 +1421,69 @@ static int arcturus_set_power_profile_mode(struct smu_context *smu,
					   long *input,
					   uint32_t size)
{
	DpmActivityMonitorCoeffInt_t activity_monitor;
	int workload_type = 0;
	uint32_t profile_mode = input[size];
	int ret = 0;

	if (!smu->pm_enabled)
		return -EINVAL;
	uint32_t smu_version;

	if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
		pr_err("Invalid power profile mode %d\n", profile_mode);
		return -EINVAL;
	}

	ret = smu_get_smc_version(smu, NULL, &smu_version);
	if (ret)
		return ret;

	if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
	     (smu_version >=0x360d00)) {
		ret = smu_update_table(smu,
				       SMU_TABLE_ACTIVITY_MONITOR_COEFF,
				       WORKLOAD_PPLIB_CUSTOM_BIT,
				       (void *)(&activity_monitor),
				       false);
		if (ret) {
			pr_err("[%s] Failed to get activity monitor!", __func__);
			return ret;
		}

		switch (input[0]) {
		case 0: /* Gfxclk */
			activity_monitor.Gfx_FPS = input[1];
			activity_monitor.Gfx_UseRlcBusy = input[2];
			activity_monitor.Gfx_MinActiveFreqType = input[3];
			activity_monitor.Gfx_MinActiveFreq = input[4];
			activity_monitor.Gfx_BoosterFreqType = input[5];
			activity_monitor.Gfx_BoosterFreq = input[6];
			activity_monitor.Gfx_PD_Data_limit_c = input[7];
			activity_monitor.Gfx_PD_Data_error_coeff = input[8];
			activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
			break;
		case 1: /* Uclk */
			activity_monitor.Mem_FPS = input[1];
			activity_monitor.Mem_UseRlcBusy = input[2];
			activity_monitor.Mem_MinActiveFreqType = input[3];
			activity_monitor.Mem_MinActiveFreq = input[4];
			activity_monitor.Mem_BoosterFreqType = input[5];
			activity_monitor.Mem_BoosterFreq = input[6];
			activity_monitor.Mem_PD_Data_limit_c = input[7];
			activity_monitor.Mem_PD_Data_error_coeff = input[8];
			activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
			break;
		}

		ret = smu_update_table(smu,
				       SMU_TABLE_ACTIVITY_MONITOR_COEFF,
				       WORKLOAD_PPLIB_CUSTOM_BIT,
				       (void *)(&activity_monitor),
				       true);
		if (ret) {
			pr_err("[%s] Failed to set activity monitor!", __func__);
			return ret;
		}
	}

	/*
	 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
	 * Not all profile modes are supported on arcturus.
+2 −4
Original line number Diff line number Diff line
@@ -823,7 +823,6 @@ typedef struct {
  uint32_t MmHubPadding[8]; // SMU internal use
} AvfsFuseOverride_t;

/* NOT CURRENTLY USED
typedef struct {
  uint8_t   Gfx_ActiveHystLimit;
  uint8_t   Gfx_IdleHystLimit;
@@ -866,7 +865,6 @@ typedef struct {

  uint32_t  MmHubPadding[8]; // SMU internal use
} DpmActivityMonitorCoeffInt_t;
*/

// These defines are used with the following messages:
// SMC_MSG_TransferTableDram2Smu
@@ -878,11 +876,11 @@ typedef struct {
#define TABLE_PMSTATUSLOG             4
#define TABLE_SMU_METRICS             5
#define TABLE_DRIVER_SMU_CONFIG       6
//#define TABLE_ACTIVITY_MONITOR_COEFF  7
#define TABLE_OVERDRIVE               7
#define TABLE_WAFL_XGMI_TOPOLOGY      8
#define TABLE_I2C_COMMANDS            9
#define TABLE_COUNT                   10
#define TABLE_ACTIVITY_MONITOR_COEFF  10
#define TABLE_COUNT                   11

// These defines are used with the SMC_MSG_SetUclkFastSwitch message.
typedef enum {