File Index
Files and directories
Sign in
FILE

renoir_ppt.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c C
   1/*
   2 * Copyright 2019 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 */
  23
  24#define SWSMU_CODE_LAYER_L2
  25
  26#include "amdgpu.h"
  27#include "amdgpu_smu.h"
  28#include "smu_v12_0_ppsmc.h"
  29#include "smu12_driver_if.h"
  30#include "smu_v12_0.h"
  31#include "renoir_ppt.h"
  32#include "smu_cmn.h"
  33
  34/*
  35 * DO NOT use these for err/warn/info/debug messages.
  36 * Use dev_err, dev_warn, dev_info and dev_dbg instead.
  37 * They are more MGPU friendly.
  38 */
  39#undef pr_err
  40#undef pr_warn
  41#undef pr_info
  42#undef pr_debug
  43
  44#define mmMP1_SMN_C2PMSG_66                                                                            0x0282
  45#define mmMP1_SMN_C2PMSG_66_BASE_IDX                                                                   0
  46
  47#define mmMP1_SMN_C2PMSG_82                                                                            0x0292
  48#define mmMP1_SMN_C2PMSG_82_BASE_IDX                                                                   0
  49
  50#define mmMP1_SMN_C2PMSG_90                                                                            0x029a
  51#define mmMP1_SMN_C2PMSG_90_BASE_IDX                                                                   0
  52
  53static struct cmn2asic_msg_mapping renoir_message_map[SMU_MSG_MAX_COUNT] = {
  54	MSG_MAP(TestMessage,                    PPSMC_MSG_TestMessage,                  1),
  55	MSG_MAP(GetSmuVersion,                  PPSMC_MSG_GetSmuVersion,                1),
  56	MSG_MAP(GetDriverIfVersion,             PPSMC_MSG_GetDriverIfVersion,           1),
  57	MSG_MAP(PowerUpGfx,                     PPSMC_MSG_PowerUpGfx,                   1),
  58	MSG_MAP(AllowGfxOff,                    PPSMC_MSG_EnableGfxOff,                 1),
  59	MSG_MAP(DisallowGfxOff,                 PPSMC_MSG_DisableGfxOff,                1),
  60	MSG_MAP(PowerDownIspByTile,             PPSMC_MSG_PowerDownIspByTile,           1),
  61	MSG_MAP(PowerUpIspByTile,               PPSMC_MSG_PowerUpIspByTile,             1),
  62	MSG_MAP(PowerDownVcn,                   PPSMC_MSG_PowerDownVcn,                 1),
  63	MSG_MAP(PowerUpVcn,                     PPSMC_MSG_PowerUpVcn,                   1),
  64	MSG_MAP(PowerDownSdma,                  PPSMC_MSG_PowerDownSdma,                1),
  65	MSG_MAP(PowerUpSdma,                    PPSMC_MSG_PowerUpSdma,                  1),
  66	MSG_MAP(SetHardMinIspclkByFreq,         PPSMC_MSG_SetHardMinIspclkByFreq,       1),
  67	MSG_MAP(SetHardMinVcn,                  PPSMC_MSG_SetHardMinVcn,                1),
  68	MSG_MAP(SetAllowFclkSwitch,             PPSMC_MSG_SetAllowFclkSwitch,           1),
  69	MSG_MAP(SetMinVideoGfxclkFreq,          PPSMC_MSG_SetMinVideoGfxclkFreq,        1),
  70	MSG_MAP(ActiveProcessNotify,            PPSMC_MSG_ActiveProcessNotify,          1),
  71	MSG_MAP(SetCustomPolicy,                PPSMC_MSG_SetCustomPolicy,              1),
  72	MSG_MAP(SetVideoFps,                    PPSMC_MSG_SetVideoFps,                  1),
  73	MSG_MAP(NumOfDisplays,                  PPSMC_MSG_SetDisplayCount,              1),
  74	MSG_MAP(QueryPowerLimit,                PPSMC_MSG_QueryPowerLimit,              1),
  75	MSG_MAP(SetDriverDramAddrHigh,          PPSMC_MSG_SetDriverDramAddrHigh,        1),
  76	MSG_MAP(SetDriverDramAddrLow,           PPSMC_MSG_SetDriverDramAddrLow,         1),
  77	MSG_MAP(TransferTableSmu2Dram,          PPSMC_MSG_TransferTableSmu2Dram,        1),
  78	MSG_MAP(TransferTableDram2Smu,          PPSMC_MSG_TransferTableDram2Smu,        1),
  79	MSG_MAP(GfxDeviceDriverReset,           PPSMC_MSG_GfxDeviceDriverReset,         1),
  80	MSG_MAP(SetGfxclkOverdriveByFreqVid,    PPSMC_MSG_SetGfxclkOverdriveByFreqVid,  1),
  81	MSG_MAP(SetHardMinDcfclkByFreq,         PPSMC_MSG_SetHardMinDcfclkByFreq,       1),
  82	MSG_MAP(SetHardMinSocclkByFreq,         PPSMC_MSG_SetHardMinSocclkByFreq,       1),
  83	MSG_MAP(ControlIgpuATS,                 PPSMC_MSG_ControlIgpuATS,               1),
  84	MSG_MAP(SetMinVideoFclkFreq,            PPSMC_MSG_SetMinVideoFclkFreq,          1),
  85	MSG_MAP(SetMinDeepSleepDcfclk,          PPSMC_MSG_SetMinDeepSleepDcfclk,        1),
  86	MSG_MAP(ForcePowerDownGfx,              PPSMC_MSG_ForcePowerDownGfx,            1),
  87	MSG_MAP(SetPhyclkVoltageByFreq,         PPSMC_MSG_SetPhyclkVoltageByFreq,       1),
  88	MSG_MAP(SetDppclkVoltageByFreq,         PPSMC_MSG_SetDppclkVoltageByFreq,       1),
  89	MSG_MAP(SetSoftMinVcn,                  PPSMC_MSG_SetSoftMinVcn,                1),
  90	MSG_MAP(EnablePostCode,                 PPSMC_MSG_EnablePostCode,               1),
  91	MSG_MAP(GetGfxclkFrequency,             PPSMC_MSG_GetGfxclkFrequency,           1),
  92	MSG_MAP(GetFclkFrequency,               PPSMC_MSG_GetFclkFrequency,             1),
  93	MSG_MAP(GetMinGfxclkFrequency,          PPSMC_MSG_GetMinGfxclkFrequency,        1),
  94	MSG_MAP(GetMaxGfxclkFrequency,          PPSMC_MSG_GetMaxGfxclkFrequency,        1),
  95	MSG_MAP(SoftReset,                      PPSMC_MSG_SoftReset,                    1),
  96	MSG_MAP(SetGfxCGPG,                     PPSMC_MSG_SetGfxCGPG,                   1),
  97	MSG_MAP(SetSoftMaxGfxClk,               PPSMC_MSG_SetSoftMaxGfxClk,             1),
  98	MSG_MAP(SetHardMinGfxClk,               PPSMC_MSG_SetHardMinGfxClk,             1),
  99	MSG_MAP(SetSoftMaxSocclkByFreq,         PPSMC_MSG_SetSoftMaxSocclkByFreq,       1),
 100	MSG_MAP(SetSoftMaxFclkByFreq,           PPSMC_MSG_SetSoftMaxFclkByFreq,         1),
 101	MSG_MAP(SetSoftMaxVcn,                  PPSMC_MSG_SetSoftMaxVcn,                1),
 102	MSG_MAP(PowerGateMmHub,                 PPSMC_MSG_PowerGateMmHub,               1),
 103	MSG_MAP(UpdatePmeRestore,               PPSMC_MSG_UpdatePmeRestore,             1),
 104	MSG_MAP(GpuChangeState,                 PPSMC_MSG_GpuChangeState,               1),
 105	MSG_MAP(SetPowerLimitPercentage,        PPSMC_MSG_SetPowerLimitPercentage,      1),
 106	MSG_MAP(ForceGfxContentSave,            PPSMC_MSG_ForceGfxContentSave,          1),
 107	MSG_MAP(EnableTmdp48MHzRefclkPwrDown,   PPSMC_MSG_EnableTmdp48MHzRefclkPwrDown, 1),
 108	MSG_MAP(PowerDownJpeg,                  PPSMC_MSG_PowerDownJpeg,                1),
 109	MSG_MAP(PowerUpJpeg,                    PPSMC_MSG_PowerUpJpeg,                  1),
 110	MSG_MAP(PowerGateAtHub,                 PPSMC_MSG_PowerGateAtHub,               1),
 111	MSG_MAP(SetSoftMinJpeg,                 PPSMC_MSG_SetSoftMinJpeg,               1),
 112	MSG_MAP(SetHardMinFclkByFreq,           PPSMC_MSG_SetHardMinFclkByFreq,         1),
 113};
 114
 115static struct cmn2asic_mapping renoir_clk_map[SMU_CLK_COUNT] = {
 116	CLK_MAP(GFXCLK, CLOCK_GFXCLK),
 117	CLK_MAP(SCLK,	CLOCK_GFXCLK),
 118	CLK_MAP(SOCCLK, CLOCK_SOCCLK),
 119	CLK_MAP(UCLK, CLOCK_FCLK),
 120	CLK_MAP(MCLK, CLOCK_FCLK),
 121	CLK_MAP(VCLK, CLOCK_VCLK),
 122	CLK_MAP(DCLK, CLOCK_DCLK),
 123};
 124
 125static struct cmn2asic_mapping renoir_table_map[SMU_TABLE_COUNT] = {
 126	TAB_MAP_VALID(WATERMARKS),
 127	TAB_MAP_INVALID(CUSTOM_DPM),
 128	TAB_MAP_VALID(DPMCLOCKS),
 129	TAB_MAP_VALID(SMU_METRICS),
 130};
 131
 132static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = {
 133	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D,		WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT),
 134	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO,		WORKLOAD_PPLIB_VIDEO_BIT),
 135	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR,			WORKLOAD_PPLIB_VR_BIT),
 136	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE,		WORKLOAD_PPLIB_COMPUTE_BIT),
 137	WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM,		WORKLOAD_PPLIB_CUSTOM_BIT),
 138};
 139
 140static const uint8_t renoir_throttler_map[] = {
 141	[THROTTLER_STATUS_BIT_SPL]		= (SMU_THROTTLER_SPL_BIT),
 142	[THROTTLER_STATUS_BIT_FPPT]		= (SMU_THROTTLER_FPPT_BIT),
 143	[THROTTLER_STATUS_BIT_SPPT]		= (SMU_THROTTLER_SPPT_BIT),
 144	[THROTTLER_STATUS_BIT_SPPT_APU]		= (SMU_THROTTLER_SPPT_APU_BIT),
 145	[THROTTLER_STATUS_BIT_THM_CORE]		= (SMU_THROTTLER_TEMP_CORE_BIT),
 146	[THROTTLER_STATUS_BIT_THM_GFX]		= (SMU_THROTTLER_TEMP_GPU_BIT),
 147	[THROTTLER_STATUS_BIT_THM_SOC]		= (SMU_THROTTLER_TEMP_SOC_BIT),
 148	[THROTTLER_STATUS_BIT_TDC_VDD]		= (SMU_THROTTLER_TDC_VDD_BIT),
 149	[THROTTLER_STATUS_BIT_TDC_SOC]		= (SMU_THROTTLER_TDC_SOC_BIT),
 150	[THROTTLER_STATUS_BIT_PROCHOT_CPU]	= (SMU_THROTTLER_PROCHOT_CPU_BIT),
 151	[THROTTLER_STATUS_BIT_PROCHOT_GFX]	= (SMU_THROTTLER_PROCHOT_GFX_BIT),
 152	[THROTTLER_STATUS_BIT_EDC_CPU]		= (SMU_THROTTLER_EDC_CPU_BIT),
 153	[THROTTLER_STATUS_BIT_EDC_GFX]		= (SMU_THROTTLER_EDC_GFX_BIT),
 154};
 155
 156static int renoir_init_smc_tables(struct smu_context *smu)
 157{
 158	struct smu_table_context *smu_table = &smu->smu_table;
 159	struct smu_table *tables = smu_table->tables;
 160
 161	SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
 162		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 163	SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
 164		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 165	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
 166		PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 167
 168	smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
 169	if (!smu_table->clocks_table)
 170		goto err0_out;
 171
 172	smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
 173	if (!smu_table->metrics_table)
 174		goto err1_out;
 175	smu_table->metrics_time = 0;
 176
 177	smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
 178	if (!smu_table->watermarks_table)
 179		goto err2_out;
 180
 181	smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2);
 182	smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
 183	if (!smu_table->gpu_metrics_table)
 184		goto err3_out;
 185
 186	return 0;
 187
 188err3_out:
 189	kfree(smu_table->watermarks_table);
 190err2_out:
 191	kfree(smu_table->metrics_table);
 192err1_out:
 193	kfree(smu_table->clocks_table);
 194err0_out:
 195	return -ENOMEM;
 196}
 197
 198/*
 199 * This interface just for getting uclk ultimate freq and should't introduce
 200 * other likewise function result in overmuch callback.
 201 */
 202static int renoir_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type,
 203						uint32_t dpm_level, uint32_t *freq)
 204{
 205	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
 206
 207	if (!clk_table || clk_type >= SMU_CLK_COUNT)
 208		return -EINVAL;
 209
 210	switch (clk_type) {
 211	case SMU_SOCCLK:
 212		if (dpm_level >= NUM_SOCCLK_DPM_LEVELS)
 213			return -EINVAL;
 214		*freq = clk_table->SocClocks[dpm_level].Freq;
 215		break;
 216	case SMU_UCLK:
 217	case SMU_MCLK:
 218		if (dpm_level >= NUM_FCLK_DPM_LEVELS)
 219			return -EINVAL;
 220		*freq = clk_table->FClocks[dpm_level].Freq;
 221		break;
 222	case SMU_DCEFCLK:
 223		if (dpm_level >= NUM_DCFCLK_DPM_LEVELS)
 224			return -EINVAL;
 225		*freq = clk_table->DcfClocks[dpm_level].Freq;
 226		break;
 227	case SMU_FCLK:
 228		if (dpm_level >= NUM_FCLK_DPM_LEVELS)
 229			return -EINVAL;
 230		*freq = clk_table->FClocks[dpm_level].Freq;
 231		break;
 232	case SMU_VCLK:
 233		if (dpm_level >= NUM_VCN_DPM_LEVELS)
 234			return -EINVAL;
 235		*freq = clk_table->VClocks[dpm_level].Freq;
 236		break;
 237	case SMU_DCLK:
 238		if (dpm_level >= NUM_VCN_DPM_LEVELS)
 239			return -EINVAL;
 240		*freq = clk_table->DClocks[dpm_level].Freq;
 241		break;
 242
 243	default:
 244		return -EINVAL;
 245	}
 246
 247	return 0;
 248}
 249
 250static int renoir_get_profiling_clk_mask(struct smu_context *smu,
 251					 enum amd_dpm_forced_level level,
 252					 uint32_t *sclk_mask,
 253					 uint32_t *mclk_mask,
 254					 uint32_t *soc_mask)
 255{
 256
 257	if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
 258		if (sclk_mask)
 259			*sclk_mask = 0;
 260	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) {
 261		if (mclk_mask)
 262			/* mclk levels are in reverse order */
 263			*mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1;
 264	} else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) {
 265		if (sclk_mask)
 266			/* The sclk as gfxclk and has three level about max/min/current */
 267			*sclk_mask = 3 - 1;
 268
 269		if (mclk_mask)
 270			/* mclk levels are in reverse order */
 271			*mclk_mask = 0;
 272
 273		if (soc_mask)
 274			*soc_mask = NUM_SOCCLK_DPM_LEVELS - 1;
 275	}
 276
 277	return 0;
 278}
 279
 280static int renoir_get_dpm_ultimate_freq(struct smu_context *smu,
 281					enum smu_clk_type clk_type,
 282					uint32_t *min,
 283					uint32_t *max)
 284{
 285	int ret = 0;
 286	uint32_t mclk_mask, soc_mask;
 287	uint32_t clock_limit;
 288
 289	if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) {
 290		switch (clk_type) {
 291		case SMU_MCLK:
 292		case SMU_UCLK:
 293			clock_limit = smu->smu_table.boot_values.uclk;
 294			break;
 295		case SMU_GFXCLK:
 296		case SMU_SCLK:
 297			clock_limit = smu->smu_table.boot_values.gfxclk;
 298			break;
 299		case SMU_SOCCLK:
 300			clock_limit = smu->smu_table.boot_values.socclk;
 301			break;
 302		default:
 303			clock_limit = 0;
 304			break;
 305		}
 306
 307		/* clock in Mhz unit */
 308		if (min)
 309			*min = clock_limit / 100;
 310		if (max)
 311			*max = clock_limit / 100;
 312
 313		return 0;
 314	}
 315
 316	if (max) {
 317		ret = renoir_get_profiling_clk_mask(smu,
 318						    AMD_DPM_FORCED_LEVEL_PROFILE_PEAK,
 319						    NULL,
 320						    &mclk_mask,
 321						    &soc_mask);
 322		if (ret)
 323			goto failed;
 324
 325		switch (clk_type) {
 326		case SMU_GFXCLK:
 327		case SMU_SCLK:
 328			ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency, max);
 329			if (ret) {
 330				dev_err(smu->adev->dev, "Attempt to get max GX frequency from SMC Failed !\n");
 331				goto failed;
 332			}
 333			break;
 334		case SMU_UCLK:
 335		case SMU_FCLK:
 336		case SMU_MCLK:
 337			ret = renoir_get_dpm_clk_limited(smu, clk_type, mclk_mask, max);
 338			if (ret)
 339				goto failed;
 340			break;
 341		case SMU_SOCCLK:
 342			ret = renoir_get_dpm_clk_limited(smu, clk_type, soc_mask, max);
 343			if (ret)
 344				goto failed;
 345			break;
 346		default:
 347			ret = -EINVAL;
 348			goto failed;
 349		}
 350	}
 351
 352	if (min) {
 353		switch (clk_type) {
 354		case SMU_GFXCLK:
 355		case SMU_SCLK:
 356			ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency, min);
 357			if (ret) {
 358				dev_err(smu->adev->dev, "Attempt to get min GX frequency from SMC Failed !\n");
 359				goto failed;
 360			}
 361			break;
 362		case SMU_UCLK:
 363		case SMU_FCLK:
 364		case SMU_MCLK:
 365			ret = renoir_get_dpm_clk_limited(smu, clk_type, NUM_MEMCLK_DPM_LEVELS - 1, min);
 366			if (ret)
 367				goto failed;
 368			break;
 369		case SMU_SOCCLK:
 370			ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min);
 371			if (ret)
 372				goto failed;
 373			break;
 374		default:
 375			ret = -EINVAL;
 376			goto failed;
 377		}
 378	}
 379failed:
 380	return ret;
 381}
 382
 383static int renoir_od_edit_dpm_table(struct smu_context *smu,
 384							enum PP_OD_DPM_TABLE_COMMAND type,
 385							long input[], uint32_t size)
 386{
 387	int ret = 0;
 388	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
 389
 390	if (!(smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL)) {
 391		dev_warn(smu->adev->dev,
 392			"pp_od_clk_voltage is not accessible if power_dpm_force_performance_level is not in manual mode!\n");
 393		return -EINVAL;
 394	}
 395
 396	switch (type) {
 397	case PP_OD_EDIT_SCLK_VDDC_TABLE:
 398		if (size != 2) {
 399			dev_err(smu->adev->dev, "Input parameter number not correct\n");
 400			return -EINVAL;
 401		}
 402
 403		if (input[0] == 0) {
 404			if (input[1] < smu->gfx_default_hard_min_freq) {
 405				dev_warn(smu->adev->dev,
 406					"Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
 407					input[1], smu->gfx_default_hard_min_freq);
 408				return -EINVAL;
 409			}
 410			smu->gfx_actual_hard_min_freq = input[1];
 411		} else if (input[0] == 1) {
 412			if (input[1] > smu->gfx_default_soft_max_freq) {
 413				dev_warn(smu->adev->dev,
 414					"Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
 415					input[1], smu->gfx_default_soft_max_freq);
 416				return -EINVAL;
 417			}
 418			smu->gfx_actual_soft_max_freq = input[1];
 419		} else {
 420			return -EINVAL;
 421		}
 422		break;
 423	case PP_OD_RESTORE_DEFAULT_TABLE:
 424		if (size != 0) {
 425			dev_err(smu->adev->dev, "Input parameter number not correct\n");
 426			return -EINVAL;
 427		}
 428		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
 429		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
 430		break;
 431	case PP_OD_COMMIT_DPM_TABLE:
 432		if (size != 0) {
 433			dev_err(smu->adev->dev, "Input parameter number not correct\n");
 434			return -EINVAL;
 435		} else {
 436			if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
 437				dev_err(smu->adev->dev,
 438					"The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
 439					smu->gfx_actual_hard_min_freq,
 440					smu->gfx_actual_soft_max_freq);
 441				return -EINVAL;
 442			}
 443
 444			ret = smu_cmn_send_smc_msg_with_param(smu,
 445								SMU_MSG_SetHardMinGfxClk,
 446								smu->gfx_actual_hard_min_freq,
 447								NULL);
 448			if (ret) {
 449				dev_err(smu->adev->dev, "Set hard min sclk failed!");
 450				return ret;
 451			}
 452
 453			ret = smu_cmn_send_smc_msg_with_param(smu,
 454								SMU_MSG_SetSoftMaxGfxClk,
 455								smu->gfx_actual_soft_max_freq,
 456								NULL);
 457			if (ret) {
 458				dev_err(smu->adev->dev, "Set soft max sclk failed!");
 459				return ret;
 460			}
 461		}
 462		break;
 463	default:
 464		return -ENOSYS;
 465	}
 466
 467	return ret;
 468}
 469
 470static int renoir_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
 471{
 472	uint32_t min = 0, max = 0;
 473	int ret = 0;
 474
 475	ret = smu_cmn_send_smc_msg_with_param(smu,
 476								SMU_MSG_GetMinGfxclkFrequency,
 477								0, &min);
 478	if (ret)
 479		return ret;
 480	ret = smu_cmn_send_smc_msg_with_param(smu,
 481								SMU_MSG_GetMaxGfxclkFrequency,
 482								0, &max);
 483	if (ret)
 484		return ret;
 485
 486	smu->gfx_default_hard_min_freq = min;
 487	smu->gfx_default_soft_max_freq = max;
 488	smu->gfx_actual_hard_min_freq = 0;
 489	smu->gfx_actual_soft_max_freq = 0;
 490
 491	return 0;
 492}
 493
 494static int renoir_print_clk_levels(struct smu_context *smu,
 495			enum smu_clk_type clk_type, char *buf)
 496{
 497	int i, idx, size = 0, ret = 0, start_offset = 0;
 498	uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0;
 499	SmuMetrics_t metrics;
 500	bool cur_value_match_level = false;
 501
 502	memset(&metrics, 0, sizeof(metrics));
 503
 504	ret = smu_cmn_get_metrics_table(smu, &metrics, false);
 505	if (ret)
 506		return ret;
 507
 508	smu_cmn_get_sysfs_buf(&buf, &size);
 509	start_offset = size;
 510
 511	switch (clk_type) {
 512	case SMU_OD_RANGE:
 513		ret = smu_cmn_send_smc_msg_with_param(smu,
 514					SMU_MSG_GetMinGfxclkFrequency,
 515					0, &min);
 516		if (ret)
 517			return ret;
 518		ret = smu_cmn_send_smc_msg_with_param(smu,
 519					SMU_MSG_GetMaxGfxclkFrequency,
 520					0, &max);
 521		if (ret)
 522			return ret;
 523		size += sysfs_emit_at(buf, size, "OD_RANGE\nSCLK: %10uMhz %10uMhz\n", min, max);
 524		break;
 525	case SMU_OD_SCLK:
 526		min = (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq;
 527		max = (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq;
 528		size += sysfs_emit_at(buf, size, "OD_SCLK\n");
 529		size += sysfs_emit_at(buf, size, "0:%10uMhz\n", min);
 530		size += sysfs_emit_at(buf, size, "1:%10uMhz\n", max);
 531		break;
 532	case SMU_GFXCLK:
 533	case SMU_SCLK:
 534		/* retirve table returned paramters unit is MHz */
 535		cur_value = metrics.ClockFrequency[CLOCK_GFXCLK];
 536		ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min, &max);
 537		if (!ret) {
 538			/* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */
 539			if (cur_value  == max)
 540				i = 2;
 541			else if (cur_value == min)
 542				i = 0;
 543			else
 544				i = 1;
 545
 546			size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", min,
 547					i == 0 ? "*" : "");
 548			size += sysfs_emit_at(buf, size, "1: %uMhz %s\n",
 549					i == 1 ? cur_value : RENOIR_UMD_PSTATE_GFXCLK,
 550					i == 1 ? "*" : "");
 551			size += sysfs_emit_at(buf, size, "2: %uMhz %s\n", max,
 552					i == 2 ? "*" : "");
 553		}
 554		return size - start_offset;
 555	case SMU_SOCCLK:
 556		count = NUM_SOCCLK_DPM_LEVELS;
 557		cur_value = metrics.ClockFrequency[CLOCK_SOCCLK];
 558		break;
 559	case SMU_MCLK:
 560		count = NUM_MEMCLK_DPM_LEVELS;
 561		cur_value = metrics.ClockFrequency[CLOCK_FCLK];
 562		break;
 563	case SMU_DCEFCLK:
 564		count = NUM_DCFCLK_DPM_LEVELS;
 565		cur_value = metrics.ClockFrequency[CLOCK_DCFCLK];
 566		break;
 567	case SMU_FCLK:
 568		count = NUM_FCLK_DPM_LEVELS;
 569		cur_value = metrics.ClockFrequency[CLOCK_FCLK];
 570		break;
 571	case SMU_VCLK:
 572		count = NUM_VCN_DPM_LEVELS;
 573		cur_value = metrics.ClockFrequency[CLOCK_VCLK];
 574		break;
 575	case SMU_DCLK:
 576		count = NUM_VCN_DPM_LEVELS;
 577		cur_value = metrics.ClockFrequency[CLOCK_DCLK];
 578		break;
 579	default:
 580		break;
 581	}
 582
 583	switch (clk_type) {
 584	case SMU_SOCCLK:
 585	case SMU_MCLK:
 586	case SMU_DCEFCLK:
 587	case SMU_FCLK:
 588	case SMU_VCLK:
 589	case SMU_DCLK:
 590		for (i = 0; i < count; i++) {
 591			idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i;
 592			ret = renoir_get_dpm_clk_limited(smu, clk_type, idx, &value);
 593			if (ret)
 594				return ret;
 595			if (!value)
 596				continue;
 597			size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i, value,
 598					cur_value == value ? "*" : "");
 599			if (cur_value == value)
 600				cur_value_match_level = true;
 601		}
 602
 603		if (!cur_value_match_level)
 604			size += sysfs_emit_at(buf, size, "   %uMhz *\n", cur_value);
 605
 606		break;
 607	default:
 608		break;
 609	}
 610
 611	return size - start_offset;
 612}
 613
 614static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context *smu)
 615{
 616	enum amd_pm_state_type pm_type;
 617	struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
 618
 619	if (!smu_dpm_ctx->dpm_context ||
 620	    !smu_dpm_ctx->dpm_current_power_state)
 621		return -EINVAL;
 622
 623	switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) {
 624	case SMU_STATE_UI_LABEL_BATTERY:
 625		pm_type = POWER_STATE_TYPE_BATTERY;
 626		break;
 627	case SMU_STATE_UI_LABEL_BALLANCED:
 628		pm_type = POWER_STATE_TYPE_BALANCED;
 629		break;
 630	case SMU_STATE_UI_LABEL_PERFORMANCE:
 631		pm_type = POWER_STATE_TYPE_PERFORMANCE;
 632		break;
 633	default:
 634		if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT)
 635			pm_type = POWER_STATE_TYPE_INTERNAL_BOOT;
 636		else
 637			pm_type = POWER_STATE_TYPE_DEFAULT;
 638		break;
 639	}
 640
 641	return pm_type;
 642}
 643
 644static int renoir_dpm_set_vcn_enable(struct smu_context *smu,
 645				      bool enable,
 646				      int inst)
 647{
 648	int ret = 0;
 649
 650	if (enable) {
 651		/* vcn dpm on is a prerequisite for vcn power gate messages */
 652		if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
 653			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL);
 654			if (ret)
 655				return ret;
 656		}
 657	} else {
 658		if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
 659			ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL);
 660			if (ret)
 661				return ret;
 662		}
 663	}
 664
 665	return ret;
 666}
 667
 668static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
 669{
 670	int ret = 0;
 671
 672	if (enable) {
 673		if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
 674			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL);
 675			if (ret)
 676				return ret;
 677		}
 678	} else {
 679		if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
 680			ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL);
 681			if (ret)
 682				return ret;
 683		}
 684	}
 685
 686	return ret;
 687}
 688
 689static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest)
 690{
 691	int ret = 0, i = 0;
 692	uint32_t min_freq, max_freq, force_freq;
 693	enum smu_clk_type clk_type;
 694
 695	enum smu_clk_type clks[] = {
 696		SMU_GFXCLK,
 697		SMU_MCLK,
 698		SMU_SOCCLK,
 699	};
 700
 701	for (i = 0; i < ARRAY_SIZE(clks); i++) {
 702		clk_type = clks[i];
 703		ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
 704		if (ret)
 705			return ret;
 706
 707		force_freq = highest ? max_freq : min_freq;
 708		ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq, false);
 709		if (ret)
 710			return ret;
 711	}
 712
 713	return ret;
 714}
 715
 716static int renoir_unforce_dpm_levels(struct smu_context *smu) {
 717
 718	int ret = 0, i = 0;
 719	uint32_t min_freq, max_freq;
 720	enum smu_clk_type clk_type;
 721
 722	struct clk_feature_map {
 723		enum smu_clk_type clk_type;
 724		uint32_t	feature;
 725	} clk_feature_map[] = {
 726		{SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT},
 727		{SMU_MCLK,   SMU_FEATURE_DPM_UCLK_BIT},
 728		{SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT},
 729	};
 730
 731	for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) {
 732		if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature))
 733		    continue;
 734
 735		clk_type = clk_feature_map[i].clk_type;
 736
 737		ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq);
 738		if (ret)
 739			return ret;
 740
 741		ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
 742		if (ret)
 743			return ret;
 744	}
 745
 746	return ret;
 747}
 748
 749/*
 750 * This interface get dpm clock table for dc
 751 */
 752static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
 753{
 754	DpmClocks_t *table = smu->smu_table.clocks_table;
 755	int i;
 756
 757	if (!clock_table || !table)
 758		return -EINVAL;
 759
 760	for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) {
 761		clock_table->DcfClocks[i].Freq = table->DcfClocks[i].Freq;
 762		clock_table->DcfClocks[i].Vol = table->DcfClocks[i].Vol;
 763	}
 764
 765	for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
 766		clock_table->SocClocks[i].Freq = table->SocClocks[i].Freq;
 767		clock_table->SocClocks[i].Vol = table->SocClocks[i].Vol;
 768	}
 769
 770	for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
 771		clock_table->FClocks[i].Freq = table->FClocks[i].Freq;
 772		clock_table->FClocks[i].Vol = table->FClocks[i].Vol;
 773	}
 774
 775	for (i = 0; i<  NUM_MEMCLK_DPM_LEVELS; i++) {
 776		clock_table->MemClocks[i].Freq = table->MemClocks[i].Freq;
 777		clock_table->MemClocks[i].Vol = table->MemClocks[i].Vol;
 778	}
 779
 780	for (i = 0; i < NUM_VCN_DPM_LEVELS; i++) {
 781		clock_table->VClocks[i].Freq = table->VClocks[i].Freq;
 782		clock_table->VClocks[i].Vol = table->VClocks[i].Vol;
 783	}
 784
 785	for (i = 0; i < NUM_VCN_DPM_LEVELS; i++) {
 786		clock_table->DClocks[i].Freq = table->DClocks[i].Freq;
 787		clock_table->DClocks[i].Vol = table->DClocks[i].Vol;
 788	}
 789
 790	return 0;
 791}
 792
 793static int renoir_force_clk_levels(struct smu_context *smu,
 794				   enum smu_clk_type clk_type, uint32_t mask)
 795{
 796
 797	int ret = 0 ;
 798	uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0;
 799
 800	soft_min_level = mask ? (ffs(mask) - 1) : 0;
 801	soft_max_level = mask ? (fls(mask) - 1) : 0;
 802
 803	switch (clk_type) {
 804	case SMU_GFXCLK:
 805	case SMU_SCLK:
 806		if (soft_min_level > 2 || soft_max_level > 2) {
 807			dev_info(smu->adev->dev, "Currently sclk only support 3 levels on APU\n");
 808			return -EINVAL;
 809		}
 810
 811		ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min_freq, &max_freq);
 812		if (ret)
 813			return ret;
 814		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
 815					soft_max_level == 0 ? min_freq :
 816					soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq,
 817					NULL);
 818		if (ret)
 819			return ret;
 820		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
 821					soft_min_level == 2 ? max_freq :
 822					soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq,
 823					NULL);
 824		if (ret)
 825			return ret;
 826		break;
 827	case SMU_SOCCLK:
 828		ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq);
 829		if (ret)
 830			return ret;
 831		ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq);
 832		if (ret)
 833			return ret;
 834		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq, NULL);
 835		if (ret)
 836			return ret;
 837		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq, NULL);
 838		if (ret)
 839			return ret;
 840		break;
 841	case SMU_MCLK:
 842	case SMU_FCLK:
 843		ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq);
 844		if (ret)
 845			return ret;
 846		ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq);
 847		if (ret)
 848			return ret;
 849		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq, NULL);
 850		if (ret)
 851			return ret;
 852		ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq, NULL);
 853		if (ret)
 854			return ret;
 855		break;
 856	default:
 857		break;
 858	}
 859
 860	return ret;
 861}
 862
 863static int renoir_set_power_profile_mode(struct smu_context *smu,
 864					 u32 workload_mask,
 865					 long *custom_params,
 866					 u32 custom_params_max_idx)
 867{
 868	int ret;
 869	u32 backend_workload_mask = 0;
 870
 871	smu_cmn_get_backend_workload_mask(smu, workload_mask,
 872					  &backend_workload_mask);
 873
 874	ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
 875					      backend_workload_mask,
 876					      NULL);
 877	if (ret) {
 878		dev_err_once(smu->adev->dev, "Failed to set workload mask 0x08%x\n",
 879			     workload_mask);
 880		return ret;
 881	}
 882
 883	return ret;
 884}
 885
 886static int renoir_set_peak_clock_by_device(struct smu_context *smu)
 887{
 888	int ret = 0;
 889	uint32_t sclk_freq = 0, uclk_freq = 0;
 890
 891	ret = renoir_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_freq);
 892	if (ret)
 893		return ret;
 894
 895	ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false);
 896	if (ret)
 897		return ret;
 898
 899	ret = renoir_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &uclk_freq);
 900	if (ret)
 901		return ret;
 902
 903	ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false);
 904	if (ret)
 905		return ret;
 906
 907	return ret;
 908}
 909
 910static int renior_set_dpm_profile_freq(struct smu_context *smu,
 911					enum amd_dpm_forced_level level,
 912					enum smu_clk_type clk_type)
 913{
 914	int ret = 0;
 915	uint32_t sclk = 0, socclk = 0, fclk = 0;
 916
 917	switch (clk_type) {
 918	case SMU_GFXCLK:
 919	case SMU_SCLK:
 920		sclk = RENOIR_UMD_PSTATE_GFXCLK;
 921		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
 922			renoir_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk);
 923		else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK)
 924			renoir_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk, NULL);
 925		break;
 926	case SMU_SOCCLK:
 927		socclk = RENOIR_UMD_PSTATE_SOCCLK;
 928		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
 929			renoir_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk);
 930		break;
 931	case SMU_FCLK:
 932	case SMU_MCLK:
 933		fclk = RENOIR_UMD_PSTATE_FCLK;
 934		if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
 935			renoir_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk);
 936		else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK)
 937			renoir_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk, NULL);
 938		break;
 939	default:
 940		ret = -EINVAL;
 941		break;
 942	}
 943
 944	if (sclk)
 945		ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk, sclk, false);
 946
 947	if (socclk)
 948		ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk, socclk, false);
 949
 950	if (fclk)
 951		ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_FCLK, fclk, fclk, false);
 952
 953	return ret;
 954}
 955
 956static int renoir_set_performance_level(struct smu_context *smu,
 957					enum amd_dpm_forced_level level)
 958{
 959	int ret = 0;
 960
 961	switch (level) {
 962	case AMD_DPM_FORCED_LEVEL_HIGH:
 963		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
 964		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
 965
 966		ret = renoir_force_dpm_limit_value(smu, true);
 967		break;
 968	case AMD_DPM_FORCED_LEVEL_LOW:
 969		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
 970		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
 971
 972		ret = renoir_force_dpm_limit_value(smu, false);
 973		break;
 974	case AMD_DPM_FORCED_LEVEL_AUTO:
 975		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
 976		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
 977
 978		ret = renoir_unforce_dpm_levels(smu);
 979		break;
 980	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
 981		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
 982		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
 983
 984		ret = smu_cmn_send_smc_msg_with_param(smu,
 985						      SMU_MSG_SetHardMinGfxClk,
 986						      RENOIR_UMD_PSTATE_GFXCLK,
 987						      NULL);
 988		if (ret)
 989			return ret;
 990		ret = smu_cmn_send_smc_msg_with_param(smu,
 991						      SMU_MSG_SetHardMinFclkByFreq,
 992						      RENOIR_UMD_PSTATE_FCLK,
 993						      NULL);
 994		if (ret)
 995			return ret;
 996		ret = smu_cmn_send_smc_msg_with_param(smu,
 997						      SMU_MSG_SetHardMinSocclkByFreq,
 998						      RENOIR_UMD_PSTATE_SOCCLK,
 999						      NULL);
1000		if (ret)
1001			return ret;
1002		ret = smu_cmn_send_smc_msg_with_param(smu,
1003						      SMU_MSG_SetHardMinVcn,
1004						      RENOIR_UMD_PSTATE_VCNCLK,
1005						      NULL);
1006		if (ret)
1007			return ret;
1008
1009		ret = smu_cmn_send_smc_msg_with_param(smu,
1010						      SMU_MSG_SetSoftMaxGfxClk,
1011						      RENOIR_UMD_PSTATE_GFXCLK,
1012						      NULL);
1013		if (ret)
1014			return ret;
1015		ret = smu_cmn_send_smc_msg_with_param(smu,
1016						      SMU_MSG_SetSoftMaxFclkByFreq,
1017						      RENOIR_UMD_PSTATE_FCLK,
1018						      NULL);
1019		if (ret)
1020			return ret;
1021		ret = smu_cmn_send_smc_msg_with_param(smu,
1022						      SMU_MSG_SetSoftMaxSocclkByFreq,
1023						      RENOIR_UMD_PSTATE_SOCCLK,
1024						      NULL);
1025		if (ret)
1026			return ret;
1027		ret = smu_cmn_send_smc_msg_with_param(smu,
1028						      SMU_MSG_SetSoftMaxVcn,
1029						      RENOIR_UMD_PSTATE_VCNCLK,
1030						      NULL);
1031		if (ret)
1032			return ret;
1033		break;
1034	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1035	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
1036		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1037		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1038
1039		renior_set_dpm_profile_freq(smu, level, SMU_SCLK);
1040		renior_set_dpm_profile_freq(smu, level, SMU_MCLK);
1041		renior_set_dpm_profile_freq(smu, level, SMU_SOCCLK);
1042		break;
1043	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1044		smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
1045		smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
1046
1047		ret = renoir_set_peak_clock_by_device(smu);
1048		break;
1049	case AMD_DPM_FORCED_LEVEL_MANUAL:
1050	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1051	default:
1052		break;
1053	}
1054	return ret;
1055}
1056
1057/* save watermark settings into pplib smu structure,
1058 * also pass data to smu controller
1059 */
1060static int renoir_set_watermarks_table(
1061		struct smu_context *smu,
1062		struct pp_smu_wm_range_sets *clock_ranges)
1063{
1064	Watermarks_t *table = smu->smu_table.watermarks_table;
1065	int ret = 0;
1066	int i;
1067
1068	if (clock_ranges) {
1069		if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
1070		    clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
1071			return -EINVAL;
1072
1073		/* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/
1074		for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
1075			table->WatermarkRow[WM_DCFCLK][i].MinClock =
1076				clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
1077			table->WatermarkRow[WM_DCFCLK][i].MaxClock =
1078				clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
1079			table->WatermarkRow[WM_DCFCLK][i].MinMclk =
1080				clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
1081			table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
1082				clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
1083
1084			table->WatermarkRow[WM_DCFCLK][i].WmSetting =
1085				clock_ranges->reader_wm_sets[i].wm_inst;
1086			table->WatermarkRow[WM_DCFCLK][i].WmType =
1087				clock_ranges->reader_wm_sets[i].wm_type;
1088		}
1089
1090		for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
1091			table->WatermarkRow[WM_SOCCLK][i].MinClock =
1092				clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
1093			table->WatermarkRow[WM_SOCCLK][i].MaxClock =
1094				clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
1095			table->WatermarkRow[WM_SOCCLK][i].MinMclk =
1096				clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
1097			table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
1098				clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
1099
1100			table->WatermarkRow[WM_SOCCLK][i].WmSetting =
1101				clock_ranges->writer_wm_sets[i].wm_inst;
1102			table->WatermarkRow[WM_SOCCLK][i].WmType =
1103				clock_ranges->writer_wm_sets[i].wm_type;
1104		}
1105
1106		smu->watermarks_bitmap |= WATERMARKS_EXIST;
1107	}
1108
1109	/* pass data to smu controller */
1110	if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
1111	     !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
1112		ret = smu_cmn_write_watermarks_table(smu);
1113		if (ret) {
1114			dev_err(smu->adev->dev, "Failed to update WMTABLE!");
1115			return ret;
1116		}
1117		smu->watermarks_bitmap |= WATERMARKS_LOADED;
1118	}
1119
1120	return 0;
1121}
1122
1123static int renoir_get_power_profile_mode(struct smu_context *smu,
1124					   char *buf)
1125{
1126	uint32_t i, size = 0;
1127	int16_t workload_type = 0;
1128
1129	if (!buf)
1130		return -EINVAL;
1131
1132	for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
1133		/*
1134		 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
1135		 * Not all profile modes are supported on arcturus.
1136		 */
1137		workload_type = smu_cmn_to_asic_specific_index(smu,
1138							       CMN2ASIC_MAPPING_WORKLOAD,
1139							       i);
1140		if (workload_type < 0)
1141			continue;
1142
1143		size += sysfs_emit_at(buf, size, "%2d %14s%s\n",
1144			i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " ");
1145	}
1146
1147	return size;
1148}
1149
1150static void renoir_get_ss_power_percent(SmuMetrics_t *metrics,
1151					uint32_t *apu_percent, uint32_t *dgpu_percent)
1152{
1153	uint32_t apu_boost = 0;
1154	uint32_t dgpu_boost = 0;
1155	uint16_t apu_limit = 0;
1156	uint16_t dgpu_limit = 0;
1157	uint16_t apu_power = 0;
1158	uint16_t dgpu_power = 0;
1159
1160	apu_power = metrics->ApuPower;
1161	apu_limit = metrics->StapmOriginalLimit;
1162	if (apu_power > apu_limit && apu_limit != 0)
1163		apu_boost =  ((apu_power - apu_limit) * 100) / apu_limit;
1164	apu_boost = (apu_boost > 100) ? 100 : apu_boost;
1165
1166	dgpu_power = metrics->dGpuPower;
1167	if (metrics->StapmCurrentLimit > metrics->StapmOriginalLimit)
1168		dgpu_limit = metrics->StapmCurrentLimit - metrics->StapmOriginalLimit;
1169	if (dgpu_power > dgpu_limit && dgpu_limit != 0)
1170		dgpu_boost = ((dgpu_power - dgpu_limit) * 100) / dgpu_limit;
1171	dgpu_boost = (dgpu_boost > 100) ? 100 : dgpu_boost;
1172
1173	if (dgpu_boost >= apu_boost)
1174		apu_boost = 0;
1175	else
1176		dgpu_boost = 0;
1177
1178	*apu_percent = apu_boost;
1179	*dgpu_percent = dgpu_boost;
1180}
1181
1182
1183static int renoir_get_smu_metrics_data(struct smu_context *smu,
1184				       MetricsMember_t member,
1185				       uint32_t *value)
1186{
1187	struct smu_table_context *smu_table = &smu->smu_table;
1188
1189	SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
1190	int ret = 0;
1191	uint32_t apu_percent = 0;
1192	uint32_t dgpu_percent = 0;
1193	struct amdgpu_device *adev = smu->adev;
1194
1195
1196	ret = smu_cmn_get_metrics_table(smu,
1197					NULL,
1198					false);
1199	if (ret)
1200		return ret;
1201
1202	switch (member) {
1203	case METRICS_AVERAGE_GFXCLK:
1204		*value = metrics->ClockFrequency[CLOCK_GFXCLK];
1205		break;
1206	case METRICS_AVERAGE_SOCCLK:
1207		*value = metrics->ClockFrequency[CLOCK_SOCCLK];
1208		break;
1209	case METRICS_AVERAGE_UCLK:
1210		*value = metrics->ClockFrequency[CLOCK_FCLK];
1211		break;
1212	case METRICS_AVERAGE_GFXACTIVITY:
1213		*value = metrics->AverageGfxActivity / 100;
1214		break;
1215	case METRICS_AVERAGE_VCNACTIVITY:
1216		*value = metrics->AverageUvdActivity / 100;
1217		break;
1218	case METRICS_CURR_SOCKETPOWER:
1219		if (((amdgpu_ip_version(adev, MP1_HWIP, 0) ==
1220		      IP_VERSION(12, 0, 1)) &&
1221		     (adev->pm.fw_version >= 0x40000f)) ||
1222		    ((amdgpu_ip_version(adev, MP1_HWIP, 0) ==
1223		      IP_VERSION(12, 0, 0)) &&
1224		     (adev->pm.fw_version >= 0x373200)))
1225			*value = metrics->CurrentSocketPower << 8;
1226		else
1227			*value = (metrics->CurrentSocketPower << 8) / 1000;
1228		break;
1229	case METRICS_TEMPERATURE_EDGE:
1230		*value = (metrics->GfxTemperature / 100) *
1231			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1232		break;
1233	case METRICS_TEMPERATURE_HOTSPOT:
1234		*value = (metrics->SocTemperature / 100) *
1235			SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
1236		break;
1237	case METRICS_THROTTLER_STATUS:
1238		*value = metrics->ThrottlerStatus;
1239		break;
1240	case METRICS_VOLTAGE_VDDGFX:
1241		*value = metrics->Voltage[0];
1242		break;
1243	case METRICS_VOLTAGE_VDDSOC:
1244		*value = metrics->Voltage[1];
1245		break;
1246	case METRICS_SS_APU_SHARE:
1247		/* return the percentage of APU power boost
1248		 * with respect to APU's power limit.
1249		 */
1250		renoir_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
1251		*value = apu_percent;
1252		break;
1253	case METRICS_SS_DGPU_SHARE:
1254		/* return the percentage of dGPU power boost
1255		 * with respect to dGPU's power limit.
1256		 */
1257		renoir_get_ss_power_percent(metrics, &apu_percent, &dgpu_percent);
1258		*value = dgpu_percent;
1259		break;
1260	default:
1261		*value = UINT_MAX;
1262		break;
1263	}
1264
1265	return ret;
1266}
1267
1268static int renoir_read_sensor(struct smu_context *smu,
1269				 enum amd_pp_sensors sensor,
1270				 void *data, uint32_t *size)
1271{
1272	int ret = 0;
1273
1274	if (!data || !size)
1275		return -EINVAL;
1276
1277	switch (sensor) {
1278	case AMDGPU_PP_SENSOR_GPU_LOAD:
1279		ret = renoir_get_smu_metrics_data(smu,
1280						  METRICS_AVERAGE_GFXACTIVITY,
1281						  (uint32_t *)data);
1282		*size = 4;
1283		break;
1284	case AMDGPU_PP_SENSOR_VCN_LOAD:
1285		ret = renoir_get_smu_metrics_data(smu,
1286						  METRICS_AVERAGE_VCNACTIVITY,
1287						  (uint32_t *)data);
1288		*size = 4;
1289		break;
1290	case AMDGPU_PP_SENSOR_EDGE_TEMP:
1291		ret = renoir_get_smu_metrics_data(smu,
1292						  METRICS_TEMPERATURE_EDGE,
1293						  (uint32_t *)data);
1294		*size = 4;
1295		break;
1296	case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
1297		ret = renoir_get_smu_metrics_data(smu,
1298						  METRICS_TEMPERATURE_HOTSPOT,
1299						  (uint32_t *)data);
1300		*size = 4;
1301		break;
1302	case AMDGPU_PP_SENSOR_GFX_MCLK:
1303		ret = renoir_get_smu_metrics_data(smu,
1304						  METRICS_AVERAGE_UCLK,
1305						  (uint32_t *)data);
1306		*(uint32_t *)data *= 100;
1307		*size = 4;
1308		break;
1309	case AMDGPU_PP_SENSOR_GFX_SCLK:
1310		ret = renoir_get_smu_metrics_data(smu,
1311						  METRICS_AVERAGE_GFXCLK,
1312						  (uint32_t *)data);
1313		*(uint32_t *)data *= 100;
1314		*size = 4;
1315		break;
1316	case AMDGPU_PP_SENSOR_VDDGFX:
1317		ret = renoir_get_smu_metrics_data(smu,
1318						  METRICS_VOLTAGE_VDDGFX,
1319						  (uint32_t *)data);
1320		*size = 4;
1321		break;
1322	case AMDGPU_PP_SENSOR_VDDNB:
1323		ret = renoir_get_smu_metrics_data(smu,
1324						  METRICS_VOLTAGE_VDDSOC,
1325						  (uint32_t *)data);
1326		*size = 4;
1327		break;
1328	case AMDGPU_PP_SENSOR_GPU_INPUT_POWER:
1329		ret = renoir_get_smu_metrics_data(smu,
1330						  METRICS_CURR_SOCKETPOWER,
1331						  (uint32_t *)data);
1332		*size = 4;
1333		break;
1334	case AMDGPU_PP_SENSOR_SS_APU_SHARE:
1335		ret = renoir_get_smu_metrics_data(smu,
1336						  METRICS_SS_APU_SHARE,
1337						  (uint32_t *)data);
1338		*size = 4;
1339		break;
1340	case AMDGPU_PP_SENSOR_SS_DGPU_SHARE:
1341		ret = renoir_get_smu_metrics_data(smu,
1342						  METRICS_SS_DGPU_SHARE,
1343						  (uint32_t *)data);
1344		*size = 4;
1345		break;
1346	case AMDGPU_PP_SENSOR_GPU_AVG_POWER:
1347	default:
1348		ret = -EOPNOTSUPP;
1349		break;
1350	}
1351
1352	return ret;
1353}
1354
1355static bool renoir_is_dpm_running(struct smu_context *smu)
1356{
1357	struct amdgpu_device *adev = smu->adev;
1358
1359	/*
1360	 * Until now, the pmfw hasn't exported the interface of SMU
1361	 * feature mask to APU SKU so just force on all the feature
1362	 * at early initial stage.
1363	 */
1364	if (adev->in_suspend)
1365		return false;
1366	else
1367		return true;
1368
1369}
1370
1371static ssize_t renoir_get_gpu_metrics(struct smu_context *smu,
1372				      void **table)
1373{
1374	struct smu_table_context *smu_table = &smu->smu_table;
1375	struct gpu_metrics_v2_2 *gpu_metrics =
1376		(struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table;
1377	SmuMetrics_t metrics;
1378	int ret = 0;
1379
1380	ret = smu_cmn_get_metrics_table(smu, &metrics, true);
1381	if (ret)
1382		return ret;
1383
1384	smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2);
1385
1386	gpu_metrics->temperature_gfx = metrics.GfxTemperature;
1387	gpu_metrics->temperature_soc = metrics.SocTemperature;
1388	memcpy(&gpu_metrics->temperature_core[0],
1389		&metrics.CoreTemperature[0],
1390		sizeof(uint16_t) * 8);
1391	gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
1392	gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1];
1393
1394	gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
1395	gpu_metrics->average_mm_activity = metrics.AverageUvdActivity;
1396
1397	gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
1398	gpu_metrics->average_cpu_power = metrics.Power[0];
1399	gpu_metrics->average_soc_power = metrics.Power[1];
1400	memcpy(&gpu_metrics->average_core_power[0],
1401		&metrics.CorePower[0],
1402		sizeof(uint16_t) * 8);
1403
1404	gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency;
1405	gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency;
1406	gpu_metrics->average_fclk_frequency = metrics.AverageFclkFrequency;
1407	gpu_metrics->average_vclk_frequency = metrics.AverageVclkFrequency;
1408
1409	gpu_metrics->current_gfxclk = metrics.ClockFrequency[CLOCK_GFXCLK];
1410	gpu_metrics->current_socclk = metrics.ClockFrequency[CLOCK_SOCCLK];
1411	gpu_metrics->current_uclk = metrics.ClockFrequency[CLOCK_UMCCLK];
1412	gpu_metrics->current_fclk = metrics.ClockFrequency[CLOCK_FCLK];
1413	gpu_metrics->current_vclk = metrics.ClockFrequency[CLOCK_VCLK];
1414	gpu_metrics->current_dclk = metrics.ClockFrequency[CLOCK_DCLK];
1415	memcpy(&gpu_metrics->current_coreclk[0],
1416		&metrics.CoreFrequency[0],
1417		sizeof(uint16_t) * 8);
1418	gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
1419	gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1];
1420
1421	gpu_metrics->throttle_status = metrics.ThrottlerStatus;
1422	gpu_metrics->indep_throttle_status =
1423		smu_cmn_get_indep_throttler_status(metrics.ThrottlerStatus,
1424						   renoir_throttler_map);
1425
1426	gpu_metrics->fan_pwm = metrics.FanPwm;
1427
1428	gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
1429
1430	*table = (void *)gpu_metrics;
1431
1432	return sizeof(struct gpu_metrics_v2_2);
1433}
1434
1435static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state)
1436{
1437
1438	return 0;
1439}
1440
1441static int renoir_get_enabled_mask(struct smu_context *smu,
1442				   uint64_t *feature_mask)
1443{
1444	if (!feature_mask)
1445		return -EINVAL;
1446	memset(feature_mask, 0xff, sizeof(*feature_mask));
1447
1448	return 0;
1449}
1450
1451static const struct pptable_funcs renoir_ppt_funcs = {
1452	.set_power_state = NULL,
1453	.print_clk_levels = renoir_print_clk_levels,
1454	.get_current_power_state = renoir_get_current_power_state,
1455	.dpm_set_vcn_enable = renoir_dpm_set_vcn_enable,
1456	.dpm_set_jpeg_enable = renoir_dpm_set_jpeg_enable,
1457	.force_clk_levels = renoir_force_clk_levels,
1458	.set_power_profile_mode = renoir_set_power_profile_mode,
1459	.set_performance_level = renoir_set_performance_level,
1460	.get_dpm_clock_table = renoir_get_dpm_clock_table,
1461	.set_watermarks_table = renoir_set_watermarks_table,
1462	.get_power_profile_mode = renoir_get_power_profile_mode,
1463	.read_sensor = renoir_read_sensor,
1464	.check_fw_status = smu_v12_0_check_fw_status,
1465	.check_fw_version = smu_v12_0_check_fw_version,
1466	.powergate_sdma = smu_v12_0_powergate_sdma,
1467	.send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
1468	.send_smc_msg = smu_cmn_send_smc_msg,
1469	.set_gfx_cgpg = smu_v12_0_set_gfx_cgpg,
1470	.gfx_off_control = smu_v12_0_gfx_off_control,
1471	.get_gfx_off_status = smu_v12_0_get_gfxoff_status,
1472	.init_smc_tables = renoir_init_smc_tables,
1473	.fini_smc_tables = smu_v12_0_fini_smc_tables,
1474	.set_default_dpm_table = smu_v12_0_set_default_dpm_tables,
1475	.get_enabled_mask = renoir_get_enabled_mask,
1476	.feature_is_enabled = smu_cmn_feature_is_enabled,
1477	.disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
1478	.get_dpm_ultimate_freq = renoir_get_dpm_ultimate_freq,
1479	.mode2_reset = smu_v12_0_mode2_reset,
1480	.set_soft_freq_limited_range = smu_v12_0_set_soft_freq_limited_range,
1481	.set_driver_table_location = smu_v12_0_set_driver_table_location,
1482	.is_dpm_running = renoir_is_dpm_running,
1483	.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
1484	.set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
1485	.get_gpu_metrics = renoir_get_gpu_metrics,
1486	.gfx_state_change_set = renoir_gfx_state_change_set,
1487	.set_fine_grain_gfx_freq_parameters = renoir_set_fine_grain_gfx_freq_parameters,
1488	.od_edit_dpm_table = renoir_od_edit_dpm_table,
1489	.get_vbios_bootup_values = smu_v12_0_get_vbios_bootup_values,
1490};
1491
1492void renoir_set_ppt_funcs(struct smu_context *smu)
1493{
1494	struct amdgpu_device *adev = smu->adev;
1495
1496	smu->ppt_funcs = &renoir_ppt_funcs;
1497	smu->message_map = renoir_message_map;
1498	smu->clock_map = renoir_clk_map;
1499	smu->table_map = renoir_table_map;
1500	smu->workload_map = renoir_workload_map;
1501	smu->smc_driver_if_version = SMU12_DRIVER_IF_VERSION;
1502	smu->is_apu = true;
1503	smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_82);
1504	smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_66);
1505	smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
1506}
~/ Read-only file preview.