File Index
Files and directories
Sign in
FILE

smu10_hwmgr.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c C
   1/*
   2 * Copyright 2015 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#include "pp_debug.h"
  24#include <linux/types.h>
  25#include <linux/kernel.h>
  26#include <linux/slab.h>
  27#include "atom-types.h"
  28#include "atombios.h"
  29#include "processpptables.h"
  30#include "cgs_common.h"
  31#include "smumgr.h"
  32#include "hwmgr.h"
  33#include "hardwaremanager.h"
  34#include "rv_ppsmc.h"
  35#include "smu10_hwmgr.h"
  36#include "power_state.h"
  37#include "soc15_common.h"
  38#include "smu10.h"
  39#include "asic_reg/pwr/pwr_10_0_offset.h"
  40#include "asic_reg/pwr/pwr_10_0_sh_mask.h"
  41
  42#define SMU10_MAX_DEEPSLEEP_DIVIDER_ID     5
  43#define SMU10_MINIMUM_ENGINE_CLOCK         800   /* 8Mhz, the low boundary of engine clock allowed on this chip */
  44#define SCLK_MIN_DIV_INTV_SHIFT         12
  45#define SMU10_DISPCLK_BYPASS_THRESHOLD     10000 /* 100Mhz */
  46#define SMC_RAM_END                     0x40000
  47
  48static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic;
  49
  50
  51static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
  52		struct pp_display_clock_request *clock_req)
  53{
  54	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
  55	enum amd_pp_clock_type clk_type = clock_req->clock_type;
  56	uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
  57	PPSMC_Msg        msg;
  58
  59	switch (clk_type) {
  60	case amd_pp_dcf_clock:
  61		if (clk_freq == smu10_data->dcf_actual_hard_min_freq)
  62			return 0;
  63		msg =  PPSMC_MSG_SetHardMinDcefclkByFreq;
  64		smu10_data->dcf_actual_hard_min_freq = clk_freq;
  65		break;
  66	case amd_pp_soc_clock:
  67		 msg = PPSMC_MSG_SetHardMinSocclkByFreq;
  68		break;
  69	case amd_pp_f_clock:
  70		if (clk_freq == smu10_data->f_actual_hard_min_freq)
  71			return 0;
  72		smu10_data->f_actual_hard_min_freq = clk_freq;
  73		msg = PPSMC_MSG_SetHardMinFclkByFreq;
  74		break;
  75	default:
  76		pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
  77		return -EINVAL;
  78	}
  79	smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq, NULL);
  80
  81	return 0;
  82}
  83
  84static struct smu10_power_state *cast_smu10_ps(struct pp_hw_power_state *hw_ps)
  85{
  86	if (SMU10_Magic != hw_ps->magic)
  87		return NULL;
  88
  89	return (struct smu10_power_state *)hw_ps;
  90}
  91
  92static const struct smu10_power_state *cast_const_smu10_ps(
  93				const struct pp_hw_power_state *hw_ps)
  94{
  95	if (SMU10_Magic != hw_ps->magic)
  96		return NULL;
  97
  98	return (struct smu10_power_state *)hw_ps;
  99}
 100
 101static int smu10_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
 102{
 103	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 104
 105	smu10_data->dce_slow_sclk_threshold = 30000;
 106	smu10_data->thermal_auto_throttling_treshold = 0;
 107	smu10_data->is_nb_dpm_enabled = 1;
 108	smu10_data->dpm_flags = 1;
 109	smu10_data->need_min_deep_sleep_dcefclk = true;
 110	smu10_data->num_active_display = 0;
 111	smu10_data->deep_sleep_dcefclk = 0;
 112
 113	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 114					PHM_PlatformCaps_SclkDeepSleep);
 115
 116	phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 117				PHM_PlatformCaps_SclkThrottleLowNotification);
 118
 119	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 120				PHM_PlatformCaps_PowerPlaySupport);
 121	return 0;
 122}
 123
 124static int smu10_construct_max_power_limits_table(struct pp_hwmgr *hwmgr,
 125			struct phm_clock_and_voltage_limits *table)
 126{
 127	return 0;
 128}
 129
 130static int smu10_init_dynamic_state_adjustment_rule_settings(
 131							struct pp_hwmgr *hwmgr)
 132{
 133	int count = 8;
 134	struct phm_clock_voltage_dependency_table *table_clk_vlt;
 135
 136	table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, count),
 137				GFP_KERNEL);
 138
 139	if (NULL == table_clk_vlt) {
 140		pr_err("Can not allocate memory!\n");
 141		return -ENOMEM;
 142	}
 143
 144	table_clk_vlt->count = count;
 145	table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0;
 146	table_clk_vlt->entries[0].v = 0;
 147	table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1;
 148	table_clk_vlt->entries[1].v = 1;
 149	table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2;
 150	table_clk_vlt->entries[2].v = 2;
 151	table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3;
 152	table_clk_vlt->entries[3].v = 3;
 153	table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4;
 154	table_clk_vlt->entries[4].v = 4;
 155	table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5;
 156	table_clk_vlt->entries[5].v = 5;
 157	table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6;
 158	table_clk_vlt->entries[6].v = 6;
 159	table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7;
 160	table_clk_vlt->entries[7].v = 7;
 161	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
 162
 163	return 0;
 164}
 165
 166static int smu10_get_system_info_data(struct pp_hwmgr *hwmgr)
 167{
 168	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)hwmgr->backend;
 169
 170	smu10_data->sys_info.htc_hyst_lmt = 5;
 171	smu10_data->sys_info.htc_tmp_lmt = 203;
 172
 173	if (smu10_data->thermal_auto_throttling_treshold == 0)
 174		 smu10_data->thermal_auto_throttling_treshold = 203;
 175
 176	smu10_construct_max_power_limits_table (hwmgr,
 177				    &hwmgr->dyn_state.max_clock_voltage_on_ac);
 178
 179	smu10_init_dynamic_state_adjustment_rule_settings(hwmgr);
 180
 181	return 0;
 182}
 183
 184static int smu10_construct_boot_state(struct pp_hwmgr *hwmgr)
 185{
 186	return 0;
 187}
 188
 189static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input)
 190{
 191	struct PP_Clocks clocks = {0};
 192	struct pp_display_clock_request clock_req;
 193
 194	clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;
 195	clock_req.clock_type = amd_pp_dcf_clock;
 196	clock_req.clock_freq_in_khz = clocks.dcefClock * 10;
 197
 198	PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, &clock_req),
 199				"Attempt to set DCF Clock Failed!", return -EINVAL);
 200
 201	return 0;
 202}
 203
 204static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock)
 205{
 206	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 207
 208	if (clock && smu10_data->deep_sleep_dcefclk != clock) {
 209		smu10_data->deep_sleep_dcefclk = clock;
 210		smum_send_msg_to_smc_with_parameter(hwmgr,
 211					PPSMC_MSG_SetMinDeepSleepDcefclk,
 212					smu10_data->deep_sleep_dcefclk,
 213					NULL);
 214	}
 215	return 0;
 216}
 217
 218static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
 219{
 220	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 221
 222	if (clock && smu10_data->dcf_actual_hard_min_freq != clock) {
 223		smu10_data->dcf_actual_hard_min_freq = clock;
 224		smum_send_msg_to_smc_with_parameter(hwmgr,
 225					PPSMC_MSG_SetHardMinDcefclkByFreq,
 226					smu10_data->dcf_actual_hard_min_freq,
 227					NULL);
 228	}
 229	return 0;
 230}
 231
 232static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
 233{
 234	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 235
 236	if (clock && smu10_data->f_actual_hard_min_freq != clock) {
 237		smu10_data->f_actual_hard_min_freq = clock;
 238		smum_send_msg_to_smc_with_parameter(hwmgr,
 239					PPSMC_MSG_SetHardMinFclkByFreq,
 240					smu10_data->f_actual_hard_min_freq,
 241					NULL);
 242	}
 243	return 0;
 244}
 245
 246static int smu10_set_hard_min_gfxclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
 247{
 248	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 249
 250	if (clock && smu10_data->gfx_actual_soft_min_freq != clock) {
 251		smu10_data->gfx_actual_soft_min_freq = clock;
 252		smum_send_msg_to_smc_with_parameter(hwmgr,
 253					PPSMC_MSG_SetHardMinGfxClk,
 254					clock,
 255					NULL);
 256	}
 257	return 0;
 258}
 259
 260static int smu10_set_soft_max_gfxclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock)
 261{
 262	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 263
 264	if (clock && smu10_data->gfx_max_freq_limit != (clock * 100))  {
 265		smu10_data->gfx_max_freq_limit = clock * 100;
 266		smum_send_msg_to_smc_with_parameter(hwmgr,
 267					PPSMC_MSG_SetSoftMaxGfxClk,
 268					clock,
 269					NULL);
 270	}
 271	return 0;
 272}
 273
 274static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count)
 275{
 276	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 277
 278	if (smu10_data->num_active_display != count) {
 279		smu10_data->num_active_display = count;
 280		smum_send_msg_to_smc_with_parameter(hwmgr,
 281				PPSMC_MSG_SetDisplayCount,
 282				smu10_data->num_active_display,
 283				NULL);
 284	}
 285
 286	return 0;
 287}
 288
 289static int smu10_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
 290{
 291	return smu10_set_clock_limit(hwmgr, input);
 292}
 293
 294static int smu10_init_power_gate_state(struct pp_hwmgr *hwmgr)
 295{
 296	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 297	struct amdgpu_device *adev = hwmgr->adev;
 298
 299	smu10_data->vcn_power_gated = true;
 300	smu10_data->isp_tileA_power_gated = true;
 301	smu10_data->isp_tileB_power_gated = true;
 302
 303	if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)
 304		return smum_send_msg_to_smc_with_parameter(hwmgr,
 305							   PPSMC_MSG_SetGfxCGPG,
 306							   true,
 307							   NULL);
 308	else
 309		return 0;
 310}
 311
 312
 313static int smu10_setup_asic_task(struct pp_hwmgr *hwmgr)
 314{
 315	return smu10_init_power_gate_state(hwmgr);
 316}
 317
 318static int smu10_reset_cc6_data(struct pp_hwmgr *hwmgr)
 319{
 320	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 321
 322	smu10_data->separation_time = 0;
 323	smu10_data->cc6_disable = false;
 324	smu10_data->pstate_disable = false;
 325	smu10_data->cc6_setting_changed = false;
 326
 327	return 0;
 328}
 329
 330static int smu10_power_off_asic(struct pp_hwmgr *hwmgr)
 331{
 332	return smu10_reset_cc6_data(hwmgr);
 333}
 334
 335static bool smu10_is_gfx_on(struct pp_hwmgr *hwmgr)
 336{
 337	uint32_t reg;
 338	struct amdgpu_device *adev = hwmgr->adev;
 339
 340	reg = RREG32_SOC15(PWR, 0, mmPWR_MISC_CNTL_STATUS);
 341	if ((reg & PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK) ==
 342	    (0x2 << PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT))
 343		return true;
 344
 345	return false;
 346}
 347
 348static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr)
 349{
 350	struct amdgpu_device *adev = hwmgr->adev;
 351
 352	if (adev->pm.pp_feature & PP_GFXOFF_MASK) {
 353		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff, NULL);
 354
 355		/* confirm gfx is back to "on" state */
 356		while (!smu10_is_gfx_on(hwmgr))
 357			msleep(1);
 358	}
 359
 360	return 0;
 361}
 362
 363static int smu10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
 364{
 365	return 0;
 366}
 367
 368static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr)
 369{
 370	struct amdgpu_device *adev = hwmgr->adev;
 371
 372	if (adev->pm.pp_feature & PP_GFXOFF_MASK)
 373		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff, NULL);
 374
 375	return 0;
 376}
 377
 378static void smu10_populate_umdpstate_clocks(struct pp_hwmgr *hwmgr)
 379{
 380	hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK;
 381	hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK;
 382
 383	smum_send_msg_to_smc(hwmgr,
 384			     PPSMC_MSG_GetMaxGfxclkFrequency,
 385			     &hwmgr->pstate_sclk_peak);
 386	hwmgr->pstate_mclk_peak = SMU10_UMD_PSTATE_PEAK_FCLK;
 387}
 388
 389static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
 390{
 391	struct amdgpu_device *adev = hwmgr->adev;
 392	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 393	int ret = -EINVAL;
 394
 395	if (adev->in_suspend) {
 396		pr_info("restore the fine grain parameters\n");
 397
 398		ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 399					PPSMC_MSG_SetHardMinGfxClk,
 400					smu10_data->gfx_actual_soft_min_freq,
 401					NULL);
 402		if (ret)
 403			return ret;
 404		ret = smum_send_msg_to_smc_with_parameter(hwmgr,
 405					PPSMC_MSG_SetSoftMaxGfxClk,
 406					smu10_data->gfx_actual_soft_max_freq,
 407					NULL);
 408		if (ret)
 409			return ret;
 410	}
 411
 412	smu10_populate_umdpstate_clocks(hwmgr);
 413
 414	return 0;
 415}
 416
 417static int smu10_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable)
 418{
 419	if (enable)
 420		return smu10_enable_gfx_off(hwmgr);
 421	else
 422		return smu10_disable_gfx_off(hwmgr);
 423}
 424
 425static int smu10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
 426				struct pp_power_state  *prequest_ps,
 427			const struct pp_power_state *pcurrent_ps)
 428{
 429	return 0;
 430}
 431
 432/* temporary hardcoded clock voltage breakdown tables */
 433static const DpmClock_t VddDcfClk[] = {
 434	{ 300, 2600},
 435	{ 600, 3200},
 436	{ 600, 3600},
 437};
 438
 439static const DpmClock_t VddSocClk[] = {
 440	{ 478, 2600},
 441	{ 722, 3200},
 442	{ 722, 3600},
 443};
 444
 445static const DpmClock_t VddFClk[] = {
 446	{ 400, 2600},
 447	{1200, 3200},
 448	{1200, 3600},
 449};
 450
 451static const DpmClock_t VddDispClk[] = {
 452	{ 435, 2600},
 453	{ 661, 3200},
 454	{1086, 3600},
 455};
 456
 457static const DpmClock_t VddDppClk[] = {
 458	{ 435, 2600},
 459	{ 661, 3200},
 460	{ 661, 3600},
 461};
 462
 463static const DpmClock_t VddPhyClk[] = {
 464	{ 540, 2600},
 465	{ 810, 3200},
 466	{ 810, 3600},
 467};
 468
 469static int smu10_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
 470			struct smu10_voltage_dependency_table **pptable,
 471			uint32_t num_entry, const DpmClock_t *pclk_dependency_table)
 472{
 473	uint32_t i;
 474	struct smu10_voltage_dependency_table *ptable;
 475
 476	ptable = kzalloc(struct_size(ptable, entries, num_entry), GFP_KERNEL);
 477	if (NULL == ptable)
 478		return -ENOMEM;
 479
 480	ptable->count = num_entry;
 481
 482	for (i = 0; i < ptable->count; i++) {
 483		ptable->entries[i].clk         = pclk_dependency_table->Freq * 100;
 484		ptable->entries[i].vol         = pclk_dependency_table->Vol;
 485		pclk_dependency_table++;
 486	}
 487
 488	*pptable = ptable;
 489
 490	return 0;
 491}
 492
 493
 494static int smu10_populate_clock_table(struct pp_hwmgr *hwmgr)
 495{
 496	uint32_t result;
 497
 498	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 499	DpmClocks_t  *table = &(smu10_data->clock_table);
 500	struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
 501
 502	result = smum_smc_table_manager(hwmgr, (uint8_t *)table, SMU10_CLOCKTABLE, true);
 503
 504	PP_ASSERT_WITH_CODE((0 == result),
 505			"Attempt to copy clock table from smc failed",
 506			return result);
 507
 508	if (0 == result && table->DcefClocks[0].Freq != 0) {
 509		smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
 510						NUM_DCEFCLK_DPM_LEVELS,
 511						&smu10_data->clock_table.DcefClocks[0]);
 512		smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
 513						NUM_SOCCLK_DPM_LEVELS,
 514						&smu10_data->clock_table.SocClocks[0]);
 515		smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
 516						NUM_FCLK_DPM_LEVELS,
 517						&smu10_data->clock_table.FClocks[0]);
 518		smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_mclk,
 519						NUM_MEMCLK_DPM_LEVELS,
 520						&smu10_data->clock_table.MemClocks[0]);
 521	} else {
 522		smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
 523						ARRAY_SIZE(VddDcfClk),
 524						&VddDcfClk[0]);
 525		smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
 526						ARRAY_SIZE(VddSocClk),
 527						&VddSocClk[0]);
 528		smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
 529						ARRAY_SIZE(VddFClk),
 530						&VddFClk[0]);
 531	}
 532	smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dispclk,
 533					ARRAY_SIZE(VddDispClk),
 534					&VddDispClk[0]);
 535	smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dppclk,
 536					ARRAY_SIZE(VddDppClk), &VddDppClk[0]);
 537	smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk,
 538					ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]);
 539
 540	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &result);
 541	smu10_data->gfx_min_freq_limit = result / 10 * 1000;
 542
 543	smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &result);
 544	smu10_data->gfx_max_freq_limit = result / 10 * 1000;
 545
 546	return 0;
 547}
 548
 549static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 550{
 551	int result = 0;
 552	struct smu10_hwmgr *data;
 553
 554	data = kzalloc(sizeof(struct smu10_hwmgr), GFP_KERNEL);
 555	if (data == NULL)
 556		return -ENOMEM;
 557
 558	hwmgr->backend = data;
 559
 560	result = smu10_initialize_dpm_defaults(hwmgr);
 561	if (result != 0) {
 562		pr_err("smu10_initialize_dpm_defaults failed\n");
 563		return result;
 564	}
 565
 566	smu10_populate_clock_table(hwmgr);
 567
 568	result = smu10_get_system_info_data(hwmgr);
 569	if (result != 0) {
 570		pr_err("smu10_get_system_info_data failed\n");
 571		return result;
 572	}
 573
 574	smu10_construct_boot_state(hwmgr);
 575
 576	hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
 577						SMU10_MAX_HARDWARE_POWERLEVELS;
 578
 579	hwmgr->platform_descriptor.hardwarePerformanceLevels =
 580						SMU10_MAX_HARDWARE_POWERLEVELS;
 581
 582	hwmgr->platform_descriptor.vbiosInterruptId = 0;
 583
 584	hwmgr->platform_descriptor.clockStep.engineClock = 500;
 585
 586	hwmgr->platform_descriptor.clockStep.memoryClock = 500;
 587
 588	hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
 589
 590	/* enable the pp_od_clk_voltage sysfs file */
 591	hwmgr->od_enabled = 1;
 592	/* disabled fine grain tuning function by default */
 593	data->fine_grain_enabled = 0;
 594	return result;
 595}
 596
 597static int smu10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
 598{
 599	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 600	struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
 601
 602	kfree(pinfo->vdd_dep_on_dcefclk);
 603	pinfo->vdd_dep_on_dcefclk = NULL;
 604	kfree(pinfo->vdd_dep_on_socclk);
 605	pinfo->vdd_dep_on_socclk = NULL;
 606	kfree(pinfo->vdd_dep_on_fclk);
 607	pinfo->vdd_dep_on_fclk = NULL;
 608	kfree(pinfo->vdd_dep_on_dispclk);
 609	pinfo->vdd_dep_on_dispclk = NULL;
 610	kfree(pinfo->vdd_dep_on_dppclk);
 611	pinfo->vdd_dep_on_dppclk = NULL;
 612	kfree(pinfo->vdd_dep_on_phyclk);
 613	pinfo->vdd_dep_on_phyclk = NULL;
 614
 615	kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
 616	hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
 617
 618	kfree(hwmgr->backend);
 619	hwmgr->backend = NULL;
 620
 621	return 0;
 622}
 623
 624static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
 625				enum amd_dpm_forced_level level)
 626{
 627	struct smu10_hwmgr *data = hwmgr->backend;
 628	uint32_t min_sclk = hwmgr->display_config->min_core_set_clock;
 629	uint32_t min_mclk = hwmgr->display_config->min_mem_set_clock/100;
 630	uint32_t index_fclk = data->clock_vol_info.vdd_dep_on_fclk->count - 1;
 631	uint32_t index_socclk = data->clock_vol_info.vdd_dep_on_socclk->count - 1;
 632	uint32_t fine_grain_min_freq = 0, fine_grain_max_freq = 0;
 633
 634	if (hwmgr->smu_version < 0x1E3700) {
 635		pr_info("smu firmware version too old, can not set dpm level\n");
 636		return 0;
 637	}
 638
 639	if (min_sclk < data->gfx_min_freq_limit)
 640		min_sclk = data->gfx_min_freq_limit;
 641
 642	min_sclk /= 100; /* transfer 10KHz to MHz */
 643	if (min_mclk < data->clock_table.FClocks[0].Freq)
 644		min_mclk = data->clock_table.FClocks[0].Freq;
 645
 646	switch (level) {
 647	case AMD_DPM_FORCED_LEVEL_HIGH:
 648	case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
 649		data->fine_grain_enabled = 0;
 650
 651		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &fine_grain_min_freq);
 652		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &fine_grain_max_freq);
 653
 654		data->gfx_actual_soft_min_freq = fine_grain_min_freq;
 655		data->gfx_actual_soft_max_freq = fine_grain_max_freq;
 656
 657		smum_send_msg_to_smc_with_parameter(hwmgr,
 658						PPSMC_MSG_SetHardMinGfxClk,
 659						data->gfx_max_freq_limit/100,
 660						NULL);
 661		smum_send_msg_to_smc_with_parameter(hwmgr,
 662						PPSMC_MSG_SetHardMinFclkByFreq,
 663						SMU10_UMD_PSTATE_PEAK_FCLK,
 664						NULL);
 665		smum_send_msg_to_smc_with_parameter(hwmgr,
 666						PPSMC_MSG_SetHardMinSocclkByFreq,
 667						SMU10_UMD_PSTATE_PEAK_SOCCLK,
 668						NULL);
 669		smum_send_msg_to_smc_with_parameter(hwmgr,
 670						PPSMC_MSG_SetHardMinVcn,
 671						SMU10_UMD_PSTATE_VCE,
 672						NULL);
 673
 674		smum_send_msg_to_smc_with_parameter(hwmgr,
 675						PPSMC_MSG_SetSoftMaxGfxClk,
 676						data->gfx_max_freq_limit/100,
 677						NULL);
 678		smum_send_msg_to_smc_with_parameter(hwmgr,
 679						PPSMC_MSG_SetSoftMaxFclkByFreq,
 680						SMU10_UMD_PSTATE_PEAK_FCLK,
 681						NULL);
 682		smum_send_msg_to_smc_with_parameter(hwmgr,
 683						PPSMC_MSG_SetSoftMaxSocclkByFreq,
 684						SMU10_UMD_PSTATE_PEAK_SOCCLK,
 685						NULL);
 686		smum_send_msg_to_smc_with_parameter(hwmgr,
 687						PPSMC_MSG_SetSoftMaxVcn,
 688						SMU10_UMD_PSTATE_VCE,
 689						NULL);
 690		break;
 691	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
 692		data->fine_grain_enabled = 0;
 693
 694		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &fine_grain_min_freq);
 695		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &fine_grain_max_freq);
 696
 697		data->gfx_actual_soft_min_freq = fine_grain_min_freq;
 698		data->gfx_actual_soft_max_freq = fine_grain_max_freq;
 699
 700		smum_send_msg_to_smc_with_parameter(hwmgr,
 701						PPSMC_MSG_SetHardMinGfxClk,
 702						min_sclk,
 703						NULL);
 704		smum_send_msg_to_smc_with_parameter(hwmgr,
 705						PPSMC_MSG_SetSoftMaxGfxClk,
 706						min_sclk,
 707						NULL);
 708		break;
 709	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
 710		data->fine_grain_enabled = 0;
 711
 712		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &fine_grain_min_freq);
 713		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &fine_grain_max_freq);
 714
 715		data->gfx_actual_soft_min_freq = fine_grain_min_freq;
 716		data->gfx_actual_soft_max_freq = fine_grain_max_freq;
 717
 718		smum_send_msg_to_smc_with_parameter(hwmgr,
 719						PPSMC_MSG_SetHardMinFclkByFreq,
 720						min_mclk,
 721						NULL);
 722		smum_send_msg_to_smc_with_parameter(hwmgr,
 723						PPSMC_MSG_SetSoftMaxFclkByFreq,
 724						min_mclk,
 725						NULL);
 726		break;
 727	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
 728		data->fine_grain_enabled = 0;
 729
 730		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &fine_grain_min_freq);
 731		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &fine_grain_max_freq);
 732
 733		data->gfx_actual_soft_min_freq = fine_grain_min_freq;
 734		data->gfx_actual_soft_max_freq = fine_grain_max_freq;
 735
 736		smum_send_msg_to_smc_with_parameter(hwmgr,
 737						PPSMC_MSG_SetHardMinGfxClk,
 738						SMU10_UMD_PSTATE_GFXCLK,
 739						NULL);
 740		smum_send_msg_to_smc_with_parameter(hwmgr,
 741						PPSMC_MSG_SetHardMinFclkByFreq,
 742						SMU10_UMD_PSTATE_FCLK,
 743						NULL);
 744		smum_send_msg_to_smc_with_parameter(hwmgr,
 745						PPSMC_MSG_SetHardMinSocclkByFreq,
 746						SMU10_UMD_PSTATE_SOCCLK,
 747						NULL);
 748		smum_send_msg_to_smc_with_parameter(hwmgr,
 749						PPSMC_MSG_SetHardMinVcn,
 750						SMU10_UMD_PSTATE_PROFILE_VCE,
 751						NULL);
 752
 753		smum_send_msg_to_smc_with_parameter(hwmgr,
 754						PPSMC_MSG_SetSoftMaxGfxClk,
 755						SMU10_UMD_PSTATE_GFXCLK,
 756						NULL);
 757		smum_send_msg_to_smc_with_parameter(hwmgr,
 758						PPSMC_MSG_SetSoftMaxFclkByFreq,
 759						SMU10_UMD_PSTATE_FCLK,
 760						NULL);
 761		smum_send_msg_to_smc_with_parameter(hwmgr,
 762						PPSMC_MSG_SetSoftMaxSocclkByFreq,
 763						SMU10_UMD_PSTATE_SOCCLK,
 764						NULL);
 765		smum_send_msg_to_smc_with_parameter(hwmgr,
 766						PPSMC_MSG_SetSoftMaxVcn,
 767						SMU10_UMD_PSTATE_PROFILE_VCE,
 768						NULL);
 769		break;
 770	case AMD_DPM_FORCED_LEVEL_AUTO:
 771		data->fine_grain_enabled = 0;
 772
 773		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &fine_grain_min_freq);
 774		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &fine_grain_max_freq);
 775
 776		data->gfx_actual_soft_min_freq = fine_grain_min_freq;
 777		data->gfx_actual_soft_max_freq = fine_grain_max_freq;
 778
 779		smum_send_msg_to_smc_with_parameter(hwmgr,
 780						PPSMC_MSG_SetHardMinGfxClk,
 781						min_sclk,
 782						NULL);
 783		smum_send_msg_to_smc_with_parameter(hwmgr,
 784						PPSMC_MSG_SetHardMinFclkByFreq,
 785						hwmgr->display_config->num_display > 3 ?
 786						(data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk / 100) :
 787						min_mclk,
 788						NULL);
 789
 790		smum_send_msg_to_smc_with_parameter(hwmgr,
 791						PPSMC_MSG_SetHardMinSocclkByFreq,
 792						data->clock_vol_info.vdd_dep_on_socclk->entries[0].clk / 100,
 793						NULL);
 794		smum_send_msg_to_smc_with_parameter(hwmgr,
 795						PPSMC_MSG_SetHardMinVcn,
 796						SMU10_UMD_PSTATE_MIN_VCE,
 797						NULL);
 798
 799		smum_send_msg_to_smc_with_parameter(hwmgr,
 800						PPSMC_MSG_SetSoftMaxGfxClk,
 801						data->gfx_max_freq_limit/100,
 802						NULL);
 803		smum_send_msg_to_smc_with_parameter(hwmgr,
 804						PPSMC_MSG_SetSoftMaxFclkByFreq,
 805						data->clock_vol_info.vdd_dep_on_fclk->entries[index_fclk].clk / 100,
 806						NULL);
 807		smum_send_msg_to_smc_with_parameter(hwmgr,
 808						PPSMC_MSG_SetSoftMaxSocclkByFreq,
 809						data->clock_vol_info.vdd_dep_on_socclk->entries[index_socclk].clk / 100,
 810						NULL);
 811		smum_send_msg_to_smc_with_parameter(hwmgr,
 812						PPSMC_MSG_SetSoftMaxVcn,
 813						SMU10_UMD_PSTATE_VCE,
 814						NULL);
 815		break;
 816	case AMD_DPM_FORCED_LEVEL_LOW:
 817		data->fine_grain_enabled = 0;
 818
 819		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &fine_grain_min_freq);
 820		smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &fine_grain_max_freq);
 821
 822		data->gfx_actual_soft_min_freq = fine_grain_min_freq;
 823		data->gfx_actual_soft_max_freq = fine_grain_max_freq;
 824
 825		smum_send_msg_to_smc_with_parameter(hwmgr,
 826						PPSMC_MSG_SetHardMinGfxClk,
 827						data->gfx_min_freq_limit/100,
 828						NULL);
 829		smum_send_msg_to_smc_with_parameter(hwmgr,
 830						PPSMC_MSG_SetSoftMaxGfxClk,
 831						data->gfx_min_freq_limit/100,
 832						NULL);
 833		smum_send_msg_to_smc_with_parameter(hwmgr,
 834						PPSMC_MSG_SetHardMinFclkByFreq,
 835						min_mclk,
 836						NULL);
 837		smum_send_msg_to_smc_with_parameter(hwmgr,
 838						PPSMC_MSG_SetSoftMaxFclkByFreq,
 839						min_mclk,
 840						NULL);
 841		break;
 842	case AMD_DPM_FORCED_LEVEL_MANUAL:
 843		data->fine_grain_enabled = 1;
 844		break;
 845	case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
 846	default:
 847		break;
 848	}
 849	return 0;
 850}
 851
 852static uint32_t smu10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
 853{
 854	struct smu10_hwmgr *data;
 855
 856	if (hwmgr == NULL)
 857		return -EINVAL;
 858
 859	data = (struct smu10_hwmgr *)(hwmgr->backend);
 860
 861	if (low)
 862		return data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
 863	else
 864		return data->clock_vol_info.vdd_dep_on_fclk->entries[
 865			data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
 866}
 867
 868static uint32_t smu10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
 869{
 870	struct smu10_hwmgr *data;
 871
 872	if (hwmgr == NULL)
 873		return -EINVAL;
 874
 875	data = (struct smu10_hwmgr *)(hwmgr->backend);
 876
 877	if (low)
 878		return data->gfx_min_freq_limit;
 879	else
 880		return data->gfx_max_freq_limit;
 881}
 882
 883static int smu10_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
 884					struct pp_hw_power_state *hw_ps)
 885{
 886	return 0;
 887}
 888
 889static int smu10_dpm_get_pp_table_entry_callback(
 890						     struct pp_hwmgr *hwmgr,
 891					   struct pp_hw_power_state *hw_ps,
 892							  unsigned int index,
 893						     const void *clock_info)
 894{
 895	struct smu10_power_state *smu10_ps = cast_smu10_ps(hw_ps);
 896
 897	smu10_ps->levels[index].engine_clock = 0;
 898
 899	smu10_ps->levels[index].vddc_index = 0;
 900	smu10_ps->level = index + 1;
 901
 902	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
 903		smu10_ps->levels[index].ds_divider_index = 5;
 904		smu10_ps->levels[index].ss_divider_index = 5;
 905	}
 906
 907	return 0;
 908}
 909
 910static int smu10_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr)
 911{
 912	int result;
 913	unsigned long ret = 0;
 914
 915	result = pp_tables_get_num_of_entries(hwmgr, &ret);
 916
 917	return result ? 0 : ret;
 918}
 919
 920static int smu10_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr,
 921		    unsigned long entry, struct pp_power_state *ps)
 922{
 923	int result;
 924	struct smu10_power_state *smu10_ps;
 925
 926	ps->hardware.magic = SMU10_Magic;
 927
 928	smu10_ps = cast_smu10_ps(&(ps->hardware));
 929
 930	result = pp_tables_get_entry(hwmgr, entry, ps,
 931			smu10_dpm_get_pp_table_entry_callback);
 932
 933	smu10_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK;
 934	smu10_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK;
 935
 936	return result;
 937}
 938
 939static int smu10_get_power_state_size(struct pp_hwmgr *hwmgr)
 940{
 941	return sizeof(struct smu10_power_state);
 942}
 943
 944static int smu10_set_cpu_power_state(struct pp_hwmgr *hwmgr)
 945{
 946	return 0;
 947}
 948
 949
 950static int smu10_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time,
 951			bool cc6_disable, bool pstate_disable, bool pstate_switch_disable)
 952{
 953	struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend);
 954
 955	if (separation_time != data->separation_time ||
 956			cc6_disable != data->cc6_disable ||
 957			pstate_disable != data->pstate_disable) {
 958		data->separation_time = separation_time;
 959		data->cc6_disable = cc6_disable;
 960		data->pstate_disable = pstate_disable;
 961		data->cc6_setting_changed = true;
 962	}
 963	return 0;
 964}
 965
 966static int smu10_get_dal_power_level(struct pp_hwmgr *hwmgr,
 967		struct amd_pp_simple_clock_info *info)
 968{
 969	return -EINVAL;
 970}
 971
 972static int smu10_force_clock_level(struct pp_hwmgr *hwmgr,
 973		enum pp_clock_type type, uint32_t mask)
 974{
 975	struct smu10_hwmgr *data = hwmgr->backend;
 976	struct smu10_voltage_dependency_table *mclk_table =
 977					data->clock_vol_info.vdd_dep_on_fclk;
 978	uint32_t low, high;
 979
 980	low = mask ? (ffs(mask) - 1) : 0;
 981	high = mask ? (fls(mask) - 1) : 0;
 982
 983	switch (type) {
 984	case PP_SCLK:
 985		if (low > 2 || high > 2) {
 986			pr_info("Currently sclk only support 3 levels on RV\n");
 987			return -EINVAL;
 988		}
 989
 990		smum_send_msg_to_smc_with_parameter(hwmgr,
 991						PPSMC_MSG_SetHardMinGfxClk,
 992						low == 2 ? data->gfx_max_freq_limit/100 :
 993						low == 1 ? SMU10_UMD_PSTATE_GFXCLK :
 994						data->gfx_min_freq_limit/100,
 995						NULL);
 996
 997		smum_send_msg_to_smc_with_parameter(hwmgr,
 998						PPSMC_MSG_SetSoftMaxGfxClk,
 999						high == 0 ? data->gfx_min_freq_limit/100 :
1000						high == 1 ? SMU10_UMD_PSTATE_GFXCLK :
1001						data->gfx_max_freq_limit/100,
1002						NULL);
1003		break;
1004
1005	case PP_MCLK:
1006		if (low > mclk_table->count - 1 || high > mclk_table->count - 1)
1007			return -EINVAL;
1008
1009		smum_send_msg_to_smc_with_parameter(hwmgr,
1010						PPSMC_MSG_SetHardMinFclkByFreq,
1011						mclk_table->entries[low].clk/100,
1012						NULL);
1013
1014		smum_send_msg_to_smc_with_parameter(hwmgr,
1015						PPSMC_MSG_SetSoftMaxFclkByFreq,
1016						mclk_table->entries[high].clk/100,
1017						NULL);
1018		break;
1019
1020	case PP_PCIE:
1021	default:
1022		break;
1023	}
1024	return 0;
1025}
1026
1027static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
1028		enum pp_clock_type type, char *buf)
1029{
1030	struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend);
1031	struct smu10_voltage_dependency_table *mclk_table =
1032			data->clock_vol_info.vdd_dep_on_fclk;
1033	uint32_t i, now, size = 0;
1034	uint32_t min_freq, max_freq = 0;
1035	int ret = 0;
1036
1037	switch (type) {
1038	case PP_SCLK:
1039		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency, &now);
1040		if (ret)
1041			return ret;
1042
1043	/* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */
1044		if (now == data->gfx_max_freq_limit/100)
1045			i = 2;
1046		else if (now == data->gfx_min_freq_limit/100)
1047			i = 0;
1048		else
1049			i = 1;
1050
1051		size += sprintf(buf + size, "0: %uMhz %s\n",
1052					data->gfx_min_freq_limit/100,
1053					i == 0 ? "*" : "");
1054		size += sprintf(buf + size, "1: %uMhz %s\n",
1055					i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK,
1056					i == 1 ? "*" : "");
1057		size += sprintf(buf + size, "2: %uMhz %s\n",
1058					data->gfx_max_freq_limit/100,
1059					i == 2 ? "*" : "");
1060		break;
1061	case PP_MCLK:
1062		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &now);
1063		if (ret)
1064			return ret;
1065
1066		for (i = 0; i < mclk_table->count; i++)
1067			size += sprintf(buf + size, "%d: %uMhz %s\n",
1068					i,
1069					mclk_table->entries[i].clk / 100,
1070					((mclk_table->entries[i].clk / 100)
1071					 == now) ? "*" : "");
1072		break;
1073	case OD_SCLK:
1074		if (hwmgr->od_enabled) {
1075			ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &min_freq);
1076			if (ret)
1077				return ret;
1078			ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &max_freq);
1079			if (ret)
1080				return ret;
1081
1082			size += sprintf(buf + size, "%s:\n", "OD_SCLK");
1083			size += sprintf(buf + size, "0: %10uMhz\n",
1084			(data->gfx_actual_soft_min_freq > 0) ? data->gfx_actual_soft_min_freq : min_freq);
1085			size += sprintf(buf + size, "1: %10uMhz\n",
1086			(data->gfx_actual_soft_max_freq > 0) ? data->gfx_actual_soft_max_freq : max_freq);
1087		}
1088		break;
1089	case OD_RANGE:
1090		if (hwmgr->od_enabled) {
1091			ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &min_freq);
1092			if (ret)
1093				return ret;
1094			ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &max_freq);
1095			if (ret)
1096				return ret;
1097
1098			size += sprintf(buf + size, "%s:\n", "OD_RANGE");
1099			size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n",
1100				min_freq, max_freq);
1101		}
1102		break;
1103	default:
1104		break;
1105	}
1106
1107	return size;
1108}
1109
1110static int smu10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
1111				PHM_PerformanceLevelDesignation designation, uint32_t index,
1112				PHM_PerformanceLevel *level)
1113{
1114	struct smu10_hwmgr *data;
1115
1116	if (level == NULL || hwmgr == NULL || state == NULL)
1117		return -EINVAL;
1118
1119	data = (struct smu10_hwmgr *)(hwmgr->backend);
1120
1121	if (index == 0) {
1122		level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
1123		level->coreClock = data->gfx_min_freq_limit;
1124	} else {
1125		level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[
1126			data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
1127		level->coreClock = data->gfx_max_freq_limit;
1128	}
1129
1130	level->nonLocalMemoryFreq = 0;
1131	level->nonLocalMemoryWidth = 0;
1132
1133	return 0;
1134}
1135
1136static int smu10_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr,
1137	const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
1138{
1139	const struct smu10_power_state *ps = cast_const_smu10_ps(state);
1140
1141	clock_info->min_eng_clk = ps->levels[0].engine_clock / (1 << (ps->levels[0].ss_divider_index));
1142	clock_info->max_eng_clk = ps->levels[ps->level - 1].engine_clock / (1 << (ps->levels[ps->level - 1].ss_divider_index));
1143
1144	return 0;
1145}
1146
1147#define MEM_FREQ_LOW_LATENCY        25000
1148#define MEM_FREQ_HIGH_LATENCY       80000
1149#define MEM_LATENCY_HIGH            245
1150#define MEM_LATENCY_LOW             35
1151#define MEM_LATENCY_ERR             0xFFFF
1152
1153
1154static uint32_t smu10_get_mem_latency(struct pp_hwmgr *hwmgr,
1155		uint32_t clock)
1156{
1157	if (clock >= MEM_FREQ_LOW_LATENCY &&
1158			clock < MEM_FREQ_HIGH_LATENCY)
1159		return MEM_LATENCY_HIGH;
1160	else if (clock >= MEM_FREQ_HIGH_LATENCY)
1161		return MEM_LATENCY_LOW;
1162	else
1163		return MEM_LATENCY_ERR;
1164}
1165
1166static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
1167		enum amd_pp_clock_type type,
1168		struct pp_clock_levels_with_latency *clocks)
1169{
1170	uint32_t i;
1171	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1172	struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
1173	struct smu10_voltage_dependency_table *pclk_vol_table;
1174	bool latency_required = false;
1175
1176	if (pinfo == NULL)
1177		return -EINVAL;
1178
1179	switch (type) {
1180	case amd_pp_mem_clock:
1181		pclk_vol_table = pinfo->vdd_dep_on_mclk;
1182		latency_required = true;
1183		break;
1184	case amd_pp_f_clock:
1185		pclk_vol_table = pinfo->vdd_dep_on_fclk;
1186		latency_required = true;
1187		break;
1188	case amd_pp_dcf_clock:
1189		pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
1190		break;
1191	case amd_pp_disp_clock:
1192		pclk_vol_table = pinfo->vdd_dep_on_dispclk;
1193		break;
1194	case amd_pp_phy_clock:
1195		pclk_vol_table = pinfo->vdd_dep_on_phyclk;
1196		break;
1197	case amd_pp_dpp_clock:
1198		pclk_vol_table = pinfo->vdd_dep_on_dppclk;
1199		break;
1200	default:
1201		return -EINVAL;
1202	}
1203
1204	if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
1205		return -EINVAL;
1206
1207	clocks->num_levels = 0;
1208	for (i = 0; i < pclk_vol_table->count; i++) {
1209		if (pclk_vol_table->entries[i].clk) {
1210			clocks->data[clocks->num_levels].clocks_in_khz =
1211				pclk_vol_table->entries[i].clk * 10;
1212			clocks->data[clocks->num_levels].latency_in_us = latency_required ?
1213				smu10_get_mem_latency(hwmgr,
1214						      pclk_vol_table->entries[i].clk) :
1215				0;
1216			clocks->num_levels++;
1217		}
1218	}
1219
1220	return 0;
1221}
1222
1223static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
1224		enum amd_pp_clock_type type,
1225		struct pp_clock_levels_with_voltage *clocks)
1226{
1227	uint32_t i;
1228	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1229	struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
1230	struct smu10_voltage_dependency_table *pclk_vol_table = NULL;
1231
1232	if (pinfo == NULL)
1233		return -EINVAL;
1234
1235	switch (type) {
1236	case amd_pp_mem_clock:
1237		pclk_vol_table = pinfo->vdd_dep_on_mclk;
1238		break;
1239	case amd_pp_f_clock:
1240		pclk_vol_table = pinfo->vdd_dep_on_fclk;
1241		break;
1242	case amd_pp_dcf_clock:
1243		pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
1244		break;
1245	case amd_pp_soc_clock:
1246		pclk_vol_table = pinfo->vdd_dep_on_socclk;
1247		break;
1248	case amd_pp_disp_clock:
1249		pclk_vol_table = pinfo->vdd_dep_on_dispclk;
1250		break;
1251	case amd_pp_phy_clock:
1252		pclk_vol_table = pinfo->vdd_dep_on_phyclk;
1253		break;
1254	default:
1255		return -EINVAL;
1256	}
1257
1258	if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
1259		return -EINVAL;
1260
1261	clocks->num_levels = 0;
1262	for (i = 0; i < pclk_vol_table->count; i++) {
1263		if (pclk_vol_table->entries[i].clk) {
1264			clocks->data[clocks->num_levels].clocks_in_khz = pclk_vol_table->entries[i].clk  * 10;
1265			clocks->data[clocks->num_levels].voltage_in_mv = pclk_vol_table->entries[i].vol;
1266			clocks->num_levels++;
1267		}
1268	}
1269
1270	return 0;
1271}
1272
1273
1274
1275static int smu10_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
1276{
1277	clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */
1278	return 0;
1279}
1280
1281static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
1282{
1283	struct amdgpu_device *adev = hwmgr->adev;
1284	uint32_t reg_value = RREG32_SOC15(THM, 0, mmTHM_TCON_CUR_TMP);
1285	int cur_temp =
1286		(reg_value & THM_TCON_CUR_TMP__CUR_TEMP_MASK) >> THM_TCON_CUR_TMP__CUR_TEMP__SHIFT;
1287
1288	if (cur_temp & THM_TCON_CUR_TMP__CUR_TEMP_RANGE_SEL_MASK)
1289		cur_temp = ((cur_temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1290	else
1291		cur_temp = (cur_temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1292
1293	return cur_temp;
1294}
1295
1296static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
1297			  void *value, int *size)
1298{
1299	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1300	struct amdgpu_device *adev = hwmgr->adev;
1301	uint32_t sclk, mclk, activity_percent;
1302	bool has_gfx_busy;
1303	int ret = 0;
1304
1305	/* GetGfxBusy support was added on RV SMU FW 30.85.00 and PCO 4.30.59 */
1306	if ((adev->apu_flags & AMD_APU_IS_PICASSO) &&
1307	    (hwmgr->smu_version >= 0x41e3b))
1308		has_gfx_busy = true;
1309	else if ((adev->apu_flags & AMD_APU_IS_RAVEN) &&
1310		 (hwmgr->smu_version >= 0x1e5500))
1311		has_gfx_busy = true;
1312	else
1313		has_gfx_busy = false;
1314
1315	switch (idx) {
1316	case AMDGPU_PP_SENSOR_GFX_SCLK:
1317		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency, &sclk);
1318		if (ret)
1319			break;
1320			/* in units of 10KHZ */
1321		*((uint32_t *)value) = sclk * 100;
1322		*size = 4;
1323		break;
1324	case AMDGPU_PP_SENSOR_GFX_MCLK:
1325		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &mclk);
1326		if (ret)
1327			break;
1328			/* in units of 10KHZ */
1329		*((uint32_t *)value) = mclk * 100;
1330		*size = 4;
1331		break;
1332	case AMDGPU_PP_SENSOR_GPU_TEMP:
1333		*((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr);
1334		break;
1335	case AMDGPU_PP_SENSOR_VCN_POWER_STATE:
1336		*(uint32_t *)value =  smu10_data->vcn_power_gated ? 0 : 1;
1337		*size = 4;
1338		break;
1339	case AMDGPU_PP_SENSOR_GPU_LOAD:
1340		if (!has_gfx_busy)
1341			ret = -EOPNOTSUPP;
1342		else {
1343			ret = smum_send_msg_to_smc(hwmgr,
1344						   PPSMC_MSG_GetGfxBusy,
1345						   &activity_percent);
1346			if (!ret)
1347				*((uint32_t *)value) = min(activity_percent, (u32)100);
1348			else
1349				ret = -EIO;
1350		}
1351		break;
1352	default:
1353		ret = -EOPNOTSUPP;
1354		break;
1355	}
1356
1357	return ret;
1358}
1359
1360static int smu10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
1361		void *clock_ranges)
1362{
1363	struct smu10_hwmgr *data = hwmgr->backend;
1364	struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges;
1365	Watermarks_t *table = &(data->water_marks_table);
1366	struct amdgpu_device *adev = hwmgr->adev;
1367	int i;
1368
1369	smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges);
1370
1371	if (adev->apu_flags & AMD_APU_IS_RAVEN2) {
1372		for (i = 0; i < NUM_WM_RANGES; i++)
1373			table->WatermarkRow[WM_DCFCLK][i].WmType = (uint8_t)0;
1374
1375		for (i = 0; i < NUM_WM_RANGES; i++)
1376			table->WatermarkRow[WM_SOCCLK][i].WmType = (uint8_t)0;
1377	}
1378
1379	smum_smc_table_manager(hwmgr, (uint8_t *)table, (uint16_t)SMU10_WMTABLE, false);
1380	data->water_marks_exist = true;
1381	return 0;
1382}
1383
1384static int smu10_smus_notify_pwe(struct pp_hwmgr *hwmgr)
1385{
1386
1387	return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SetRccPfcPmeRestoreRegister, NULL);
1388}
1389
1390static int smu10_powergate_mmhub(struct pp_hwmgr *hwmgr)
1391{
1392	return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub, NULL);
1393}
1394
1395static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate)
1396{
1397	if (gate)
1398		return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerDownSdma, NULL);
1399	else
1400		return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerUpSdma, NULL);
1401}
1402
1403static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate)
1404{
1405	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1406
1407	if (bgate) {
1408		amdgpu_device_ip_set_powergating_state(hwmgr->adev,
1409						AMD_IP_BLOCK_TYPE_VCN,
1410						AMD_PG_STATE_GATE);
1411		smum_send_msg_to_smc_with_parameter(hwmgr,
1412					PPSMC_MSG_PowerDownVcn, 0, NULL);
1413		smu10_data->vcn_power_gated = true;
1414	} else {
1415		smum_send_msg_to_smc_with_parameter(hwmgr,
1416						PPSMC_MSG_PowerUpVcn, 0, NULL);
1417		amdgpu_device_ip_set_powergating_state(hwmgr->adev,
1418						AMD_IP_BLOCK_TYPE_VCN,
1419						AMD_PG_STATE_UNGATE);
1420		smu10_data->vcn_power_gated = false;
1421	}
1422}
1423
1424static int conv_power_profile_to_pplib_workload(int power_profile)
1425{
1426	int pplib_workload = 0;
1427
1428	switch (power_profile) {
1429	case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
1430		pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
1431		break;
1432	case PP_SMC_POWER_PROFILE_VIDEO:
1433		pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT;
1434		break;
1435	case PP_SMC_POWER_PROFILE_VR:
1436		pplib_workload = WORKLOAD_PPLIB_VR_BIT;
1437		break;
1438	case PP_SMC_POWER_PROFILE_COMPUTE:
1439		pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT;
1440		break;
1441	case PP_SMC_POWER_PROFILE_CUSTOM:
1442		pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT;
1443		break;
1444	}
1445
1446	return pplib_workload;
1447}
1448
1449static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
1450{
1451	uint32_t i, size = 0;
1452	static const uint8_t
1453		profile_mode_setting[6][4] = {{70, 60, 0, 0,},
1454						{70, 60, 1, 3,},
1455						{90, 60, 0, 0,},
1456						{70, 60, 0, 0,},
1457						{70, 90, 0, 0,},
1458						{30, 60, 0, 6,},
1459						};
1460	static const char *title[6] = {"NUM",
1461			"MODE_NAME",
1462			"BUSY_SET_POINT",
1463			"FPS",
1464			"USE_RLC_BUSY",
1465			"MIN_ACTIVE_LEVEL"};
1466
1467	if (!buf)
1468		return -EINVAL;
1469
1470	phm_get_sysfs_buf(&buf, &size);
1471
1472	size += sysfs_emit_at(buf, size, "%s %16s %s %s %s %s\n", title[0],
1473			title[1], title[2], title[3], title[4], title[5]);
1474
1475	for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++)
1476		size += sysfs_emit_at(buf, size, "%3d %14s%s: %14d %3d %10d %14d\n",
1477			i, amdgpu_pp_profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
1478			profile_mode_setting[i][0], profile_mode_setting[i][1],
1479			profile_mode_setting[i][2], profile_mode_setting[i][3]);
1480
1481	return size;
1482}
1483
1484static bool smu10_is_raven1_refresh(struct pp_hwmgr *hwmgr)
1485{
1486	struct amdgpu_device *adev = hwmgr->adev;
1487	if ((adev->apu_flags & AMD_APU_IS_RAVEN) &&
1488	    (hwmgr->smu_version >= 0x41e2b))
1489		return true;
1490	else
1491		return false;
1492}
1493
1494static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
1495{
1496	int workload_type = 0;
1497	int result = 0;
1498
1499	if (input[size] > PP_SMC_POWER_PROFILE_COMPUTE) {
1500		pr_err("Invalid power profile mode %ld\n", input[size]);
1501		return -EINVAL;
1502	}
1503	if (hwmgr->power_profile_mode == input[size])
1504		return 0;
1505
1506	/* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
1507	workload_type =
1508		conv_power_profile_to_pplib_workload(input[size]);
1509	if (workload_type &&
1510	    smu10_is_raven1_refresh(hwmgr) &&
1511	    !hwmgr->gfxoff_state_changed_by_workload) {
1512		smu10_gfx_off_control(hwmgr, false);
1513		hwmgr->gfxoff_state_changed_by_workload = true;
1514	}
1515	result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ActiveProcessNotify,
1516						1 << workload_type,
1517						NULL);
1518	if (!result)
1519		hwmgr->power_profile_mode = input[size];
1520	if (workload_type && hwmgr->gfxoff_state_changed_by_workload) {
1521		smu10_gfx_off_control(hwmgr, true);
1522		hwmgr->gfxoff_state_changed_by_workload = false;
1523	}
1524
1525	return 0;
1526}
1527
1528static int smu10_asic_reset(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode)
1529{
1530	return smum_send_msg_to_smc_with_parameter(hwmgr,
1531						   PPSMC_MSG_DeviceDriverReset,
1532						   mode,
1533						   NULL);
1534}
1535
1536static int smu10_set_fine_grain_clk_vol(struct pp_hwmgr *hwmgr,
1537					enum PP_OD_DPM_TABLE_COMMAND type,
1538					long *input, uint32_t size)
1539{
1540	uint32_t min_freq, max_freq = 0;
1541	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
1542	int ret = 0;
1543
1544	if (!hwmgr->od_enabled) {
1545		pr_err("Fine grain not support\n");
1546		return -EINVAL;
1547	}
1548
1549	if (!smu10_data->fine_grain_enabled) {
1550		pr_err("pp_od_clk_voltage is not accessible if power_dpm_force_performance_level is not in manual mode!\n");
1551		return -EINVAL;
1552	}
1553
1554	if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
1555		if (size != 2) {
1556			pr_err("Input parameter number not correct\n");
1557			return -EINVAL;
1558		}
1559
1560		if (input[0] == 0) {
1561			ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &min_freq);
1562			if (ret)
1563				return ret;
1564
1565			if (input[1] < min_freq) {
1566				pr_err("Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
1567					input[1], min_freq);
1568				return -EINVAL;
1569			}
1570			smu10_data->gfx_actual_soft_min_freq = input[1];
1571		} else if (input[0] == 1) {
1572			ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &max_freq);
1573			if (ret)
1574				return ret;
1575
1576			if (input[1] > max_freq) {
1577				pr_err("Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
1578					input[1], max_freq);
1579				return -EINVAL;
1580			}
1581			smu10_data->gfx_actual_soft_max_freq = input[1];
1582		} else {
1583			return -EINVAL;
1584		}
1585	} else if (type == PP_OD_RESTORE_DEFAULT_TABLE) {
1586		if (size != 0) {
1587			pr_err("Input parameter number not correct\n");
1588			return -EINVAL;
1589		}
1590		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &min_freq);
1591		if (ret)
1592			return ret;
1593		smu10_data->gfx_actual_soft_min_freq = min_freq;
1594
1595		ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &max_freq);
1596		if (ret)
1597			return ret;
1598
1599		smu10_data->gfx_actual_soft_max_freq = max_freq;
1600	} else if (type == PP_OD_COMMIT_DPM_TABLE) {
1601		if (size != 0) {
1602			pr_err("Input parameter number not correct\n");
1603			return -EINVAL;
1604		}
1605
1606		if (smu10_data->gfx_actual_soft_min_freq > smu10_data->gfx_actual_soft_max_freq) {
1607			pr_err("The setting minimum sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
1608					smu10_data->gfx_actual_soft_min_freq, smu10_data->gfx_actual_soft_max_freq);
1609			return -EINVAL;
1610		}
1611
1612		ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1613					PPSMC_MSG_SetHardMinGfxClk,
1614					smu10_data->gfx_actual_soft_min_freq,
1615					NULL);
1616		if (ret)
1617			return ret;
1618
1619		ret = smum_send_msg_to_smc_with_parameter(hwmgr,
1620					PPSMC_MSG_SetSoftMaxGfxClk,
1621					smu10_data->gfx_actual_soft_max_freq,
1622					NULL);
1623		if (ret)
1624			return ret;
1625	} else {
1626		return -EINVAL;
1627	}
1628
1629	return 0;
1630}
1631
1632static int smu10_gfx_state_change(struct pp_hwmgr *hwmgr, uint32_t state)
1633{
1634	smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GpuChangeState, state, NULL);
1635
1636	return 0;
1637}
1638
1639static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
1640	.backend_init = smu10_hwmgr_backend_init,
1641	.backend_fini = smu10_hwmgr_backend_fini,
1642	.apply_state_adjust_rules = smu10_apply_state_adjust_rules,
1643	.force_dpm_level = smu10_dpm_force_dpm_level,
1644	.get_power_state_size = smu10_get_power_state_size,
1645	.powergate_uvd = smu10_powergate_vcn,
1646	.powergate_vce = NULL,
1647	.get_mclk = smu10_dpm_get_mclk,
1648	.get_sclk = smu10_dpm_get_sclk,
1649	.patch_boot_state = smu10_dpm_patch_boot_state,
1650	.get_pp_table_entry = smu10_dpm_get_pp_table_entry,
1651	.get_num_of_pp_table_entries = smu10_dpm_get_num_of_pp_table_entries,
1652	.set_cpu_power_state = smu10_set_cpu_power_state,
1653	.store_cc6_data = smu10_store_cc6_data,
1654	.force_clock_level = smu10_force_clock_level,
1655	.print_clock_levels = smu10_print_clock_levels,
1656	.get_dal_power_level = smu10_get_dal_power_level,
1657	.get_performance_level = smu10_get_performance_level,
1658	.get_current_shallow_sleep_clocks = smu10_get_current_shallow_sleep_clocks,
1659	.get_clock_by_type_with_latency = smu10_get_clock_by_type_with_latency,
1660	.get_clock_by_type_with_voltage = smu10_get_clock_by_type_with_voltage,
1661	.set_watermarks_for_clocks_ranges = smu10_set_watermarks_for_clocks_ranges,
1662	.get_max_high_clocks = smu10_get_max_high_clocks,
1663	.read_sensor = smu10_read_sensor,
1664	.set_active_display_count = smu10_set_active_display_count,
1665	.set_min_deep_sleep_dcefclk = smu10_set_min_deep_sleep_dcefclk,
1666	.dynamic_state_management_enable = smu10_enable_dpm_tasks,
1667	.power_off_asic = smu10_power_off_asic,
1668	.asic_setup = smu10_setup_asic_task,
1669	.power_state_set = smu10_set_power_state_tasks,
1670	.dynamic_state_management_disable = smu10_disable_dpm_tasks,
1671	.powergate_mmhub = smu10_powergate_mmhub,
1672	.smus_notify_pwe = smu10_smus_notify_pwe,
1673	.display_clock_voltage_request = smu10_display_clock_voltage_request,
1674	.powergate_gfx = smu10_gfx_off_control,
1675	.powergate_sdma = smu10_powergate_sdma,
1676	.set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq,
1677	.set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq,
1678	.set_hard_min_gfxclk_by_freq = smu10_set_hard_min_gfxclk_by_freq,
1679	.set_soft_max_gfxclk_by_freq = smu10_set_soft_max_gfxclk_by_freq,
1680	.get_power_profile_mode = smu10_get_power_profile_mode,
1681	.set_power_profile_mode = smu10_set_power_profile_mode,
1682	.asic_reset = smu10_asic_reset,
1683	.set_fine_grain_clk_vol = smu10_set_fine_grain_clk_vol,
1684	.gfx_state_change = smu10_gfx_state_change,
1685};
1686
1687int smu10_init_function_pointers(struct pp_hwmgr *hwmgr)
1688{
1689	hwmgr->hwmgr_func = &smu10_hwmgr_funcs;
1690	hwmgr->pptable_func = &pptable_funcs;
1691	return 0;
1692}
~/ Read-only file preview.