]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
drm/amdkfd: Improve multiple SDMA queues support per process
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / powerplay / hwmgr / cz_hwmgr.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 "smu/smu_8_0_d.h"
32 #include "smu8_fusion.h"
33 #include "smu/smu_8_0_sh_mask.h"
34 #include "smumgr.h"
35 #include "hwmgr.h"
36 #include "hardwaremanager.h"
37 #include "cz_ppsmc.h"
38 #include "cz_hwmgr.h"
39 #include "power_state.h"
40 #include "cz_clockpowergating.h"
41
42 #define ixSMUSVI_NB_CURRENTVID 0xD8230044
43 #define CURRENT_NB_VID_MASK 0xff000000
44 #define CURRENT_NB_VID__SHIFT 24
45 #define ixSMUSVI_GFX_CURRENTVID 0xD8230048
46 #define CURRENT_GFX_VID_MASK 0xff000000
47 #define CURRENT_GFX_VID__SHIFT 24
48
49 static const unsigned long PhwCz_Magic = (unsigned long) PHM_Cz_Magic;
50
51 static struct cz_power_state *cast_PhwCzPowerState(struct pp_hw_power_state *hw_ps)
52 {
53 if (PhwCz_Magic != hw_ps->magic)
54 return NULL;
55
56 return (struct cz_power_state *)hw_ps;
57 }
58
59 static const struct cz_power_state *cast_const_PhwCzPowerState(
60 const struct pp_hw_power_state *hw_ps)
61 {
62 if (PhwCz_Magic != hw_ps->magic)
63 return NULL;
64
65 return (struct cz_power_state *)hw_ps;
66 }
67
68 static uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr,
69 uint32_t clock, uint32_t msg)
70 {
71 int i = 0;
72 struct phm_vce_clock_voltage_dependency_table *ptable =
73 hwmgr->dyn_state.vce_clock_voltage_dependency_table;
74
75 switch (msg) {
76 case PPSMC_MSG_SetEclkSoftMin:
77 case PPSMC_MSG_SetEclkHardMin:
78 for (i = 0; i < (int)ptable->count; i++) {
79 if (clock <= ptable->entries[i].ecclk)
80 break;
81 }
82 break;
83
84 case PPSMC_MSG_SetEclkSoftMax:
85 case PPSMC_MSG_SetEclkHardMax:
86 for (i = ptable->count - 1; i >= 0; i--) {
87 if (clock >= ptable->entries[i].ecclk)
88 break;
89 }
90 break;
91
92 default:
93 break;
94 }
95
96 return i;
97 }
98
99 static uint32_t cz_get_sclk_level(struct pp_hwmgr *hwmgr,
100 uint32_t clock, uint32_t msg)
101 {
102 int i = 0;
103 struct phm_clock_voltage_dependency_table *table =
104 hwmgr->dyn_state.vddc_dependency_on_sclk;
105
106 switch (msg) {
107 case PPSMC_MSG_SetSclkSoftMin:
108 case PPSMC_MSG_SetSclkHardMin:
109 for (i = 0; i < (int)table->count; i++) {
110 if (clock <= table->entries[i].clk)
111 break;
112 }
113 break;
114
115 case PPSMC_MSG_SetSclkSoftMax:
116 case PPSMC_MSG_SetSclkHardMax:
117 for (i = table->count - 1; i >= 0; i--) {
118 if (clock >= table->entries[i].clk)
119 break;
120 }
121 break;
122
123 default:
124 break;
125 }
126 return i;
127 }
128
129 static uint32_t cz_get_uvd_level(struct pp_hwmgr *hwmgr,
130 uint32_t clock, uint32_t msg)
131 {
132 int i = 0;
133 struct phm_uvd_clock_voltage_dependency_table *ptable =
134 hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
135
136 switch (msg) {
137 case PPSMC_MSG_SetUvdSoftMin:
138 case PPSMC_MSG_SetUvdHardMin:
139 for (i = 0; i < (int)ptable->count; i++) {
140 if (clock <= ptable->entries[i].vclk)
141 break;
142 }
143 break;
144
145 case PPSMC_MSG_SetUvdSoftMax:
146 case PPSMC_MSG_SetUvdHardMax:
147 for (i = ptable->count - 1; i >= 0; i--) {
148 if (clock >= ptable->entries[i].vclk)
149 break;
150 }
151 break;
152
153 default:
154 break;
155 }
156
157 return i;
158 }
159
160 static uint32_t cz_get_max_sclk_level(struct pp_hwmgr *hwmgr)
161 {
162 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
163
164 if (cz_hwmgr->max_sclk_level == 0) {
165 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxSclkLevel);
166 cz_hwmgr->max_sclk_level = smum_get_argument(hwmgr) + 1;
167 }
168
169 return cz_hwmgr->max_sclk_level;
170 }
171
172 static int cz_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
173 {
174 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
175 uint32_t i;
176 struct cgs_system_info sys_info = {0};
177 int result;
178
179 cz_hwmgr->gfx_ramp_step = 256*25/100;
180 cz_hwmgr->gfx_ramp_delay = 1; /* by default, we delay 1us */
181
182 for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++)
183 cz_hwmgr->activity_target[i] = CZ_AT_DFLT;
184
185 cz_hwmgr->mgcg_cgtt_local0 = 0x00000000;
186 cz_hwmgr->mgcg_cgtt_local1 = 0x00000000;
187 cz_hwmgr->clock_slow_down_freq = 25000;
188 cz_hwmgr->skip_clock_slow_down = 1;
189 cz_hwmgr->enable_nb_ps_policy = 1; /* disable until UNB is ready, Enabled */
190 cz_hwmgr->voltage_drop_in_dce_power_gating = 0; /* disable until fully verified */
191 cz_hwmgr->voting_rights_clients = 0x00C00033;
192 cz_hwmgr->static_screen_threshold = 8;
193 cz_hwmgr->ddi_power_gating_disabled = 0;
194 cz_hwmgr->bapm_enabled = 1;
195 cz_hwmgr->voltage_drop_threshold = 0;
196 cz_hwmgr->gfx_power_gating_threshold = 500;
197 cz_hwmgr->vce_slow_sclk_threshold = 20000;
198 cz_hwmgr->dce_slow_sclk_threshold = 30000;
199 cz_hwmgr->disable_driver_thermal_policy = 1;
200 cz_hwmgr->disable_nb_ps3_in_battery = 0;
201
202 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
203 PHM_PlatformCaps_ABM);
204
205 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
206 PHM_PlatformCaps_NonABMSupportInPPLib);
207
208 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
209 PHM_PlatformCaps_DynamicM3Arbiter);
210
211 cz_hwmgr->override_dynamic_mgpg = 1;
212
213 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
214 PHM_PlatformCaps_DynamicPatchPowerState);
215
216 cz_hwmgr->thermal_auto_throttling_treshold = 0;
217 cz_hwmgr->tdr_clock = 0;
218 cz_hwmgr->disable_gfx_power_gating_in_uvd = 0;
219
220 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
221 PHM_PlatformCaps_DynamicUVDState);
222
223 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
224 PHM_PlatformCaps_UVDDPM);
225 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
226 PHM_PlatformCaps_VCEDPM);
227
228 cz_hwmgr->cc6_settings.cpu_cc6_disable = false;
229 cz_hwmgr->cc6_settings.cpu_pstate_disable = false;
230 cz_hwmgr->cc6_settings.nb_pstate_switch_disable = false;
231 cz_hwmgr->cc6_settings.cpu_pstate_separation_time = 0;
232
233 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
234 PHM_PlatformCaps_DisableVoltageIsland);
235
236 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
237 PHM_PlatformCaps_UVDPowerGating);
238 phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
239 PHM_PlatformCaps_VCEPowerGating);
240 sys_info.size = sizeof(struct cgs_system_info);
241 sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
242 result = cgs_query_system_info(hwmgr->device, &sys_info);
243 if (!result) {
244 if (sys_info.value & AMD_PG_SUPPORT_UVD)
245 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
246 PHM_PlatformCaps_UVDPowerGating);
247 if (sys_info.value & AMD_PG_SUPPORT_VCE)
248 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
249 PHM_PlatformCaps_VCEPowerGating);
250 }
251
252 return 0;
253 }
254
255 static uint32_t cz_convert_8Bit_index_to_voltage(
256 struct pp_hwmgr *hwmgr, uint16_t voltage)
257 {
258 return 6200 - (voltage * 25);
259 }
260
261 static int cz_construct_max_power_limits_table(struct pp_hwmgr *hwmgr,
262 struct phm_clock_and_voltage_limits *table)
263 {
264 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)hwmgr->backend;
265 struct cz_sys_info *sys_info = &cz_hwmgr->sys_info;
266 struct phm_clock_voltage_dependency_table *dep_table =
267 hwmgr->dyn_state.vddc_dependency_on_sclk;
268
269 if (dep_table->count > 0) {
270 table->sclk = dep_table->entries[dep_table->count-1].clk;
271 table->vddc = cz_convert_8Bit_index_to_voltage(hwmgr,
272 (uint16_t)dep_table->entries[dep_table->count-1].v);
273 }
274 table->mclk = sys_info->nbp_memory_clock[0];
275 return 0;
276 }
277
278 static int cz_init_dynamic_state_adjustment_rule_settings(
279 struct pp_hwmgr *hwmgr,
280 ATOM_CLK_VOLT_CAPABILITY *disp_voltage_table)
281 {
282 uint32_t table_size =
283 sizeof(struct phm_clock_voltage_dependency_table) +
284 (7 * sizeof(struct phm_clock_voltage_dependency_record));
285
286 struct phm_clock_voltage_dependency_table *table_clk_vlt =
287 kzalloc(table_size, GFP_KERNEL);
288
289 if (NULL == table_clk_vlt) {
290 pr_err("Can not allocate memory!\n");
291 return -ENOMEM;
292 }
293
294 table_clk_vlt->count = 8;
295 table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0;
296 table_clk_vlt->entries[0].v = 0;
297 table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1;
298 table_clk_vlt->entries[1].v = 1;
299 table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2;
300 table_clk_vlt->entries[2].v = 2;
301 table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3;
302 table_clk_vlt->entries[3].v = 3;
303 table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4;
304 table_clk_vlt->entries[4].v = 4;
305 table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5;
306 table_clk_vlt->entries[5].v = 5;
307 table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6;
308 table_clk_vlt->entries[6].v = 6;
309 table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7;
310 table_clk_vlt->entries[7].v = 7;
311 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
312
313 return 0;
314 }
315
316 static int cz_get_system_info_data(struct pp_hwmgr *hwmgr)
317 {
318 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)hwmgr->backend;
319 ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info = NULL;
320 uint32_t i;
321 int result = 0;
322 uint8_t frev, crev;
323 uint16_t size;
324
325 info = (ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *) cgs_atom_get_data_table(
326 hwmgr->device,
327 GetIndexIntoMasterTable(DATA, IntegratedSystemInfo),
328 &size, &frev, &crev);
329
330 if (crev != 9) {
331 pr_err("Unsupported IGP table: %d %d\n", frev, crev);
332 return -EINVAL;
333 }
334
335 if (info == NULL) {
336 pr_err("Could not retrieve the Integrated System Info Table!\n");
337 return -EINVAL;
338 }
339
340 cz_hwmgr->sys_info.bootup_uma_clock =
341 le32_to_cpu(info->ulBootUpUMAClock);
342
343 cz_hwmgr->sys_info.bootup_engine_clock =
344 le32_to_cpu(info->ulBootUpEngineClock);
345
346 cz_hwmgr->sys_info.dentist_vco_freq =
347 le32_to_cpu(info->ulDentistVCOFreq);
348
349 cz_hwmgr->sys_info.system_config =
350 le32_to_cpu(info->ulSystemConfig);
351
352 cz_hwmgr->sys_info.bootup_nb_voltage_index =
353 le16_to_cpu(info->usBootUpNBVoltage);
354
355 cz_hwmgr->sys_info.htc_hyst_lmt =
356 (info->ucHtcHystLmt == 0) ? 5 : info->ucHtcHystLmt;
357
358 cz_hwmgr->sys_info.htc_tmp_lmt =
359 (info->ucHtcTmpLmt == 0) ? 203 : info->ucHtcTmpLmt;
360
361 if (cz_hwmgr->sys_info.htc_tmp_lmt <=
362 cz_hwmgr->sys_info.htc_hyst_lmt) {
363 pr_err("The htcTmpLmt should be larger than htcHystLmt.\n");
364 return -EINVAL;
365 }
366
367 cz_hwmgr->sys_info.nb_dpm_enable =
368 cz_hwmgr->enable_nb_ps_policy &&
369 (le32_to_cpu(info->ulSystemConfig) >> 3 & 0x1);
370
371 for (i = 0; i < CZ_NUM_NBPSTATES; i++) {
372 if (i < CZ_NUM_NBPMEMORYCLOCK) {
373 cz_hwmgr->sys_info.nbp_memory_clock[i] =
374 le32_to_cpu(info->ulNbpStateMemclkFreq[i]);
375 }
376 cz_hwmgr->sys_info.nbp_n_clock[i] =
377 le32_to_cpu(info->ulNbpStateNClkFreq[i]);
378 }
379
380 for (i = 0; i < MAX_DISPLAY_CLOCK_LEVEL; i++) {
381 cz_hwmgr->sys_info.display_clock[i] =
382 le32_to_cpu(info->sDispClkVoltageMapping[i].ulMaximumSupportedCLK);
383 }
384
385 /* Here use 4 levels, make sure not exceed */
386 for (i = 0; i < CZ_NUM_NBPSTATES; i++) {
387 cz_hwmgr->sys_info.nbp_voltage_index[i] =
388 le16_to_cpu(info->usNBPStateVoltage[i]);
389 }
390
391 if (!cz_hwmgr->sys_info.nb_dpm_enable) {
392 for (i = 1; i < CZ_NUM_NBPSTATES; i++) {
393 if (i < CZ_NUM_NBPMEMORYCLOCK) {
394 cz_hwmgr->sys_info.nbp_memory_clock[i] =
395 cz_hwmgr->sys_info.nbp_memory_clock[0];
396 }
397 cz_hwmgr->sys_info.nbp_n_clock[i] =
398 cz_hwmgr->sys_info.nbp_n_clock[0];
399 cz_hwmgr->sys_info.nbp_voltage_index[i] =
400 cz_hwmgr->sys_info.nbp_voltage_index[0];
401 }
402 }
403
404 if (le32_to_cpu(info->ulGPUCapInfo) &
405 SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) {
406 phm_cap_set(hwmgr->platform_descriptor.platformCaps,
407 PHM_PlatformCaps_EnableDFSBypass);
408 }
409
410 cz_hwmgr->sys_info.uma_channel_number = info->ucUMAChannelNumber;
411
412 cz_construct_max_power_limits_table (hwmgr,
413 &hwmgr->dyn_state.max_clock_voltage_on_ac);
414
415 cz_init_dynamic_state_adjustment_rule_settings(hwmgr,
416 &info->sDISPCLK_Voltage[0]);
417
418 return result;
419 }
420
421 static int cz_construct_boot_state(struct pp_hwmgr *hwmgr)
422 {
423 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
424
425 cz_hwmgr->boot_power_level.engineClock =
426 cz_hwmgr->sys_info.bootup_engine_clock;
427
428 cz_hwmgr->boot_power_level.vddcIndex =
429 (uint8_t)cz_hwmgr->sys_info.bootup_nb_voltage_index;
430
431 cz_hwmgr->boot_power_level.dsDividerIndex = 0;
432 cz_hwmgr->boot_power_level.ssDividerIndex = 0;
433 cz_hwmgr->boot_power_level.allowGnbSlow = 1;
434 cz_hwmgr->boot_power_level.forceNBPstate = 0;
435 cz_hwmgr->boot_power_level.hysteresis_up = 0;
436 cz_hwmgr->boot_power_level.numSIMDToPowerDown = 0;
437 cz_hwmgr->boot_power_level.display_wm = 0;
438 cz_hwmgr->boot_power_level.vce_wm = 0;
439
440 return 0;
441 }
442
443 static int cz_upload_pptable_to_smu(struct pp_hwmgr *hwmgr)
444 {
445 struct SMU8_Fusion_ClkTable *clock_table;
446 int ret;
447 uint32_t i;
448 void *table = NULL;
449 pp_atomctrl_clock_dividers_kong dividers;
450
451 struct phm_clock_voltage_dependency_table *vddc_table =
452 hwmgr->dyn_state.vddc_dependency_on_sclk;
453 struct phm_clock_voltage_dependency_table *vdd_gfx_table =
454 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk;
455 struct phm_acp_clock_voltage_dependency_table *acp_table =
456 hwmgr->dyn_state.acp_clock_voltage_dependency_table;
457 struct phm_uvd_clock_voltage_dependency_table *uvd_table =
458 hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
459 struct phm_vce_clock_voltage_dependency_table *vce_table =
460 hwmgr->dyn_state.vce_clock_voltage_dependency_table;
461
462 if (!hwmgr->need_pp_table_upload)
463 return 0;
464
465 ret = smum_download_powerplay_table(hwmgr, &table);
466
467 PP_ASSERT_WITH_CODE((0 == ret && NULL != table),
468 "Fail to get clock table from SMU!", return -EINVAL;);
469
470 clock_table = (struct SMU8_Fusion_ClkTable *)table;
471
472 /* patch clock table */
473 PP_ASSERT_WITH_CODE((vddc_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
474 "Dependency table entry exceeds max limit!", return -EINVAL;);
475 PP_ASSERT_WITH_CODE((vdd_gfx_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
476 "Dependency table entry exceeds max limit!", return -EINVAL;);
477 PP_ASSERT_WITH_CODE((acp_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
478 "Dependency table entry exceeds max limit!", return -EINVAL;);
479 PP_ASSERT_WITH_CODE((uvd_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
480 "Dependency table entry exceeds max limit!", return -EINVAL;);
481 PP_ASSERT_WITH_CODE((vce_table->count <= CZ_MAX_HARDWARE_POWERLEVELS),
482 "Dependency table entry exceeds max limit!", return -EINVAL;);
483
484 for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++) {
485
486 /* vddc_sclk */
487 clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid =
488 (i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0;
489 clock_table->SclkBreakdownTable.ClkLevel[i].Frequency =
490 (i < vddc_table->count) ? vddc_table->entries[i].clk : 0;
491
492 atomctrl_get_engine_pll_dividers_kong(hwmgr,
493 clock_table->SclkBreakdownTable.ClkLevel[i].Frequency,
494 &dividers);
495
496 clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid =
497 (uint8_t)dividers.pll_post_divider;
498
499 /* vddgfx_sclk */
500 clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid =
501 (i < vdd_gfx_table->count) ? (uint8_t)vdd_gfx_table->entries[i].v : 0;
502
503 /* acp breakdown */
504 clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid =
505 (i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0;
506 clock_table->AclkBreakdownTable.ClkLevel[i].Frequency =
507 (i < acp_table->count) ? acp_table->entries[i].acpclk : 0;
508
509 atomctrl_get_engine_pll_dividers_kong(hwmgr,
510 clock_table->AclkBreakdownTable.ClkLevel[i].Frequency,
511 &dividers);
512
513 clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid =
514 (uint8_t)dividers.pll_post_divider;
515
516
517 /* uvd breakdown */
518 clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid =
519 (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0;
520 clock_table->VclkBreakdownTable.ClkLevel[i].Frequency =
521 (i < uvd_table->count) ? uvd_table->entries[i].vclk : 0;
522
523 atomctrl_get_engine_pll_dividers_kong(hwmgr,
524 clock_table->VclkBreakdownTable.ClkLevel[i].Frequency,
525 &dividers);
526
527 clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid =
528 (uint8_t)dividers.pll_post_divider;
529
530 clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid =
531 (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0;
532 clock_table->DclkBreakdownTable.ClkLevel[i].Frequency =
533 (i < uvd_table->count) ? uvd_table->entries[i].dclk : 0;
534
535 atomctrl_get_engine_pll_dividers_kong(hwmgr,
536 clock_table->DclkBreakdownTable.ClkLevel[i].Frequency,
537 &dividers);
538
539 clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid =
540 (uint8_t)dividers.pll_post_divider;
541
542 /* vce breakdown */
543 clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid =
544 (i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0;
545 clock_table->EclkBreakdownTable.ClkLevel[i].Frequency =
546 (i < vce_table->count) ? vce_table->entries[i].ecclk : 0;
547
548
549 atomctrl_get_engine_pll_dividers_kong(hwmgr,
550 clock_table->EclkBreakdownTable.ClkLevel[i].Frequency,
551 &dividers);
552
553 clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid =
554 (uint8_t)dividers.pll_post_divider;
555
556 }
557 ret = smum_upload_powerplay_table(hwmgr);
558
559 return ret;
560 }
561
562 static int cz_init_sclk_limit(struct pp_hwmgr *hwmgr)
563 {
564 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
565 struct phm_clock_voltage_dependency_table *table =
566 hwmgr->dyn_state.vddc_dependency_on_sclk;
567 unsigned long clock = 0, level;
568
569 if (NULL == table || table->count <= 0)
570 return -EINVAL;
571
572 cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
573 cz_hwmgr->sclk_dpm.hard_min_clk = table->entries[0].clk;
574
575 level = cz_get_max_sclk_level(hwmgr) - 1;
576
577 if (level < table->count)
578 clock = table->entries[level].clk;
579 else
580 clock = table->entries[table->count - 1].clk;
581
582 cz_hwmgr->sclk_dpm.soft_max_clk = clock;
583 cz_hwmgr->sclk_dpm.hard_max_clk = clock;
584
585 return 0;
586 }
587
588 static int cz_init_uvd_limit(struct pp_hwmgr *hwmgr)
589 {
590 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
591 struct phm_uvd_clock_voltage_dependency_table *table =
592 hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
593 unsigned long clock = 0, level;
594
595 if (NULL == table || table->count <= 0)
596 return -EINVAL;
597
598 cz_hwmgr->uvd_dpm.soft_min_clk = 0;
599 cz_hwmgr->uvd_dpm.hard_min_clk = 0;
600
601 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxUvdLevel);
602 level = smum_get_argument(hwmgr);
603
604 if (level < table->count)
605 clock = table->entries[level].vclk;
606 else
607 clock = table->entries[table->count - 1].vclk;
608
609 cz_hwmgr->uvd_dpm.soft_max_clk = clock;
610 cz_hwmgr->uvd_dpm.hard_max_clk = clock;
611
612 return 0;
613 }
614
615 static int cz_init_vce_limit(struct pp_hwmgr *hwmgr)
616 {
617 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
618 struct phm_vce_clock_voltage_dependency_table *table =
619 hwmgr->dyn_state.vce_clock_voltage_dependency_table;
620 unsigned long clock = 0, level;
621
622 if (NULL == table || table->count <= 0)
623 return -EINVAL;
624
625 cz_hwmgr->vce_dpm.soft_min_clk = 0;
626 cz_hwmgr->vce_dpm.hard_min_clk = 0;
627
628 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxEclkLevel);
629 level = smum_get_argument(hwmgr);
630
631 if (level < table->count)
632 clock = table->entries[level].ecclk;
633 else
634 clock = table->entries[table->count - 1].ecclk;
635
636 cz_hwmgr->vce_dpm.soft_max_clk = clock;
637 cz_hwmgr->vce_dpm.hard_max_clk = clock;
638
639 return 0;
640 }
641
642 static int cz_init_acp_limit(struct pp_hwmgr *hwmgr)
643 {
644 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
645 struct phm_acp_clock_voltage_dependency_table *table =
646 hwmgr->dyn_state.acp_clock_voltage_dependency_table;
647 unsigned long clock = 0, level;
648
649 if (NULL == table || table->count <= 0)
650 return -EINVAL;
651
652 cz_hwmgr->acp_dpm.soft_min_clk = 0;
653 cz_hwmgr->acp_dpm.hard_min_clk = 0;
654
655 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxAclkLevel);
656 level = smum_get_argument(hwmgr);
657
658 if (level < table->count)
659 clock = table->entries[level].acpclk;
660 else
661 clock = table->entries[table->count - 1].acpclk;
662
663 cz_hwmgr->acp_dpm.soft_max_clk = clock;
664 cz_hwmgr->acp_dpm.hard_max_clk = clock;
665 return 0;
666 }
667
668 static void cz_init_power_gate_state(struct pp_hwmgr *hwmgr)
669 {
670 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
671
672 cz_hwmgr->uvd_power_gated = false;
673 cz_hwmgr->vce_power_gated = false;
674 cz_hwmgr->samu_power_gated = false;
675 cz_hwmgr->acp_power_gated = false;
676 cz_hwmgr->pgacpinit = true;
677 }
678
679 static void cz_init_sclk_threshold(struct pp_hwmgr *hwmgr)
680 {
681 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
682
683 cz_hwmgr->low_sclk_interrupt_threshold = 0;
684 }
685
686 static int cz_update_sclk_limit(struct pp_hwmgr *hwmgr)
687 {
688 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
689 struct phm_clock_voltage_dependency_table *table =
690 hwmgr->dyn_state.vddc_dependency_on_sclk;
691
692 unsigned long clock = 0;
693 unsigned long level;
694 unsigned long stable_pstate_sclk;
695 unsigned long percentage;
696
697 cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
698 level = cz_get_max_sclk_level(hwmgr) - 1;
699
700 if (level < table->count)
701 cz_hwmgr->sclk_dpm.soft_max_clk = table->entries[level].clk;
702 else
703 cz_hwmgr->sclk_dpm.soft_max_clk = table->entries[table->count - 1].clk;
704
705 clock = hwmgr->display_config.min_core_set_clock;
706 if (clock == 0)
707 pr_debug("min_core_set_clock not set\n");
708
709 if (cz_hwmgr->sclk_dpm.hard_min_clk != clock) {
710 cz_hwmgr->sclk_dpm.hard_min_clk = clock;
711
712 smum_send_msg_to_smc_with_parameter(hwmgr,
713 PPSMC_MSG_SetSclkHardMin,
714 cz_get_sclk_level(hwmgr,
715 cz_hwmgr->sclk_dpm.hard_min_clk,
716 PPSMC_MSG_SetSclkHardMin));
717 }
718
719 clock = cz_hwmgr->sclk_dpm.soft_min_clk;
720
721 /* update minimum clocks for Stable P-State feature */
722 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
723 PHM_PlatformCaps_StablePState)) {
724 percentage = 75;
725 /*Sclk - calculate sclk value based on percentage and find FLOOR sclk from VddcDependencyOnSCLK table */
726 stable_pstate_sclk = (hwmgr->dyn_state.max_clock_voltage_on_ac.mclk *
727 percentage) / 100;
728
729 if (clock < stable_pstate_sclk)
730 clock = stable_pstate_sclk;
731 } else {
732 if (clock < hwmgr->gfx_arbiter.sclk)
733 clock = hwmgr->gfx_arbiter.sclk;
734 }
735
736 if (cz_hwmgr->sclk_dpm.soft_min_clk != clock) {
737 cz_hwmgr->sclk_dpm.soft_min_clk = clock;
738 smum_send_msg_to_smc_with_parameter(hwmgr,
739 PPSMC_MSG_SetSclkSoftMin,
740 cz_get_sclk_level(hwmgr,
741 cz_hwmgr->sclk_dpm.soft_min_clk,
742 PPSMC_MSG_SetSclkSoftMin));
743 }
744
745 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
746 PHM_PlatformCaps_StablePState) &&
747 cz_hwmgr->sclk_dpm.soft_max_clk != clock) {
748 cz_hwmgr->sclk_dpm.soft_max_clk = clock;
749 smum_send_msg_to_smc_with_parameter(hwmgr,
750 PPSMC_MSG_SetSclkSoftMax,
751 cz_get_sclk_level(hwmgr,
752 cz_hwmgr->sclk_dpm.soft_max_clk,
753 PPSMC_MSG_SetSclkSoftMax));
754 }
755
756 return 0;
757 }
758
759 static int cz_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr)
760 {
761 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
762 PHM_PlatformCaps_SclkDeepSleep)) {
763 uint32_t clks = hwmgr->display_config.min_core_set_clock_in_sr;
764 if (clks == 0)
765 clks = CZ_MIN_DEEP_SLEEP_SCLK;
766
767 PP_DBG_LOG("Setting Deep Sleep Clock: %d\n", clks);
768
769 smum_send_msg_to_smc_with_parameter(hwmgr,
770 PPSMC_MSG_SetMinDeepSleepSclk,
771 clks);
772 }
773
774 return 0;
775 }
776
777 static int cz_set_watermark_threshold(struct pp_hwmgr *hwmgr)
778 {
779 struct cz_hwmgr *cz_hwmgr =
780 (struct cz_hwmgr *)(hwmgr->backend);
781
782 smum_send_msg_to_smc_with_parameter(hwmgr,
783 PPSMC_MSG_SetWatermarkFrequency,
784 cz_hwmgr->sclk_dpm.soft_max_clk);
785
786 return 0;
787 }
788
789 static int cz_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock)
790 {
791 struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
792
793 if (hw_data->is_nb_dpm_enabled) {
794 if (enable) {
795 PP_DBG_LOG("enable Low Memory PState.\n");
796
797 return smum_send_msg_to_smc_with_parameter(hwmgr,
798 PPSMC_MSG_EnableLowMemoryPstate,
799 (lock ? 1 : 0));
800 } else {
801 PP_DBG_LOG("disable Low Memory PState.\n");
802
803 return smum_send_msg_to_smc_with_parameter(hwmgr,
804 PPSMC_MSG_DisableLowMemoryPstate,
805 (lock ? 1 : 0));
806 }
807 }
808
809 return 0;
810 }
811
812 static int cz_disable_nb_dpm(struct pp_hwmgr *hwmgr)
813 {
814 int ret = 0;
815
816 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
817 unsigned long dpm_features = 0;
818
819 if (cz_hwmgr->is_nb_dpm_enabled) {
820 cz_nbdpm_pstate_enable_disable(hwmgr, true, true);
821 dpm_features |= NB_DPM_MASK;
822 ret = smum_send_msg_to_smc_with_parameter(
823 hwmgr,
824 PPSMC_MSG_DisableAllSmuFeatures,
825 dpm_features);
826 if (ret == 0)
827 cz_hwmgr->is_nb_dpm_enabled = false;
828 }
829
830 return ret;
831 }
832
833 static int cz_enable_nb_dpm(struct pp_hwmgr *hwmgr)
834 {
835 int ret = 0;
836
837 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
838 unsigned long dpm_features = 0;
839
840 if (!cz_hwmgr->is_nb_dpm_enabled) {
841 PP_DBG_LOG("enabling ALL SMU features.\n");
842 dpm_features |= NB_DPM_MASK;
843 ret = smum_send_msg_to_smc_with_parameter(
844 hwmgr,
845 PPSMC_MSG_EnableAllSmuFeatures,
846 dpm_features);
847 if (ret == 0)
848 cz_hwmgr->is_nb_dpm_enabled = true;
849 }
850
851 return ret;
852 }
853
854 static int cz_update_low_mem_pstate(struct pp_hwmgr *hwmgr, const void *input)
855 {
856 bool disable_switch;
857 bool enable_low_mem_state;
858 struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
859 const struct phm_set_power_state_input *states = (struct phm_set_power_state_input *)input;
860 const struct cz_power_state *pnew_state = cast_const_PhwCzPowerState(states->pnew_state);
861
862 if (hw_data->sys_info.nb_dpm_enable) {
863 disable_switch = hw_data->cc6_settings.nb_pstate_switch_disable ? true : false;
864 enable_low_mem_state = hw_data->cc6_settings.nb_pstate_switch_disable ? false : true;
865
866 if (pnew_state->action == FORCE_HIGH)
867 cz_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch);
868 else if (pnew_state->action == CANCEL_FORCE_HIGH)
869 cz_nbdpm_pstate_enable_disable(hwmgr, true, disable_switch);
870 else
871 cz_nbdpm_pstate_enable_disable(hwmgr, enable_low_mem_state, disable_switch);
872 }
873 return 0;
874 }
875
876 static int cz_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
877 {
878 int ret = 0;
879
880 cz_update_sclk_limit(hwmgr);
881 cz_set_deep_sleep_sclk_threshold(hwmgr);
882 cz_set_watermark_threshold(hwmgr);
883 ret = cz_enable_nb_dpm(hwmgr);
884 if (ret)
885 return ret;
886 cz_update_low_mem_pstate(hwmgr, input);
887
888 return 0;
889 };
890
891
892 static int cz_setup_asic_task(struct pp_hwmgr *hwmgr)
893 {
894 int ret;
895
896 ret = cz_upload_pptable_to_smu(hwmgr);
897 if (ret)
898 return ret;
899 ret = cz_init_sclk_limit(hwmgr);
900 if (ret)
901 return ret;
902 ret = cz_init_uvd_limit(hwmgr);
903 if (ret)
904 return ret;
905 ret = cz_init_vce_limit(hwmgr);
906 if (ret)
907 return ret;
908 ret = cz_init_acp_limit(hwmgr);
909 if (ret)
910 return ret;
911
912 cz_init_power_gate_state(hwmgr);
913 cz_init_sclk_threshold(hwmgr);
914
915 return 0;
916 }
917
918 static void cz_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr)
919 {
920 struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
921
922 hw_data->disp_clk_bypass_pending = false;
923 hw_data->disp_clk_bypass = false;
924 }
925
926 static void cz_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr)
927 {
928 struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
929
930 hw_data->is_nb_dpm_enabled = false;
931 }
932
933 static void cz_reset_cc6_data(struct pp_hwmgr *hwmgr)
934 {
935 struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
936
937 hw_data->cc6_settings.cc6_setting_changed = false;
938 hw_data->cc6_settings.cpu_pstate_separation_time = 0;
939 hw_data->cc6_settings.cpu_cc6_disable = false;
940 hw_data->cc6_settings.cpu_pstate_disable = false;
941 }
942
943 static int cz_power_off_asic(struct pp_hwmgr *hwmgr)
944 {
945 cz_power_up_display_clock_sys_pll(hwmgr);
946 cz_clear_nb_dpm_flag(hwmgr);
947 cz_reset_cc6_data(hwmgr);
948 return 0;
949 };
950
951 static void cz_program_voting_clients(struct pp_hwmgr *hwmgr)
952 {
953 PHMCZ_WRITE_SMC_REGISTER(hwmgr->device, CG_FREQ_TRAN_VOTING_0,
954 PPCZ_VOTINGRIGHTSCLIENTS_DFLT0);
955 }
956
957 static void cz_clear_voting_clients(struct pp_hwmgr *hwmgr)
958 {
959 PHMCZ_WRITE_SMC_REGISTER(hwmgr->device, CG_FREQ_TRAN_VOTING_0, 0);
960 }
961
962 static int cz_start_dpm(struct pp_hwmgr *hwmgr)
963 {
964 int ret = 0;
965 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
966 unsigned long dpm_features = 0;
967
968 cz_hwmgr->dpm_flags |= DPMFlags_SCLK_Enabled;
969 dpm_features |= SCLK_DPM_MASK;
970
971 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
972 PPSMC_MSG_EnableAllSmuFeatures,
973 dpm_features);
974
975 return ret;
976 }
977
978 static int cz_stop_dpm(struct pp_hwmgr *hwmgr)
979 {
980 int ret = 0;
981 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
982 unsigned long dpm_features = 0;
983
984 if (cz_hwmgr->dpm_flags & DPMFlags_SCLK_Enabled) {
985 dpm_features |= SCLK_DPM_MASK;
986 cz_hwmgr->dpm_flags &= ~DPMFlags_SCLK_Enabled;
987 ret = smum_send_msg_to_smc_with_parameter(hwmgr,
988 PPSMC_MSG_DisableAllSmuFeatures,
989 dpm_features);
990 }
991 return ret;
992 }
993
994 static int cz_program_bootup_state(struct pp_hwmgr *hwmgr)
995 {
996 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
997
998 cz_hwmgr->sclk_dpm.soft_min_clk = cz_hwmgr->sys_info.bootup_engine_clock;
999 cz_hwmgr->sclk_dpm.soft_max_clk = cz_hwmgr->sys_info.bootup_engine_clock;
1000
1001 smum_send_msg_to_smc_with_parameter(hwmgr,
1002 PPSMC_MSG_SetSclkSoftMin,
1003 cz_get_sclk_level(hwmgr,
1004 cz_hwmgr->sclk_dpm.soft_min_clk,
1005 PPSMC_MSG_SetSclkSoftMin));
1006
1007 smum_send_msg_to_smc_with_parameter(hwmgr,
1008 PPSMC_MSG_SetSclkSoftMax,
1009 cz_get_sclk_level(hwmgr,
1010 cz_hwmgr->sclk_dpm.soft_max_clk,
1011 PPSMC_MSG_SetSclkSoftMax));
1012
1013 return 0;
1014 }
1015
1016 static void cz_reset_acp_boot_level(struct pp_hwmgr *hwmgr)
1017 {
1018 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1019
1020 cz_hwmgr->acp_boot_level = 0xff;
1021 }
1022
1023 static bool cz_dpm_check_smu_features(struct pp_hwmgr *hwmgr,
1024 unsigned long check_feature)
1025 {
1026 int result;
1027 unsigned long features;
1028
1029 result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetFeatureStatus, 0);
1030 if (result == 0) {
1031 features = smum_get_argument(hwmgr);
1032 if (features & check_feature)
1033 return true;
1034 }
1035
1036 return false;
1037 }
1038
1039 static bool cz_check_for_dpm_enabled(struct pp_hwmgr *hwmgr)
1040 {
1041 if (cz_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn))
1042 return true;
1043 return false;
1044 }
1045
1046 static int cz_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
1047 {
1048 if (!cz_check_for_dpm_enabled(hwmgr)) {
1049 pr_info("dpm has been disabled\n");
1050 return 0;
1051 }
1052 cz_disable_nb_dpm(hwmgr);
1053
1054 cz_clear_voting_clients(hwmgr);
1055 if (cz_stop_dpm(hwmgr))
1056 return -EINVAL;
1057
1058 return 0;
1059 };
1060
1061 static int cz_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
1062 {
1063 if (cz_check_for_dpm_enabled(hwmgr)) {
1064 pr_info("dpm has been enabled\n");
1065 return 0;
1066 }
1067
1068 cz_program_voting_clients(hwmgr);
1069 if (cz_start_dpm(hwmgr))
1070 return -EINVAL;
1071 cz_program_bootup_state(hwmgr);
1072 cz_reset_acp_boot_level(hwmgr);
1073
1074 return 0;
1075 };
1076
1077 static int cz_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
1078 struct pp_power_state *prequest_ps,
1079 const struct pp_power_state *pcurrent_ps)
1080 {
1081 struct cz_power_state *cz_ps =
1082 cast_PhwCzPowerState(&prequest_ps->hardware);
1083
1084 const struct cz_power_state *cz_current_ps =
1085 cast_const_PhwCzPowerState(&pcurrent_ps->hardware);
1086
1087 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1088 struct PP_Clocks clocks = {0, 0, 0, 0};
1089 bool force_high;
1090 uint32_t num_of_active_displays = 0;
1091 struct cgs_display_info info = {0};
1092
1093 cz_ps->evclk = hwmgr->vce_arbiter.evclk;
1094 cz_ps->ecclk = hwmgr->vce_arbiter.ecclk;
1095
1096 cz_ps->need_dfs_bypass = true;
1097
1098 cz_hwmgr->video_start = (hwmgr->uvd_arbiter.vclk != 0 || hwmgr->uvd_arbiter.dclk != 0 ||
1099 hwmgr->vce_arbiter.evclk != 0 || hwmgr->vce_arbiter.ecclk != 0);
1100
1101 cz_hwmgr->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label);
1102
1103 clocks.memoryClock = hwmgr->display_config.min_mem_set_clock != 0 ?
1104 hwmgr->display_config.min_mem_set_clock :
1105 cz_hwmgr->sys_info.nbp_memory_clock[1];
1106
1107 cgs_get_active_displays_info(hwmgr->device, &info);
1108 num_of_active_displays = info.display_count;
1109
1110 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
1111 clocks.memoryClock = hwmgr->dyn_state.max_clock_voltage_on_ac.mclk;
1112
1113 if (clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
1114 clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
1115
1116 force_high = (clocks.memoryClock > cz_hwmgr->sys_info.nbp_memory_clock[CZ_NUM_NBPMEMORYCLOCK - 1])
1117 || (num_of_active_displays >= 3);
1118
1119 cz_ps->action = cz_current_ps->action;
1120
1121 if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
1122 cz_nbdpm_pstate_enable_disable(hwmgr, false, false);
1123 else if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD)
1124 cz_nbdpm_pstate_enable_disable(hwmgr, false, true);
1125 else if (!force_high && (cz_ps->action == FORCE_HIGH))
1126 cz_ps->action = CANCEL_FORCE_HIGH;
1127 else if (force_high && (cz_ps->action != FORCE_HIGH))
1128 cz_ps->action = FORCE_HIGH;
1129 else
1130 cz_ps->action = DO_NOTHING;
1131
1132 return 0;
1133 }
1134
1135 static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
1136 {
1137 int result = 0;
1138 struct cz_hwmgr *data;
1139
1140 data = kzalloc(sizeof(struct cz_hwmgr), GFP_KERNEL);
1141 if (data == NULL)
1142 return -ENOMEM;
1143
1144 hwmgr->backend = data;
1145
1146 result = cz_initialize_dpm_defaults(hwmgr);
1147 if (result != 0) {
1148 pr_err("cz_initialize_dpm_defaults failed\n");
1149 return result;
1150 }
1151
1152 result = cz_get_system_info_data(hwmgr);
1153 if (result != 0) {
1154 pr_err("cz_get_system_info_data failed\n");
1155 return result;
1156 }
1157
1158 cz_construct_boot_state(hwmgr);
1159
1160 hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = CZ_MAX_HARDWARE_POWERLEVELS;
1161
1162 return result;
1163 }
1164
1165 static int cz_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
1166 {
1167 if (hwmgr != NULL) {
1168 kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
1169 hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
1170
1171 kfree(hwmgr->backend);
1172 hwmgr->backend = NULL;
1173 }
1174 return 0;
1175 }
1176
1177 static int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr)
1178 {
1179 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1180
1181 smum_send_msg_to_smc_with_parameter(hwmgr,
1182 PPSMC_MSG_SetSclkSoftMin,
1183 cz_get_sclk_level(hwmgr,
1184 cz_hwmgr->sclk_dpm.soft_max_clk,
1185 PPSMC_MSG_SetSclkSoftMin));
1186
1187 smum_send_msg_to_smc_with_parameter(hwmgr,
1188 PPSMC_MSG_SetSclkSoftMax,
1189 cz_get_sclk_level(hwmgr,
1190 cz_hwmgr->sclk_dpm.soft_max_clk,
1191 PPSMC_MSG_SetSclkSoftMax));
1192
1193 return 0;
1194 }
1195
1196 static int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
1197 {
1198 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1199 struct phm_clock_voltage_dependency_table *table =
1200 hwmgr->dyn_state.vddc_dependency_on_sclk;
1201 unsigned long clock = 0, level;
1202
1203 if (NULL == table || table->count <= 0)
1204 return -EINVAL;
1205
1206 cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
1207 cz_hwmgr->sclk_dpm.hard_min_clk = table->entries[0].clk;
1208
1209 level = cz_get_max_sclk_level(hwmgr) - 1;
1210
1211 if (level < table->count)
1212 clock = table->entries[level].clk;
1213 else
1214 clock = table->entries[table->count - 1].clk;
1215
1216 cz_hwmgr->sclk_dpm.soft_max_clk = clock;
1217 cz_hwmgr->sclk_dpm.hard_max_clk = clock;
1218
1219 smum_send_msg_to_smc_with_parameter(hwmgr,
1220 PPSMC_MSG_SetSclkSoftMin,
1221 cz_get_sclk_level(hwmgr,
1222 cz_hwmgr->sclk_dpm.soft_min_clk,
1223 PPSMC_MSG_SetSclkSoftMin));
1224
1225 smum_send_msg_to_smc_with_parameter(hwmgr,
1226 PPSMC_MSG_SetSclkSoftMax,
1227 cz_get_sclk_level(hwmgr,
1228 cz_hwmgr->sclk_dpm.soft_max_clk,
1229 PPSMC_MSG_SetSclkSoftMax));
1230
1231 return 0;
1232 }
1233
1234 static int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr)
1235 {
1236 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1237
1238 smum_send_msg_to_smc_with_parameter(hwmgr,
1239 PPSMC_MSG_SetSclkSoftMax,
1240 cz_get_sclk_level(hwmgr,
1241 cz_hwmgr->sclk_dpm.soft_min_clk,
1242 PPSMC_MSG_SetSclkSoftMax));
1243
1244 smum_send_msg_to_smc_with_parameter(hwmgr,
1245 PPSMC_MSG_SetSclkSoftMin,
1246 cz_get_sclk_level(hwmgr,
1247 cz_hwmgr->sclk_dpm.soft_min_clk,
1248 PPSMC_MSG_SetSclkSoftMin));
1249
1250 return 0;
1251 }
1252
1253 static int cz_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
1254 enum amd_dpm_forced_level level)
1255 {
1256 int ret = 0;
1257
1258 switch (level) {
1259 case AMD_DPM_FORCED_LEVEL_HIGH:
1260 case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
1261 ret = cz_phm_force_dpm_highest(hwmgr);
1262 break;
1263 case AMD_DPM_FORCED_LEVEL_LOW:
1264 case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
1265 case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
1266 ret = cz_phm_force_dpm_lowest(hwmgr);
1267 break;
1268 case AMD_DPM_FORCED_LEVEL_AUTO:
1269 ret = cz_phm_unforce_dpm_levels(hwmgr);
1270 break;
1271 case AMD_DPM_FORCED_LEVEL_MANUAL:
1272 case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
1273 default:
1274 break;
1275 }
1276
1277 return ret;
1278 }
1279
1280 int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr)
1281 {
1282 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1283 PHM_PlatformCaps_UVDPowerGating))
1284 return smum_send_msg_to_smc(hwmgr,
1285 PPSMC_MSG_UVDPowerOFF);
1286 return 0;
1287 }
1288
1289 int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr)
1290 {
1291 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1292 PHM_PlatformCaps_UVDPowerGating)) {
1293 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1294 PHM_PlatformCaps_UVDDynamicPowerGating)) {
1295 return smum_send_msg_to_smc_with_parameter(
1296 hwmgr,
1297 PPSMC_MSG_UVDPowerON, 1);
1298 } else {
1299 return smum_send_msg_to_smc_with_parameter(
1300 hwmgr,
1301 PPSMC_MSG_UVDPowerON, 0);
1302 }
1303 }
1304
1305 return 0;
1306 }
1307
1308 int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
1309 {
1310 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1311 struct phm_uvd_clock_voltage_dependency_table *ptable =
1312 hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
1313
1314 if (!bgate) {
1315 /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */
1316 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1317 PHM_PlatformCaps_StablePState)
1318 || hwmgr->en_umd_pstate) {
1319 cz_hwmgr->uvd_dpm.hard_min_clk =
1320 ptable->entries[ptable->count - 1].vclk;
1321
1322 smum_send_msg_to_smc_with_parameter(hwmgr,
1323 PPSMC_MSG_SetUvdHardMin,
1324 cz_get_uvd_level(hwmgr,
1325 cz_hwmgr->uvd_dpm.hard_min_clk,
1326 PPSMC_MSG_SetUvdHardMin));
1327
1328 cz_enable_disable_uvd_dpm(hwmgr, true);
1329 } else {
1330 cz_enable_disable_uvd_dpm(hwmgr, true);
1331 }
1332 } else {
1333 cz_enable_disable_uvd_dpm(hwmgr, false);
1334 }
1335
1336 return 0;
1337 }
1338
1339 int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr)
1340 {
1341 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1342 struct phm_vce_clock_voltage_dependency_table *ptable =
1343 hwmgr->dyn_state.vce_clock_voltage_dependency_table;
1344
1345 /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */
1346 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1347 PHM_PlatformCaps_StablePState)
1348 || hwmgr->en_umd_pstate) {
1349 cz_hwmgr->vce_dpm.hard_min_clk =
1350 ptable->entries[ptable->count - 1].ecclk;
1351
1352 smum_send_msg_to_smc_with_parameter(hwmgr,
1353 PPSMC_MSG_SetEclkHardMin,
1354 cz_get_eclk_level(hwmgr,
1355 cz_hwmgr->vce_dpm.hard_min_clk,
1356 PPSMC_MSG_SetEclkHardMin));
1357 } else {
1358 /*Program HardMin based on the vce_arbiter.ecclk */
1359 if (hwmgr->vce_arbiter.ecclk == 0) {
1360 smum_send_msg_to_smc_with_parameter(hwmgr,
1361 PPSMC_MSG_SetEclkHardMin, 0);
1362 /* disable ECLK DPM 0. Otherwise VCE could hang if
1363 * switching SCLK from DPM 0 to 6/7 */
1364 smum_send_msg_to_smc_with_parameter(hwmgr,
1365 PPSMC_MSG_SetEclkSoftMin, 1);
1366 } else {
1367 cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
1368 smum_send_msg_to_smc_with_parameter(hwmgr,
1369 PPSMC_MSG_SetEclkHardMin,
1370 cz_get_eclk_level(hwmgr,
1371 cz_hwmgr->vce_dpm.hard_min_clk,
1372 PPSMC_MSG_SetEclkHardMin));
1373 }
1374 }
1375 return 0;
1376 }
1377
1378 int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr)
1379 {
1380 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1381 PHM_PlatformCaps_VCEPowerGating))
1382 return smum_send_msg_to_smc(hwmgr,
1383 PPSMC_MSG_VCEPowerOFF);
1384 return 0;
1385 }
1386
1387 int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr)
1388 {
1389 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
1390 PHM_PlatformCaps_VCEPowerGating))
1391 return smum_send_msg_to_smc(hwmgr,
1392 PPSMC_MSG_VCEPowerON);
1393 return 0;
1394 }
1395
1396 static uint32_t cz_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
1397 {
1398 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1399
1400 return cz_hwmgr->sys_info.bootup_uma_clock;
1401 }
1402
1403 static uint32_t cz_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
1404 {
1405 struct pp_power_state *ps;
1406 struct cz_power_state *cz_ps;
1407
1408 if (hwmgr == NULL)
1409 return -EINVAL;
1410
1411 ps = hwmgr->request_ps;
1412
1413 if (ps == NULL)
1414 return -EINVAL;
1415
1416 cz_ps = cast_PhwCzPowerState(&ps->hardware);
1417
1418 if (low)
1419 return cz_ps->levels[0].engineClock;
1420 else
1421 return cz_ps->levels[cz_ps->level-1].engineClock;
1422 }
1423
1424 static int cz_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
1425 struct pp_hw_power_state *hw_ps)
1426 {
1427 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1428 struct cz_power_state *cz_ps = cast_PhwCzPowerState(hw_ps);
1429
1430 cz_ps->level = 1;
1431 cz_ps->nbps_flags = 0;
1432 cz_ps->bapm_flags = 0;
1433 cz_ps->levels[0] = cz_hwmgr->boot_power_level;
1434
1435 return 0;
1436 }
1437
1438 static int cz_dpm_get_pp_table_entry_callback(
1439 struct pp_hwmgr *hwmgr,
1440 struct pp_hw_power_state *hw_ps,
1441 unsigned int index,
1442 const void *clock_info)
1443 {
1444 struct cz_power_state *cz_ps = cast_PhwCzPowerState(hw_ps);
1445
1446 const ATOM_PPLIB_CZ_CLOCK_INFO *cz_clock_info = clock_info;
1447
1448 struct phm_clock_voltage_dependency_table *table =
1449 hwmgr->dyn_state.vddc_dependency_on_sclk;
1450 uint8_t clock_info_index = cz_clock_info->index;
1451
1452 if (clock_info_index > (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1))
1453 clock_info_index = (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1);
1454
1455 cz_ps->levels[index].engineClock = table->entries[clock_info_index].clk;
1456 cz_ps->levels[index].vddcIndex = (uint8_t)table->entries[clock_info_index].v;
1457
1458 cz_ps->level = index + 1;
1459
1460 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
1461 cz_ps->levels[index].dsDividerIndex = 5;
1462 cz_ps->levels[index].ssDividerIndex = 5;
1463 }
1464
1465 return 0;
1466 }
1467
1468 static int cz_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr)
1469 {
1470 int result;
1471 unsigned long ret = 0;
1472
1473 result = pp_tables_get_num_of_entries(hwmgr, &ret);
1474
1475 return result ? 0 : ret;
1476 }
1477
1478 static int cz_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr,
1479 unsigned long entry, struct pp_power_state *ps)
1480 {
1481 int result;
1482 struct cz_power_state *cz_ps;
1483
1484 ps->hardware.magic = PhwCz_Magic;
1485
1486 cz_ps = cast_PhwCzPowerState(&(ps->hardware));
1487
1488 result = pp_tables_get_entry(hwmgr, entry, ps,
1489 cz_dpm_get_pp_table_entry_callback);
1490
1491 cz_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK;
1492 cz_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK;
1493
1494 return result;
1495 }
1496
1497 static int cz_get_power_state_size(struct pp_hwmgr *hwmgr)
1498 {
1499 return sizeof(struct cz_power_state);
1500 }
1501
1502 static void cz_hw_print_display_cfg(
1503 const struct cc6_settings *cc6_settings)
1504 {
1505 PP_DBG_LOG("New Display Configuration:\n");
1506
1507 PP_DBG_LOG(" cpu_cc6_disable: %d\n",
1508 cc6_settings->cpu_cc6_disable);
1509 PP_DBG_LOG(" cpu_pstate_disable: %d\n",
1510 cc6_settings->cpu_pstate_disable);
1511 PP_DBG_LOG(" nb_pstate_switch_disable: %d\n",
1512 cc6_settings->nb_pstate_switch_disable);
1513 PP_DBG_LOG(" cpu_pstate_separation_time: %d\n\n",
1514 cc6_settings->cpu_pstate_separation_time);
1515 }
1516
1517 static int cz_set_cpu_power_state(struct pp_hwmgr *hwmgr)
1518 {
1519 struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
1520 uint32_t data = 0;
1521
1522 if (hw_data->cc6_settings.cc6_setting_changed) {
1523
1524 hw_data->cc6_settings.cc6_setting_changed = false;
1525
1526 cz_hw_print_display_cfg(&hw_data->cc6_settings);
1527
1528 data |= (hw_data->cc6_settings.cpu_pstate_separation_time
1529 & PWRMGT_SEPARATION_TIME_MASK)
1530 << PWRMGT_SEPARATION_TIME_SHIFT;
1531
1532 data |= (hw_data->cc6_settings.cpu_cc6_disable ? 0x1 : 0x0)
1533 << PWRMGT_DISABLE_CPU_CSTATES_SHIFT;
1534
1535 data |= (hw_data->cc6_settings.cpu_pstate_disable ? 0x1 : 0x0)
1536 << PWRMGT_DISABLE_CPU_PSTATES_SHIFT;
1537
1538 PP_DBG_LOG("SetDisplaySizePowerParams data: 0x%X\n",
1539 data);
1540
1541 smum_send_msg_to_smc_with_parameter(hwmgr,
1542 PPSMC_MSG_SetDisplaySizePowerParams,
1543 data);
1544 }
1545
1546 return 0;
1547 }
1548
1549
1550 static int cz_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time,
1551 bool cc6_disable, bool pstate_disable, bool pstate_switch_disable)
1552 {
1553 struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend);
1554
1555 if (separation_time !=
1556 hw_data->cc6_settings.cpu_pstate_separation_time ||
1557 cc6_disable != hw_data->cc6_settings.cpu_cc6_disable ||
1558 pstate_disable != hw_data->cc6_settings.cpu_pstate_disable ||
1559 pstate_switch_disable != hw_data->cc6_settings.nb_pstate_switch_disable) {
1560
1561 hw_data->cc6_settings.cc6_setting_changed = true;
1562
1563 hw_data->cc6_settings.cpu_pstate_separation_time =
1564 separation_time;
1565 hw_data->cc6_settings.cpu_cc6_disable =
1566 cc6_disable;
1567 hw_data->cc6_settings.cpu_pstate_disable =
1568 pstate_disable;
1569 hw_data->cc6_settings.nb_pstate_switch_disable =
1570 pstate_switch_disable;
1571
1572 }
1573
1574 return 0;
1575 }
1576
1577 static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr,
1578 struct amd_pp_simple_clock_info *info)
1579 {
1580 uint32_t i;
1581 const struct phm_clock_voltage_dependency_table *table =
1582 hwmgr->dyn_state.vddc_dep_on_dal_pwrl;
1583 const struct phm_clock_and_voltage_limits *limits =
1584 &hwmgr->dyn_state.max_clock_voltage_on_ac;
1585
1586 info->engine_max_clock = limits->sclk;
1587 info->memory_max_clock = limits->mclk;
1588
1589 for (i = table->count - 1; i > 0; i--) {
1590 if (limits->vddc >= table->entries[i].v) {
1591 info->level = table->entries[i].clk;
1592 return 0;
1593 }
1594 }
1595 return -EINVAL;
1596 }
1597
1598 static int cz_force_clock_level(struct pp_hwmgr *hwmgr,
1599 enum pp_clock_type type, uint32_t mask)
1600 {
1601 if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
1602 return -EINVAL;
1603
1604 switch (type) {
1605 case PP_SCLK:
1606 smum_send_msg_to_smc_with_parameter(hwmgr,
1607 PPSMC_MSG_SetSclkSoftMin,
1608 mask);
1609 smum_send_msg_to_smc_with_parameter(hwmgr,
1610 PPSMC_MSG_SetSclkSoftMax,
1611 mask);
1612 break;
1613 default:
1614 break;
1615 }
1616
1617 return 0;
1618 }
1619
1620 static int cz_print_clock_levels(struct pp_hwmgr *hwmgr,
1621 enum pp_clock_type type, char *buf)
1622 {
1623 struct phm_clock_voltage_dependency_table *sclk_table =
1624 hwmgr->dyn_state.vddc_dependency_on_sclk;
1625 int i, now, size = 0;
1626
1627 switch (type) {
1628 case PP_SCLK:
1629 now = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device,
1630 CGS_IND_REG__SMC,
1631 ixTARGET_AND_CURRENT_PROFILE_INDEX),
1632 TARGET_AND_CURRENT_PROFILE_INDEX,
1633 CURR_SCLK_INDEX);
1634
1635 for (i = 0; i < sclk_table->count; i++)
1636 size += sprintf(buf + size, "%d: %uMhz %s\n",
1637 i, sclk_table->entries[i].clk / 100,
1638 (i == now) ? "*" : "");
1639 break;
1640 default:
1641 break;
1642 }
1643 return size;
1644 }
1645
1646 static int cz_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
1647 PHM_PerformanceLevelDesignation designation, uint32_t index,
1648 PHM_PerformanceLevel *level)
1649 {
1650 const struct cz_power_state *ps;
1651 struct cz_hwmgr *data;
1652 uint32_t level_index;
1653 uint32_t i;
1654
1655 if (level == NULL || hwmgr == NULL || state == NULL)
1656 return -EINVAL;
1657
1658 data = (struct cz_hwmgr *)(hwmgr->backend);
1659 ps = cast_const_PhwCzPowerState(state);
1660
1661 level_index = index > ps->level - 1 ? ps->level - 1 : index;
1662 level->coreClock = ps->levels[level_index].engineClock;
1663
1664 if (designation == PHM_PerformanceLevelDesignation_PowerContainment) {
1665 for (i = 1; i < ps->level; i++) {
1666 if (ps->levels[i].engineClock > data->dce_slow_sclk_threshold) {
1667 level->coreClock = ps->levels[i].engineClock;
1668 break;
1669 }
1670 }
1671 }
1672
1673 if (level_index == 0)
1674 level->memory_clock = data->sys_info.nbp_memory_clock[CZ_NUM_NBPMEMORYCLOCK - 1];
1675 else
1676 level->memory_clock = data->sys_info.nbp_memory_clock[0];
1677
1678 level->vddc = (cz_convert_8Bit_index_to_voltage(hwmgr, ps->levels[level_index].vddcIndex) + 2) / 4;
1679 level->nonLocalMemoryFreq = 0;
1680 level->nonLocalMemoryWidth = 0;
1681
1682 return 0;
1683 }
1684
1685 static int cz_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr,
1686 const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
1687 {
1688 const struct cz_power_state *ps = cast_const_PhwCzPowerState(state);
1689
1690 clock_info->min_eng_clk = ps->levels[0].engineClock / (1 << (ps->levels[0].ssDividerIndex));
1691 clock_info->max_eng_clk = ps->levels[ps->level - 1].engineClock / (1 << (ps->levels[ps->level - 1].ssDividerIndex));
1692
1693 return 0;
1694 }
1695
1696 static int cz_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type,
1697 struct amd_pp_clocks *clocks)
1698 {
1699 struct cz_hwmgr *data = (struct cz_hwmgr *)(hwmgr->backend);
1700 int i;
1701 struct phm_clock_voltage_dependency_table *table;
1702
1703 clocks->count = cz_get_max_sclk_level(hwmgr);
1704 switch (type) {
1705 case amd_pp_disp_clock:
1706 for (i = 0; i < clocks->count; i++)
1707 clocks->clock[i] = data->sys_info.display_clock[i];
1708 break;
1709 case amd_pp_sys_clock:
1710 table = hwmgr->dyn_state.vddc_dependency_on_sclk;
1711 for (i = 0; i < clocks->count; i++)
1712 clocks->clock[i] = table->entries[i].clk;
1713 break;
1714 case amd_pp_mem_clock:
1715 clocks->count = CZ_NUM_NBPMEMORYCLOCK;
1716 for (i = 0; i < clocks->count; i++)
1717 clocks->clock[i] = data->sys_info.nbp_memory_clock[clocks->count - 1 - i];
1718 break;
1719 default:
1720 return -1;
1721 }
1722
1723 return 0;
1724 }
1725
1726 static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
1727 {
1728 struct phm_clock_voltage_dependency_table *table =
1729 hwmgr->dyn_state.vddc_dependency_on_sclk;
1730 unsigned long level;
1731 const struct phm_clock_and_voltage_limits *limits =
1732 &hwmgr->dyn_state.max_clock_voltage_on_ac;
1733
1734 if ((NULL == table) || (table->count <= 0) || (clocks == NULL))
1735 return -EINVAL;
1736
1737 level = cz_get_max_sclk_level(hwmgr) - 1;
1738
1739 if (level < table->count)
1740 clocks->engine_max_clock = table->entries[level].clk;
1741 else
1742 clocks->engine_max_clock = table->entries[table->count - 1].clk;
1743
1744 clocks->memory_max_clock = limits->mclk;
1745
1746 return 0;
1747 }
1748
1749 static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr)
1750 {
1751 int actual_temp = 0;
1752 uint32_t val = cgs_read_ind_register(hwmgr->device,
1753 CGS_IND_REG__SMC, ixTHM_TCON_CUR_TMP);
1754 uint32_t temp = PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP);
1755
1756 if (PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL))
1757 actual_temp = ((temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1758 else
1759 actual_temp = (temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
1760
1761 return actual_temp;
1762 }
1763
1764 static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx,
1765 void *value, int *size)
1766 {
1767 struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
1768
1769 struct phm_clock_voltage_dependency_table *table =
1770 hwmgr->dyn_state.vddc_dependency_on_sclk;
1771
1772 struct phm_vce_clock_voltage_dependency_table *vce_table =
1773 hwmgr->dyn_state.vce_clock_voltage_dependency_table;
1774
1775 struct phm_uvd_clock_voltage_dependency_table *uvd_table =
1776 hwmgr->dyn_state.uvd_clock_voltage_dependency_table;
1777
1778 uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX),
1779 TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);
1780 uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
1781 TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);
1782 uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
1783 TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
1784
1785 uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent;
1786 uint16_t vddnb, vddgfx;
1787 int result;
1788
1789 /* size must be at least 4 bytes for all sensors */
1790 if (*size < 4)
1791 return -EINVAL;
1792 *size = 4;
1793
1794 switch (idx) {
1795 case AMDGPU_PP_SENSOR_GFX_SCLK:
1796 if (sclk_index < NUM_SCLK_LEVELS) {
1797 sclk = table->entries[sclk_index].clk;
1798 *((uint32_t *)value) = sclk;
1799 return 0;
1800 }
1801 return -EINVAL;
1802 case AMDGPU_PP_SENSOR_VDDNB:
1803 tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) &
1804 CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;
1805 vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp);
1806 *((uint32_t *)value) = vddnb;
1807 return 0;
1808 case AMDGPU_PP_SENSOR_VDDGFX:
1809 tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) &
1810 CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;
1811 vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp);
1812 *((uint32_t *)value) = vddgfx;
1813 return 0;
1814 case AMDGPU_PP_SENSOR_UVD_VCLK:
1815 if (!cz_hwmgr->uvd_power_gated) {
1816 if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
1817 return -EINVAL;
1818 } else {
1819 vclk = uvd_table->entries[uvd_index].vclk;
1820 *((uint32_t *)value) = vclk;
1821 return 0;
1822 }
1823 }
1824 *((uint32_t *)value) = 0;
1825 return 0;
1826 case AMDGPU_PP_SENSOR_UVD_DCLK:
1827 if (!cz_hwmgr->uvd_power_gated) {
1828 if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
1829 return -EINVAL;
1830 } else {
1831 dclk = uvd_table->entries[uvd_index].dclk;
1832 *((uint32_t *)value) = dclk;
1833 return 0;
1834 }
1835 }
1836 *((uint32_t *)value) = 0;
1837 return 0;
1838 case AMDGPU_PP_SENSOR_VCE_ECCLK:
1839 if (!cz_hwmgr->vce_power_gated) {
1840 if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
1841 return -EINVAL;
1842 } else {
1843 ecclk = vce_table->entries[vce_index].ecclk;
1844 *((uint32_t *)value) = ecclk;
1845 return 0;
1846 }
1847 }
1848 *((uint32_t *)value) = 0;
1849 return 0;
1850 case AMDGPU_PP_SENSOR_GPU_LOAD:
1851 result = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGraphicsActivity);
1852 if (0 == result) {
1853 activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0);
1854 activity_percent = activity_percent > 100 ? 100 : activity_percent;
1855 } else {
1856 activity_percent = 50;
1857 }
1858 *((uint32_t *)value) = activity_percent;
1859 return 0;
1860 case AMDGPU_PP_SENSOR_UVD_POWER:
1861 *((uint32_t *)value) = cz_hwmgr->uvd_power_gated ? 0 : 1;
1862 return 0;
1863 case AMDGPU_PP_SENSOR_VCE_POWER:
1864 *((uint32_t *)value) = cz_hwmgr->vce_power_gated ? 0 : 1;
1865 return 0;
1866 case AMDGPU_PP_SENSOR_GPU_TEMP:
1867 *((uint32_t *)value) = cz_thermal_get_temperature(hwmgr);
1868 return 0;
1869 default:
1870 return -EINVAL;
1871 }
1872 }
1873
1874 static const struct pp_hwmgr_func cz_hwmgr_funcs = {
1875 .backend_init = cz_hwmgr_backend_init,
1876 .backend_fini = cz_hwmgr_backend_fini,
1877 .apply_state_adjust_rules = cz_apply_state_adjust_rules,
1878 .force_dpm_level = cz_dpm_force_dpm_level,
1879 .get_power_state_size = cz_get_power_state_size,
1880 .powerdown_uvd = cz_dpm_powerdown_uvd,
1881 .powergate_uvd = cz_dpm_powergate_uvd,
1882 .powergate_vce = cz_dpm_powergate_vce,
1883 .get_mclk = cz_dpm_get_mclk,
1884 .get_sclk = cz_dpm_get_sclk,
1885 .patch_boot_state = cz_dpm_patch_boot_state,
1886 .get_pp_table_entry = cz_dpm_get_pp_table_entry,
1887 .get_num_of_pp_table_entries = cz_dpm_get_num_of_pp_table_entries,
1888 .set_cpu_power_state = cz_set_cpu_power_state,
1889 .store_cc6_data = cz_store_cc6_data,
1890 .force_clock_level = cz_force_clock_level,
1891 .print_clock_levels = cz_print_clock_levels,
1892 .get_dal_power_level = cz_get_dal_power_level,
1893 .get_performance_level = cz_get_performance_level,
1894 .get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks,
1895 .get_clock_by_type = cz_get_clock_by_type,
1896 .get_max_high_clocks = cz_get_max_high_clocks,
1897 .read_sensor = cz_read_sensor,
1898 .power_off_asic = cz_power_off_asic,
1899 .asic_setup = cz_setup_asic_task,
1900 .dynamic_state_management_enable = cz_enable_dpm_tasks,
1901 .power_state_set = cz_set_power_state_tasks,
1902 .dynamic_state_management_disable = cz_disable_dpm_tasks,
1903 };
1904
1905 int cz_init_function_pointers(struct pp_hwmgr *hwmgr)
1906 {
1907 hwmgr->hwmgr_func = &cz_hwmgr_funcs;
1908 hwmgr->pptable_func = &pptable_funcs;
1909 return 0;
1910 }