1*54ddf812Sriastradh /*	$NetBSD: amdgpu_dm_pp_smu.c,v 1.3 2021/12/19 10:59:01 riastradh Exp $	*/
21571a7a1Sriastradh 
31571a7a1Sriastradh /*
41571a7a1Sriastradh  * Copyright 2018 Advanced Micro Devices, Inc.
51571a7a1Sriastradh  *
61571a7a1Sriastradh  * Permission is hereby granted, free of charge, to any person obtaining a
71571a7a1Sriastradh  * copy of this software and associated documentation files (the "Software"),
81571a7a1Sriastradh  * to deal in the Software without restriction, including without limitation
91571a7a1Sriastradh  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
101571a7a1Sriastradh  * and/or sell copies of the Software, and to permit persons to whom the
111571a7a1Sriastradh  * Software is furnished to do so, subject to the following conditions:
121571a7a1Sriastradh  *
131571a7a1Sriastradh  * The above copyright notice and this permission notice shall be included in
141571a7a1Sriastradh  * all copies or substantial portions of the Software.
151571a7a1Sriastradh  *
161571a7a1Sriastradh  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
171571a7a1Sriastradh  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
181571a7a1Sriastradh  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
191571a7a1Sriastradh  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
201571a7a1Sriastradh  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
211571a7a1Sriastradh  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
221571a7a1Sriastradh  * OTHER DEALINGS IN THE SOFTWARE.
231571a7a1Sriastradh  *
241571a7a1Sriastradh  * Authors: AMD
251571a7a1Sriastradh  */
261571a7a1Sriastradh #include <sys/cdefs.h>
27*54ddf812Sriastradh __KERNEL_RCSID(0, "$NetBSD: amdgpu_dm_pp_smu.c,v 1.3 2021/12/19 10:59:01 riastradh Exp $");
281571a7a1Sriastradh 
291571a7a1Sriastradh #include <linux/string.h>
301571a7a1Sriastradh #include <linux/acpi.h>
311571a7a1Sriastradh 
321571a7a1Sriastradh #include <drm/drm_probe_helper.h>
331571a7a1Sriastradh #include <drm/amdgpu_drm.h>
341571a7a1Sriastradh #include "dm_services.h"
351571a7a1Sriastradh #include "amdgpu.h"
361571a7a1Sriastradh #include "amdgpu_dm.h"
371571a7a1Sriastradh #include "amdgpu_dm_irq.h"
381571a7a1Sriastradh #include "amdgpu_pm.h"
391571a7a1Sriastradh #include "dm_pp_smu.h"
401571a7a1Sriastradh #include "amdgpu_smu.h"
411571a7a1Sriastradh 
421571a7a1Sriastradh 
dm_pp_apply_display_requirements(const struct dc_context * ctx,const struct dm_pp_display_configuration * pp_display_cfg)431571a7a1Sriastradh bool dm_pp_apply_display_requirements(
441571a7a1Sriastradh 		const struct dc_context *ctx,
451571a7a1Sriastradh 		const struct dm_pp_display_configuration *pp_display_cfg)
461571a7a1Sriastradh {
471571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
481571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
491571a7a1Sriastradh 	int i;
501571a7a1Sriastradh 
511571a7a1Sriastradh 	if (adev->pm.dpm_enabled) {
521571a7a1Sriastradh 
531571a7a1Sriastradh 		memset(&adev->pm.pm_display_cfg, 0,
541571a7a1Sriastradh 				sizeof(adev->pm.pm_display_cfg));
551571a7a1Sriastradh 
561571a7a1Sriastradh 		adev->pm.pm_display_cfg.cpu_cc6_disable =
571571a7a1Sriastradh 			pp_display_cfg->cpu_cc6_disable;
581571a7a1Sriastradh 
591571a7a1Sriastradh 		adev->pm.pm_display_cfg.cpu_pstate_disable =
601571a7a1Sriastradh 			pp_display_cfg->cpu_pstate_disable;
611571a7a1Sriastradh 
621571a7a1Sriastradh 		adev->pm.pm_display_cfg.cpu_pstate_separation_time =
631571a7a1Sriastradh 			pp_display_cfg->cpu_pstate_separation_time;
641571a7a1Sriastradh 
651571a7a1Sriastradh 		adev->pm.pm_display_cfg.nb_pstate_switch_disable =
661571a7a1Sriastradh 			pp_display_cfg->nb_pstate_switch_disable;
671571a7a1Sriastradh 
681571a7a1Sriastradh 		adev->pm.pm_display_cfg.num_display =
691571a7a1Sriastradh 				pp_display_cfg->display_count;
701571a7a1Sriastradh 		adev->pm.pm_display_cfg.num_path_including_non_display =
711571a7a1Sriastradh 				pp_display_cfg->display_count;
721571a7a1Sriastradh 
731571a7a1Sriastradh 		adev->pm.pm_display_cfg.min_core_set_clock =
741571a7a1Sriastradh 				pp_display_cfg->min_engine_clock_khz/10;
751571a7a1Sriastradh 		adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
761571a7a1Sriastradh 				pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
771571a7a1Sriastradh 		adev->pm.pm_display_cfg.min_mem_set_clock =
781571a7a1Sriastradh 				pp_display_cfg->min_memory_clock_khz/10;
791571a7a1Sriastradh 
801571a7a1Sriastradh 		adev->pm.pm_display_cfg.min_dcef_deep_sleep_set_clk =
811571a7a1Sriastradh 				pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
821571a7a1Sriastradh 		adev->pm.pm_display_cfg.min_dcef_set_clk =
831571a7a1Sriastradh 				pp_display_cfg->min_dcfclock_khz/10;
841571a7a1Sriastradh 
851571a7a1Sriastradh 		adev->pm.pm_display_cfg.multi_monitor_in_sync =
861571a7a1Sriastradh 				pp_display_cfg->all_displays_in_sync;
871571a7a1Sriastradh 		adev->pm.pm_display_cfg.min_vblank_time =
881571a7a1Sriastradh 				pp_display_cfg->avail_mclk_switch_time_us;
891571a7a1Sriastradh 
901571a7a1Sriastradh 		adev->pm.pm_display_cfg.display_clk =
911571a7a1Sriastradh 				pp_display_cfg->disp_clk_khz/10;
921571a7a1Sriastradh 
931571a7a1Sriastradh 		adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
941571a7a1Sriastradh 				pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
951571a7a1Sriastradh 
961571a7a1Sriastradh 		adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
971571a7a1Sriastradh 		adev->pm.pm_display_cfg.line_time_in_us =
981571a7a1Sriastradh 				pp_display_cfg->line_time_in_us;
991571a7a1Sriastradh 
1001571a7a1Sriastradh 		adev->pm.pm_display_cfg.vrefresh = pp_display_cfg->disp_configs[0].v_refresh;
1011571a7a1Sriastradh 		adev->pm.pm_display_cfg.crossfire_display_index = -1;
1021571a7a1Sriastradh 		adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
1031571a7a1Sriastradh 
1041571a7a1Sriastradh 		for (i = 0; i < pp_display_cfg->display_count; i++) {
1051571a7a1Sriastradh 			const struct dm_pp_single_disp_config *dc_cfg =
1061571a7a1Sriastradh 						&pp_display_cfg->disp_configs[i];
1071571a7a1Sriastradh 			adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1;
1081571a7a1Sriastradh 		}
1091571a7a1Sriastradh 
1101571a7a1Sriastradh 		if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_configuration_change)
1111571a7a1Sriastradh 			adev->powerplay.pp_funcs->display_configuration_change(
1121571a7a1Sriastradh 				adev->powerplay.pp_handle,
1131571a7a1Sriastradh 				&adev->pm.pm_display_cfg);
1141571a7a1Sriastradh 		else
1151571a7a1Sriastradh 			smu_display_configuration_change(smu,
1161571a7a1Sriastradh 							 &adev->pm.pm_display_cfg);
1171571a7a1Sriastradh 
1181571a7a1Sriastradh 		amdgpu_pm_compute_clocks(adev);
1191571a7a1Sriastradh 	}
1201571a7a1Sriastradh 
1211571a7a1Sriastradh 	return true;
1221571a7a1Sriastradh }
1231571a7a1Sriastradh 
get_default_clock_levels(enum dm_pp_clock_type clk_type,struct dm_pp_clock_levels * clks)1241571a7a1Sriastradh static void get_default_clock_levels(
1251571a7a1Sriastradh 		enum dm_pp_clock_type clk_type,
1261571a7a1Sriastradh 		struct dm_pp_clock_levels *clks)
1271571a7a1Sriastradh {
1281571a7a1Sriastradh 	uint32_t disp_clks_in_khz[6] = {
1291571a7a1Sriastradh 			300000, 400000, 496560, 626090, 685720, 757900 };
1301571a7a1Sriastradh 	uint32_t sclks_in_khz[6] = {
1311571a7a1Sriastradh 			300000, 360000, 423530, 514290, 626090, 720000 };
1321571a7a1Sriastradh 	uint32_t mclks_in_khz[2] = { 333000, 800000 };
1331571a7a1Sriastradh 
1341571a7a1Sriastradh 	switch (clk_type) {
1351571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
1361571a7a1Sriastradh 		clks->num_levels = 6;
1371571a7a1Sriastradh 		memmove(clks->clocks_in_khz, disp_clks_in_khz,
1381571a7a1Sriastradh 				sizeof(disp_clks_in_khz));
1391571a7a1Sriastradh 		break;
1401571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_ENGINE_CLK:
1411571a7a1Sriastradh 		clks->num_levels = 6;
1421571a7a1Sriastradh 		memmove(clks->clocks_in_khz, sclks_in_khz,
1431571a7a1Sriastradh 				sizeof(sclks_in_khz));
1441571a7a1Sriastradh 		break;
1451571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_MEMORY_CLK:
1461571a7a1Sriastradh 		clks->num_levels = 2;
1471571a7a1Sriastradh 		memmove(clks->clocks_in_khz, mclks_in_khz,
1481571a7a1Sriastradh 				sizeof(mclks_in_khz));
1491571a7a1Sriastradh 		break;
1501571a7a1Sriastradh 	default:
1511571a7a1Sriastradh 		clks->num_levels = 0;
1521571a7a1Sriastradh 		break;
1531571a7a1Sriastradh 	}
1541571a7a1Sriastradh }
1551571a7a1Sriastradh 
dc_to_smu_clock_type(enum dm_pp_clock_type dm_pp_clk_type)1561571a7a1Sriastradh static enum smu_clk_type dc_to_smu_clock_type(
1571571a7a1Sriastradh 		enum dm_pp_clock_type dm_pp_clk_type)
1581571a7a1Sriastradh {
1591571a7a1Sriastradh 	enum smu_clk_type smu_clk_type = SMU_CLK_COUNT;
1601571a7a1Sriastradh 
1611571a7a1Sriastradh 	switch (dm_pp_clk_type) {
1621571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
1631571a7a1Sriastradh 		smu_clk_type = SMU_DISPCLK;
1641571a7a1Sriastradh 		break;
1651571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_ENGINE_CLK:
1661571a7a1Sriastradh 		smu_clk_type = SMU_GFXCLK;
1671571a7a1Sriastradh 		break;
1681571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_MEMORY_CLK:
1691571a7a1Sriastradh 		smu_clk_type = SMU_MCLK;
1701571a7a1Sriastradh 		break;
1711571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DCEFCLK:
1721571a7a1Sriastradh 		smu_clk_type = SMU_DCEFCLK;
1731571a7a1Sriastradh 		break;
1741571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_SOCCLK:
1751571a7a1Sriastradh 		smu_clk_type = SMU_SOCCLK;
1761571a7a1Sriastradh 		break;
1771571a7a1Sriastradh 	default:
1781571a7a1Sriastradh 		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
1791571a7a1Sriastradh 			  dm_pp_clk_type);
1801571a7a1Sriastradh 		break;
1811571a7a1Sriastradh 	}
1821571a7a1Sriastradh 
1831571a7a1Sriastradh 	return smu_clk_type;
1841571a7a1Sriastradh }
1851571a7a1Sriastradh 
dc_to_pp_clock_type(enum dm_pp_clock_type dm_pp_clk_type)1861571a7a1Sriastradh static enum amd_pp_clock_type dc_to_pp_clock_type(
1871571a7a1Sriastradh 		enum dm_pp_clock_type dm_pp_clk_type)
1881571a7a1Sriastradh {
1891571a7a1Sriastradh 	enum amd_pp_clock_type amd_pp_clk_type = 0;
1901571a7a1Sriastradh 
1911571a7a1Sriastradh 	switch (dm_pp_clk_type) {
1921571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
1931571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_disp_clock;
1941571a7a1Sriastradh 		break;
1951571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_ENGINE_CLK:
1961571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_sys_clock;
1971571a7a1Sriastradh 		break;
1981571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_MEMORY_CLK:
1991571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_mem_clock;
2001571a7a1Sriastradh 		break;
2011571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DCEFCLK:
2021571a7a1Sriastradh 		amd_pp_clk_type  = amd_pp_dcef_clock;
2031571a7a1Sriastradh 		break;
2041571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DCFCLK:
2051571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_dcf_clock;
2061571a7a1Sriastradh 		break;
2071571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_PIXELCLK:
2081571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_pixel_clock;
2091571a7a1Sriastradh 		break;
2101571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_FCLK:
2111571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_f_clock;
2121571a7a1Sriastradh 		break;
2131571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
2141571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_phy_clock;
2151571a7a1Sriastradh 		break;
2161571a7a1Sriastradh 	case DM_PP_CLOCK_TYPE_DPPCLK:
2171571a7a1Sriastradh 		amd_pp_clk_type = amd_pp_dpp_clock;
2181571a7a1Sriastradh 		break;
2191571a7a1Sriastradh 	default:
2201571a7a1Sriastradh 		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
2211571a7a1Sriastradh 				dm_pp_clk_type);
2221571a7a1Sriastradh 		break;
2231571a7a1Sriastradh 	}
2241571a7a1Sriastradh 
2251571a7a1Sriastradh 	return amd_pp_clk_type;
2261571a7a1Sriastradh }
2271571a7a1Sriastradh 
pp_to_dc_powerlevel_state(enum PP_DAL_POWERLEVEL max_clocks_state)2281571a7a1Sriastradh static enum dm_pp_clocks_state pp_to_dc_powerlevel_state(
2291571a7a1Sriastradh 			enum PP_DAL_POWERLEVEL max_clocks_state)
2301571a7a1Sriastradh {
2311571a7a1Sriastradh 	switch (max_clocks_state) {
2321571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_0:
2331571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_0;
2341571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_1:
2351571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_1;
2361571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_2:
2371571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_2;
2381571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_3:
2391571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_3;
2401571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_4:
2411571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_4;
2421571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_5:
2431571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_5;
2441571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_6:
2451571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_6;
2461571a7a1Sriastradh 	case PP_DAL_POWERLEVEL_7:
2471571a7a1Sriastradh 		return DM_PP_CLOCKS_DPM_STATE_LEVEL_7;
2481571a7a1Sriastradh 	default:
2491571a7a1Sriastradh 		DRM_ERROR("DM_PPLIB: invalid powerlevel state: %d!\n",
2501571a7a1Sriastradh 				max_clocks_state);
2511571a7a1Sriastradh 		return DM_PP_CLOCKS_STATE_INVALID;
2521571a7a1Sriastradh 	}
2531571a7a1Sriastradh }
2541571a7a1Sriastradh 
pp_to_dc_clock_levels(const struct amd_pp_clocks * pp_clks,struct dm_pp_clock_levels * dc_clks,enum dm_pp_clock_type dc_clk_type)2551571a7a1Sriastradh static void pp_to_dc_clock_levels(
2561571a7a1Sriastradh 		const struct amd_pp_clocks *pp_clks,
2571571a7a1Sriastradh 		struct dm_pp_clock_levels *dc_clks,
2581571a7a1Sriastradh 		enum dm_pp_clock_type dc_clk_type)
2591571a7a1Sriastradh {
2601571a7a1Sriastradh 	uint32_t i;
2611571a7a1Sriastradh 
2621571a7a1Sriastradh 	if (pp_clks->count > DM_PP_MAX_CLOCK_LEVELS) {
2631571a7a1Sriastradh 		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
2641571a7a1Sriastradh 				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
2651571a7a1Sriastradh 				pp_clks->count,
2661571a7a1Sriastradh 				DM_PP_MAX_CLOCK_LEVELS);
2671571a7a1Sriastradh 
2681571a7a1Sriastradh 		dc_clks->num_levels = DM_PP_MAX_CLOCK_LEVELS;
2691571a7a1Sriastradh 	} else
2701571a7a1Sriastradh 		dc_clks->num_levels = pp_clks->count;
2711571a7a1Sriastradh 
2721571a7a1Sriastradh 	DRM_INFO("DM_PPLIB: values for %s clock\n",
2731571a7a1Sriastradh 			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
2741571a7a1Sriastradh 
2751571a7a1Sriastradh 	for (i = 0; i < dc_clks->num_levels; i++) {
2761571a7a1Sriastradh 		DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
2771571a7a1Sriastradh 		dc_clks->clocks_in_khz[i] = pp_clks->clock[i];
2781571a7a1Sriastradh 	}
2791571a7a1Sriastradh }
2801571a7a1Sriastradh 
pp_to_dc_clock_levels_with_latency(const struct pp_clock_levels_with_latency * pp_clks,struct dm_pp_clock_levels_with_latency * clk_level_info,enum dm_pp_clock_type dc_clk_type)2811571a7a1Sriastradh static void pp_to_dc_clock_levels_with_latency(
2821571a7a1Sriastradh 		const struct pp_clock_levels_with_latency *pp_clks,
2831571a7a1Sriastradh 		struct dm_pp_clock_levels_with_latency *clk_level_info,
2841571a7a1Sriastradh 		enum dm_pp_clock_type dc_clk_type)
2851571a7a1Sriastradh {
2861571a7a1Sriastradh 	uint32_t i;
2871571a7a1Sriastradh 
2881571a7a1Sriastradh 	if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
2891571a7a1Sriastradh 		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
2901571a7a1Sriastradh 				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
2911571a7a1Sriastradh 				pp_clks->num_levels,
2921571a7a1Sriastradh 				DM_PP_MAX_CLOCK_LEVELS);
2931571a7a1Sriastradh 
2941571a7a1Sriastradh 		clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
2951571a7a1Sriastradh 	} else
2961571a7a1Sriastradh 		clk_level_info->num_levels = pp_clks->num_levels;
2971571a7a1Sriastradh 
2981571a7a1Sriastradh 	DRM_DEBUG("DM_PPLIB: values for %s clock\n",
2991571a7a1Sriastradh 			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
3001571a7a1Sriastradh 
3011571a7a1Sriastradh 	for (i = 0; i < clk_level_info->num_levels; i++) {
3021571a7a1Sriastradh 		DRM_DEBUG("DM_PPLIB:\t %d in kHz\n", pp_clks->data[i].clocks_in_khz);
3031571a7a1Sriastradh 		clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz;
3041571a7a1Sriastradh 		clk_level_info->data[i].latency_in_us = pp_clks->data[i].latency_in_us;
3051571a7a1Sriastradh 	}
3061571a7a1Sriastradh }
3071571a7a1Sriastradh 
pp_to_dc_clock_levels_with_voltage(const struct pp_clock_levels_with_voltage * pp_clks,struct dm_pp_clock_levels_with_voltage * clk_level_info,enum dm_pp_clock_type dc_clk_type)3081571a7a1Sriastradh static void pp_to_dc_clock_levels_with_voltage(
3091571a7a1Sriastradh 		const struct pp_clock_levels_with_voltage *pp_clks,
3101571a7a1Sriastradh 		struct dm_pp_clock_levels_with_voltage *clk_level_info,
3111571a7a1Sriastradh 		enum dm_pp_clock_type dc_clk_type)
3121571a7a1Sriastradh {
3131571a7a1Sriastradh 	uint32_t i;
3141571a7a1Sriastradh 
3151571a7a1Sriastradh 	if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
3161571a7a1Sriastradh 		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
3171571a7a1Sriastradh 				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
3181571a7a1Sriastradh 				pp_clks->num_levels,
3191571a7a1Sriastradh 				DM_PP_MAX_CLOCK_LEVELS);
3201571a7a1Sriastradh 
3211571a7a1Sriastradh 		clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
3221571a7a1Sriastradh 	} else
3231571a7a1Sriastradh 		clk_level_info->num_levels = pp_clks->num_levels;
3241571a7a1Sriastradh 
3251571a7a1Sriastradh 	DRM_INFO("DM_PPLIB: values for %s clock\n",
3261571a7a1Sriastradh 			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
3271571a7a1Sriastradh 
3281571a7a1Sriastradh 	for (i = 0; i < clk_level_info->num_levels; i++) {
3291571a7a1Sriastradh 		DRM_INFO("DM_PPLIB:\t %d in kHz, %d in mV\n", pp_clks->data[i].clocks_in_khz,
3301571a7a1Sriastradh 			 pp_clks->data[i].voltage_in_mv);
3311571a7a1Sriastradh 		clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz;
3321571a7a1Sriastradh 		clk_level_info->data[i].voltage_in_mv = pp_clks->data[i].voltage_in_mv;
3331571a7a1Sriastradh 	}
3341571a7a1Sriastradh }
3351571a7a1Sriastradh 
dm_pp_get_clock_levels_by_type(const struct dc_context * ctx,enum dm_pp_clock_type clk_type,struct dm_pp_clock_levels * dc_clks)3361571a7a1Sriastradh bool dm_pp_get_clock_levels_by_type(
3371571a7a1Sriastradh 		const struct dc_context *ctx,
3381571a7a1Sriastradh 		enum dm_pp_clock_type clk_type,
3391571a7a1Sriastradh 		struct dm_pp_clock_levels *dc_clks)
3401571a7a1Sriastradh {
3411571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
3421571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
3431571a7a1Sriastradh 	struct amd_pp_clocks pp_clks = { 0 };
3441571a7a1Sriastradh 	struct amd_pp_simple_clock_info validation_clks = { 0 };
3451571a7a1Sriastradh 	uint32_t i;
3461571a7a1Sriastradh 
3471571a7a1Sriastradh 	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) {
3481571a7a1Sriastradh 		if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle,
3491571a7a1Sriastradh 			dc_to_pp_clock_type(clk_type), &pp_clks)) {
3501571a7a1Sriastradh 			/* Error in pplib. Provide default values. */
3511571a7a1Sriastradh 			get_default_clock_levels(clk_type, dc_clks);
3521571a7a1Sriastradh 			return true;
3531571a7a1Sriastradh 		}
3541571a7a1Sriastradh 	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_clock_by_type) {
3551571a7a1Sriastradh 		if (smu_get_clock_by_type(&adev->smu,
3561571a7a1Sriastradh 					  dc_to_pp_clock_type(clk_type),
3571571a7a1Sriastradh 					  &pp_clks)) {
3581571a7a1Sriastradh 			get_default_clock_levels(clk_type, dc_clks);
3591571a7a1Sriastradh 			return true;
3601571a7a1Sriastradh 		}
3611571a7a1Sriastradh 	}
3621571a7a1Sriastradh 
3631571a7a1Sriastradh 	pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
3641571a7a1Sriastradh 
3651571a7a1Sriastradh 	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_display_mode_validation_clocks) {
3661571a7a1Sriastradh 		if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks(
3671571a7a1Sriastradh 						pp_handle, &validation_clks)) {
3681571a7a1Sriastradh 			/* Error in pplib. Provide default values. */
3691571a7a1Sriastradh 			DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
3701571a7a1Sriastradh 			validation_clks.engine_max_clock = 72000;
3711571a7a1Sriastradh 			validation_clks.memory_max_clock = 80000;
3721571a7a1Sriastradh 			validation_clks.level = 0;
3731571a7a1Sriastradh 		}
3741571a7a1Sriastradh 	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_max_high_clocks) {
3751571a7a1Sriastradh 		if (smu_get_max_high_clocks(&adev->smu, &validation_clks)) {
3761571a7a1Sriastradh 			DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
3771571a7a1Sriastradh 			validation_clks.engine_max_clock = 72000;
3781571a7a1Sriastradh 			validation_clks.memory_max_clock = 80000;
3791571a7a1Sriastradh 			validation_clks.level = 0;
3801571a7a1Sriastradh 		}
3811571a7a1Sriastradh 	}
3821571a7a1Sriastradh 
3831571a7a1Sriastradh 	DRM_INFO("DM_PPLIB: Validation clocks:\n");
3841571a7a1Sriastradh 	DRM_INFO("DM_PPLIB:    engine_max_clock: %d\n",
3851571a7a1Sriastradh 			validation_clks.engine_max_clock);
3861571a7a1Sriastradh 	DRM_INFO("DM_PPLIB:    memory_max_clock: %d\n",
3871571a7a1Sriastradh 			validation_clks.memory_max_clock);
3881571a7a1Sriastradh 	DRM_INFO("DM_PPLIB:    level           : %d\n",
3891571a7a1Sriastradh 			validation_clks.level);
3901571a7a1Sriastradh 
3911571a7a1Sriastradh 	/* Translate 10 kHz to kHz. */
3921571a7a1Sriastradh 	validation_clks.engine_max_clock *= 10;
3931571a7a1Sriastradh 	validation_clks.memory_max_clock *= 10;
3941571a7a1Sriastradh 
3951571a7a1Sriastradh 	/* Determine the highest non-boosted level from the Validation Clocks */
3961571a7a1Sriastradh 	if (clk_type == DM_PP_CLOCK_TYPE_ENGINE_CLK) {
3971571a7a1Sriastradh 		for (i = 0; i < dc_clks->num_levels; i++) {
3981571a7a1Sriastradh 			if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
3991571a7a1Sriastradh 				/* This clock is higher the validation clock.
4001571a7a1Sriastradh 				 * Than means the previous one is the highest
4011571a7a1Sriastradh 				 * non-boosted one. */
4021571a7a1Sriastradh 				DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
4031571a7a1Sriastradh 						dc_clks->num_levels, i);
4041571a7a1Sriastradh 				dc_clks->num_levels = i > 0 ? i : 1;
4051571a7a1Sriastradh 				break;
4061571a7a1Sriastradh 			}
4071571a7a1Sriastradh 		}
4081571a7a1Sriastradh 	} else if (clk_type == DM_PP_CLOCK_TYPE_MEMORY_CLK) {
4091571a7a1Sriastradh 		for (i = 0; i < dc_clks->num_levels; i++) {
4101571a7a1Sriastradh 			if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
4111571a7a1Sriastradh 				DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
4121571a7a1Sriastradh 						dc_clks->num_levels, i);
4131571a7a1Sriastradh 				dc_clks->num_levels = i > 0 ? i : 1;
4141571a7a1Sriastradh 				break;
4151571a7a1Sriastradh 			}
4161571a7a1Sriastradh 		}
4171571a7a1Sriastradh 	}
4181571a7a1Sriastradh 
4191571a7a1Sriastradh 	return true;
4201571a7a1Sriastradh }
4211571a7a1Sriastradh 
dm_pp_get_clock_levels_by_type_with_latency(const struct dc_context * ctx,enum dm_pp_clock_type clk_type,struct dm_pp_clock_levels_with_latency * clk_level_info)4221571a7a1Sriastradh bool dm_pp_get_clock_levels_by_type_with_latency(
4231571a7a1Sriastradh 	const struct dc_context *ctx,
4241571a7a1Sriastradh 	enum dm_pp_clock_type clk_type,
4251571a7a1Sriastradh 	struct dm_pp_clock_levels_with_latency *clk_level_info)
4261571a7a1Sriastradh {
4271571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
4281571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
4291571a7a1Sriastradh 	struct pp_clock_levels_with_latency pp_clks = { 0 };
4301571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
4311571a7a1Sriastradh 	int ret;
4321571a7a1Sriastradh 
4331571a7a1Sriastradh 	if (pp_funcs && pp_funcs->get_clock_by_type_with_latency) {
4341571a7a1Sriastradh 		ret = pp_funcs->get_clock_by_type_with_latency(pp_handle,
4351571a7a1Sriastradh 						dc_to_pp_clock_type(clk_type),
4361571a7a1Sriastradh 						&pp_clks);
4371571a7a1Sriastradh 		if (ret)
4381571a7a1Sriastradh 			return false;
4391571a7a1Sriastradh 	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_clock_by_type_with_latency) {
4401571a7a1Sriastradh 		if (smu_get_clock_by_type_with_latency(&adev->smu,
4411571a7a1Sriastradh 						       dc_to_smu_clock_type(clk_type),
4421571a7a1Sriastradh 						       &pp_clks))
4431571a7a1Sriastradh 			return false;
4441571a7a1Sriastradh 	}
4451571a7a1Sriastradh 
4461571a7a1Sriastradh 
4471571a7a1Sriastradh 	pp_to_dc_clock_levels_with_latency(&pp_clks, clk_level_info, clk_type);
4481571a7a1Sriastradh 
4491571a7a1Sriastradh 	return true;
4501571a7a1Sriastradh }
4511571a7a1Sriastradh 
dm_pp_get_clock_levels_by_type_with_voltage(const struct dc_context * ctx,enum dm_pp_clock_type clk_type,struct dm_pp_clock_levels_with_voltage * clk_level_info)4521571a7a1Sriastradh bool dm_pp_get_clock_levels_by_type_with_voltage(
4531571a7a1Sriastradh 	const struct dc_context *ctx,
4541571a7a1Sriastradh 	enum dm_pp_clock_type clk_type,
4551571a7a1Sriastradh 	struct dm_pp_clock_levels_with_voltage *clk_level_info)
4561571a7a1Sriastradh {
4571571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
4581571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
4591571a7a1Sriastradh 	struct pp_clock_levels_with_voltage pp_clk_info = {0};
4601571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
4611571a7a1Sriastradh 	int ret;
4621571a7a1Sriastradh 
4631571a7a1Sriastradh 	if (pp_funcs && pp_funcs->get_clock_by_type_with_voltage) {
4641571a7a1Sriastradh 		ret = pp_funcs->get_clock_by_type_with_voltage(pp_handle,
4651571a7a1Sriastradh 						dc_to_pp_clock_type(clk_type),
4661571a7a1Sriastradh 						&pp_clk_info);
4671571a7a1Sriastradh 		if (ret)
4681571a7a1Sriastradh 			return false;
4691571a7a1Sriastradh 	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_clock_by_type_with_voltage) {
4701571a7a1Sriastradh 		if (smu_get_clock_by_type_with_voltage(&adev->smu,
4711571a7a1Sriastradh 						       dc_to_pp_clock_type(clk_type),
4721571a7a1Sriastradh 						       &pp_clk_info))
4731571a7a1Sriastradh 			return false;
4741571a7a1Sriastradh 	}
4751571a7a1Sriastradh 
4761571a7a1Sriastradh 	pp_to_dc_clock_levels_with_voltage(&pp_clk_info, clk_level_info, clk_type);
4771571a7a1Sriastradh 
4781571a7a1Sriastradh 	return true;
4791571a7a1Sriastradh }
4801571a7a1Sriastradh 
dm_pp_notify_wm_clock_changes(const struct dc_context * ctx,struct dm_pp_wm_sets_with_clock_ranges * wm_with_clock_ranges)4811571a7a1Sriastradh bool dm_pp_notify_wm_clock_changes(
4821571a7a1Sriastradh 	const struct dc_context *ctx,
4831571a7a1Sriastradh 	struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges)
4841571a7a1Sriastradh {
4851571a7a1Sriastradh 	/* TODO: to be implemented */
4861571a7a1Sriastradh 	return false;
4871571a7a1Sriastradh }
4881571a7a1Sriastradh 
dm_pp_apply_power_level_change_request(const struct dc_context * ctx,struct dm_pp_power_level_change_request * level_change_req)4891571a7a1Sriastradh bool dm_pp_apply_power_level_change_request(
4901571a7a1Sriastradh 	const struct dc_context *ctx,
4911571a7a1Sriastradh 	struct dm_pp_power_level_change_request *level_change_req)
4921571a7a1Sriastradh {
4931571a7a1Sriastradh 	/* TODO: to be implemented */
4941571a7a1Sriastradh 	return false;
4951571a7a1Sriastradh }
4961571a7a1Sriastradh 
dm_pp_apply_clock_for_voltage_request(const struct dc_context * ctx,struct dm_pp_clock_for_voltage_req * clock_for_voltage_req)4971571a7a1Sriastradh bool dm_pp_apply_clock_for_voltage_request(
4981571a7a1Sriastradh 	const struct dc_context *ctx,
4991571a7a1Sriastradh 	struct dm_pp_clock_for_voltage_req *clock_for_voltage_req)
5001571a7a1Sriastradh {
5011571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
5021571a7a1Sriastradh 	struct pp_display_clock_request pp_clock_request = {0};
5031571a7a1Sriastradh 	int ret = 0;
5041571a7a1Sriastradh 
5051571a7a1Sriastradh 	pp_clock_request.clock_type = dc_to_pp_clock_type(clock_for_voltage_req->clk_type);
5061571a7a1Sriastradh 	pp_clock_request.clock_freq_in_khz = clock_for_voltage_req->clocks_in_khz;
5071571a7a1Sriastradh 
5081571a7a1Sriastradh 	if (!pp_clock_request.clock_type)
5091571a7a1Sriastradh 		return false;
5101571a7a1Sriastradh 
5111571a7a1Sriastradh 	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_clock_voltage_request)
5121571a7a1Sriastradh 		ret = adev->powerplay.pp_funcs->display_clock_voltage_request(
5131571a7a1Sriastradh 			adev->powerplay.pp_handle,
5141571a7a1Sriastradh 			&pp_clock_request);
5151571a7a1Sriastradh 	else if (adev->smu.ppt_funcs &&
5161571a7a1Sriastradh 		 adev->smu.ppt_funcs->display_clock_voltage_request)
5171571a7a1Sriastradh 		ret = smu_display_clock_voltage_request(&adev->smu,
5181571a7a1Sriastradh 							&pp_clock_request);
5191571a7a1Sriastradh 	if (ret)
5201571a7a1Sriastradh 		return false;
5211571a7a1Sriastradh 	return true;
5221571a7a1Sriastradh }
5231571a7a1Sriastradh 
dm_pp_get_static_clocks(const struct dc_context * ctx,struct dm_pp_static_clock_info * static_clk_info)5241571a7a1Sriastradh bool dm_pp_get_static_clocks(
5251571a7a1Sriastradh 	const struct dc_context *ctx,
5261571a7a1Sriastradh 	struct dm_pp_static_clock_info *static_clk_info)
5271571a7a1Sriastradh {
5281571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
5291571a7a1Sriastradh 	struct amd_pp_clock_info pp_clk_info = {0};
5301571a7a1Sriastradh 	int ret = 0;
5311571a7a1Sriastradh 
5321571a7a1Sriastradh 	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_current_clocks)
5331571a7a1Sriastradh 		ret = adev->powerplay.pp_funcs->get_current_clocks(
5341571a7a1Sriastradh 			adev->powerplay.pp_handle,
5351571a7a1Sriastradh 			&pp_clk_info);
5361571a7a1Sriastradh 	else if (adev->smu.ppt_funcs)
5371571a7a1Sriastradh 		ret = smu_get_current_clocks(&adev->smu, &pp_clk_info);
5381571a7a1Sriastradh 	if (ret)
5391571a7a1Sriastradh 		return false;
5401571a7a1Sriastradh 
5411571a7a1Sriastradh 	static_clk_info->max_clocks_state = pp_to_dc_powerlevel_state(pp_clk_info.max_clocks_state);
5421571a7a1Sriastradh 	static_clk_info->max_mclk_khz = pp_clk_info.max_memory_clock * 10;
5431571a7a1Sriastradh 	static_clk_info->max_sclk_khz = pp_clk_info.max_engine_clock * 10;
5441571a7a1Sriastradh 
5451571a7a1Sriastradh 	return true;
5461571a7a1Sriastradh }
5471571a7a1Sriastradh 
pp_rv_set_wm_ranges(struct pp_smu * pp,struct pp_smu_wm_range_sets * ranges)5481571a7a1Sriastradh void pp_rv_set_wm_ranges(struct pp_smu *pp,
5491571a7a1Sriastradh 		struct pp_smu_wm_range_sets *ranges)
5501571a7a1Sriastradh {
5511571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
5521571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
5531571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
5541571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
5551571a7a1Sriastradh 	struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
5561571a7a1Sriastradh 	struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks = wm_with_clock_ranges.wm_dmif_clocks_ranges;
5571571a7a1Sriastradh 	struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks = wm_with_clock_ranges.wm_mcif_clocks_ranges;
5581571a7a1Sriastradh 	int32_t i;
5591571a7a1Sriastradh 
5601571a7a1Sriastradh 	wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
5611571a7a1Sriastradh 	wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
5621571a7a1Sriastradh 
5631571a7a1Sriastradh 	for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
5641571a7a1Sriastradh 		if (ranges->reader_wm_sets[i].wm_inst > 3)
5651571a7a1Sriastradh 			wm_dce_clocks[i].wm_set_id = WM_SET_A;
5661571a7a1Sriastradh 		else
5671571a7a1Sriastradh 			wm_dce_clocks[i].wm_set_id =
5681571a7a1Sriastradh 					ranges->reader_wm_sets[i].wm_inst;
5691571a7a1Sriastradh 		wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
5701571a7a1Sriastradh 				ranges->reader_wm_sets[i].max_drain_clk_mhz * 1000;
5711571a7a1Sriastradh 		wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
5721571a7a1Sriastradh 				ranges->reader_wm_sets[i].min_drain_clk_mhz * 1000;
5731571a7a1Sriastradh 		wm_dce_clocks[i].wm_max_mem_clk_in_khz =
5741571a7a1Sriastradh 				ranges->reader_wm_sets[i].max_fill_clk_mhz * 1000;
5751571a7a1Sriastradh 		wm_dce_clocks[i].wm_min_mem_clk_in_khz =
5761571a7a1Sriastradh 				ranges->reader_wm_sets[i].min_fill_clk_mhz * 1000;
5771571a7a1Sriastradh 	}
5781571a7a1Sriastradh 
5791571a7a1Sriastradh 	for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
5801571a7a1Sriastradh 		if (ranges->writer_wm_sets[i].wm_inst > 3)
5811571a7a1Sriastradh 			wm_soc_clocks[i].wm_set_id = WM_SET_A;
5821571a7a1Sriastradh 		else
5831571a7a1Sriastradh 			wm_soc_clocks[i].wm_set_id =
5841571a7a1Sriastradh 					ranges->writer_wm_sets[i].wm_inst;
5851571a7a1Sriastradh 		wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
5861571a7a1Sriastradh 				ranges->writer_wm_sets[i].max_fill_clk_mhz * 1000;
5871571a7a1Sriastradh 		wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
5881571a7a1Sriastradh 				ranges->writer_wm_sets[i].min_fill_clk_mhz * 1000;
5891571a7a1Sriastradh 		wm_soc_clocks[i].wm_max_mem_clk_in_khz =
5901571a7a1Sriastradh 				ranges->writer_wm_sets[i].max_drain_clk_mhz * 1000;
5911571a7a1Sriastradh 		wm_soc_clocks[i].wm_min_mem_clk_in_khz =
5921571a7a1Sriastradh 				ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000;
5931571a7a1Sriastradh 	}
5941571a7a1Sriastradh 
5951571a7a1Sriastradh 	if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges)
5961571a7a1Sriastradh 		pp_funcs->set_watermarks_for_clocks_ranges(pp_handle,
5971571a7a1Sriastradh 							   &wm_with_clock_ranges);
5981571a7a1Sriastradh 	else
5991571a7a1Sriastradh 		smu_set_watermarks_for_clock_ranges(&adev->smu,
6001571a7a1Sriastradh 				&wm_with_clock_ranges);
6011571a7a1Sriastradh }
6021571a7a1Sriastradh 
pp_rv_set_pme_wa_enable(struct pp_smu * pp)6031571a7a1Sriastradh void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
6041571a7a1Sriastradh {
6051571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
6061571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
6071571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
6081571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
6091571a7a1Sriastradh 
6101571a7a1Sriastradh 	if (pp_funcs && pp_funcs->notify_smu_enable_pwe)
6111571a7a1Sriastradh 		pp_funcs->notify_smu_enable_pwe(pp_handle);
6121571a7a1Sriastradh 	else if (adev->smu.ppt_funcs)
6131571a7a1Sriastradh 		smu_notify_smu_enable_pwe(&adev->smu);
6141571a7a1Sriastradh }
6151571a7a1Sriastradh 
pp_rv_set_active_display_count(struct pp_smu * pp,int count)6161571a7a1Sriastradh void pp_rv_set_active_display_count(struct pp_smu *pp, int count)
6171571a7a1Sriastradh {
6181571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
6191571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
6201571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
6211571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
6221571a7a1Sriastradh 
6231571a7a1Sriastradh 	if (!pp_funcs || !pp_funcs->set_active_display_count)
6241571a7a1Sriastradh 		return;
6251571a7a1Sriastradh 
6261571a7a1Sriastradh 	pp_funcs->set_active_display_count(pp_handle, count);
6271571a7a1Sriastradh }
6281571a7a1Sriastradh 
pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu * pp,int clock)6291571a7a1Sriastradh void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock)
6301571a7a1Sriastradh {
6311571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
6321571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
6331571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
6341571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
6351571a7a1Sriastradh 
6361571a7a1Sriastradh 	if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk)
6371571a7a1Sriastradh 		return;
6381571a7a1Sriastradh 
6391571a7a1Sriastradh 	pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, clock);
6401571a7a1Sriastradh }
6411571a7a1Sriastradh 
pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu * pp,int clock)6421571a7a1Sriastradh void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock)
6431571a7a1Sriastradh {
6441571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
6451571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
6461571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
6471571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
6481571a7a1Sriastradh 
6491571a7a1Sriastradh 	if (!pp_funcs || !pp_funcs->set_hard_min_dcefclk_by_freq)
6501571a7a1Sriastradh 		return;
6511571a7a1Sriastradh 
6521571a7a1Sriastradh 	pp_funcs->set_hard_min_dcefclk_by_freq(pp_handle, clock);
6531571a7a1Sriastradh }
6541571a7a1Sriastradh 
pp_rv_set_hard_min_fclk_by_freq(struct pp_smu * pp,int mhz)6551571a7a1Sriastradh void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz)
6561571a7a1Sriastradh {
6571571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
6581571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
6591571a7a1Sriastradh 	void *pp_handle = adev->powerplay.pp_handle;
6601571a7a1Sriastradh 	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
6611571a7a1Sriastradh 
6621571a7a1Sriastradh 	if (!pp_funcs || !pp_funcs->set_hard_min_fclk_by_freq)
6631571a7a1Sriastradh 		return;
6641571a7a1Sriastradh 
6651571a7a1Sriastradh 	pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz);
6661571a7a1Sriastradh }
6671571a7a1Sriastradh 
pp_nv_set_wm_ranges(struct pp_smu * pp,struct pp_smu_wm_range_sets * ranges)6681571a7a1Sriastradh enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
6691571a7a1Sriastradh 		struct pp_smu_wm_range_sets *ranges)
6701571a7a1Sriastradh {
6711571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
6721571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
6731571a7a1Sriastradh 	struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
6741571a7a1Sriastradh 	struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks =
6751571a7a1Sriastradh 			wm_with_clock_ranges.wm_dmif_clocks_ranges;
6761571a7a1Sriastradh 	struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks =
6771571a7a1Sriastradh 			wm_with_clock_ranges.wm_mcif_clocks_ranges;
6781571a7a1Sriastradh 	int32_t i;
6791571a7a1Sriastradh 
6801571a7a1Sriastradh 	wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
6811571a7a1Sriastradh 	wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
6821571a7a1Sriastradh 
6831571a7a1Sriastradh 	for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
6841571a7a1Sriastradh 		if (ranges->reader_wm_sets[i].wm_inst > 3)
6851571a7a1Sriastradh 			wm_dce_clocks[i].wm_set_id = WM_SET_A;
6861571a7a1Sriastradh 		else
6871571a7a1Sriastradh 			wm_dce_clocks[i].wm_set_id =
6881571a7a1Sriastradh 					ranges->reader_wm_sets[i].wm_inst;
6891571a7a1Sriastradh 		wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
6901571a7a1Sriastradh 			ranges->reader_wm_sets[i].max_drain_clk_mhz * 1000;
6911571a7a1Sriastradh 		wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
6921571a7a1Sriastradh 			ranges->reader_wm_sets[i].min_drain_clk_mhz * 1000;
6931571a7a1Sriastradh 		wm_dce_clocks[i].wm_max_mem_clk_in_khz =
6941571a7a1Sriastradh 			ranges->reader_wm_sets[i].max_fill_clk_mhz * 1000;
6951571a7a1Sriastradh 		wm_dce_clocks[i].wm_min_mem_clk_in_khz =
6961571a7a1Sriastradh 			ranges->reader_wm_sets[i].min_fill_clk_mhz * 1000;
6971571a7a1Sriastradh 	}
6981571a7a1Sriastradh 
6991571a7a1Sriastradh 	for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
7001571a7a1Sriastradh 		if (ranges->writer_wm_sets[i].wm_inst > 3)
7011571a7a1Sriastradh 			wm_soc_clocks[i].wm_set_id = WM_SET_A;
7021571a7a1Sriastradh 		else
7031571a7a1Sriastradh 			wm_soc_clocks[i].wm_set_id =
7041571a7a1Sriastradh 					ranges->writer_wm_sets[i].wm_inst;
7051571a7a1Sriastradh 		wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
7061571a7a1Sriastradh 			ranges->writer_wm_sets[i].max_fill_clk_mhz * 1000;
7071571a7a1Sriastradh 		wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
7081571a7a1Sriastradh 			ranges->writer_wm_sets[i].min_fill_clk_mhz * 1000;
7091571a7a1Sriastradh 		wm_soc_clocks[i].wm_max_mem_clk_in_khz =
7101571a7a1Sriastradh 			ranges->writer_wm_sets[i].max_drain_clk_mhz * 1000;
7111571a7a1Sriastradh 		wm_soc_clocks[i].wm_min_mem_clk_in_khz =
7121571a7a1Sriastradh 			ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000;
7131571a7a1Sriastradh 	}
7141571a7a1Sriastradh 
7151571a7a1Sriastradh 	smu_set_watermarks_for_clock_ranges(&adev->smu,	&wm_with_clock_ranges);
7161571a7a1Sriastradh 
7171571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
7181571a7a1Sriastradh }
7191571a7a1Sriastradh 
pp_nv_set_pme_wa_enable(struct pp_smu * pp)7201571a7a1Sriastradh enum pp_smu_status pp_nv_set_pme_wa_enable(struct pp_smu *pp)
7211571a7a1Sriastradh {
7221571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
7231571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
7241571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
7251571a7a1Sriastradh 
7261571a7a1Sriastradh 	if (!smu->ppt_funcs)
7271571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
7281571a7a1Sriastradh 
7291571a7a1Sriastradh 	/* 0: successful or smu.ppt_funcs->set_azalia_d3_pme = NULL;  1: fail */
7301571a7a1Sriastradh 	if (smu_set_azalia_d3_pme(smu))
7311571a7a1Sriastradh 		return PP_SMU_RESULT_FAIL;
7321571a7a1Sriastradh 
7331571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
7341571a7a1Sriastradh }
7351571a7a1Sriastradh 
pp_nv_set_display_count(struct pp_smu * pp,int count)7361571a7a1Sriastradh enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count)
7371571a7a1Sriastradh {
7381571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
7391571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
7401571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
7411571a7a1Sriastradh 
7421571a7a1Sriastradh 	if (!smu->ppt_funcs)
7431571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
7441571a7a1Sriastradh 
7451571a7a1Sriastradh 	/* 0: successful or smu.ppt_funcs->set_display_count = NULL;  1: fail */
7461571a7a1Sriastradh 	if (smu_set_display_count(smu, count))
7471571a7a1Sriastradh 		return PP_SMU_RESULT_FAIL;
7481571a7a1Sriastradh 
7491571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
7501571a7a1Sriastradh }
7511571a7a1Sriastradh 
pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu * pp,int mhz)7521571a7a1Sriastradh enum pp_smu_status pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz)
7531571a7a1Sriastradh {
7541571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
7551571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
7561571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
7571571a7a1Sriastradh 
7581571a7a1Sriastradh 	if (!smu->ppt_funcs)
7591571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
7601571a7a1Sriastradh 
7611571a7a1Sriastradh 	/* 0: successful or smu.ppt_funcs->set_deep_sleep_dcefclk = NULL;1: fail */
7621571a7a1Sriastradh 	if (smu_set_deep_sleep_dcefclk(smu, mhz))
7631571a7a1Sriastradh 		return PP_SMU_RESULT_FAIL;
7641571a7a1Sriastradh 
7651571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
7661571a7a1Sriastradh }
7671571a7a1Sriastradh 
pp_nv_set_hard_min_dcefclk_by_freq(struct pp_smu * pp,int mhz)7681571a7a1Sriastradh enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq(
7691571a7a1Sriastradh 		struct pp_smu *pp, int mhz)
7701571a7a1Sriastradh {
7711571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
7721571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
7731571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
7741571a7a1Sriastradh 	struct pp_display_clock_request clock_req;
7751571a7a1Sriastradh 
7761571a7a1Sriastradh 	if (!smu->ppt_funcs)
7771571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
7781571a7a1Sriastradh 
7791571a7a1Sriastradh 	clock_req.clock_type = amd_pp_dcef_clock;
7801571a7a1Sriastradh 	clock_req.clock_freq_in_khz = mhz * 1000;
7811571a7a1Sriastradh 
7821571a7a1Sriastradh 	/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
7831571a7a1Sriastradh 	 * 1: fail
7841571a7a1Sriastradh 	 */
7851571a7a1Sriastradh 	if (smu_display_clock_voltage_request(smu, &clock_req))
7861571a7a1Sriastradh 		return PP_SMU_RESULT_FAIL;
7871571a7a1Sriastradh 
7881571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
7891571a7a1Sriastradh }
7901571a7a1Sriastradh 
pp_nv_set_hard_min_uclk_by_freq(struct pp_smu * pp,int mhz)7911571a7a1Sriastradh enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz)
7921571a7a1Sriastradh {
7931571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
7941571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
7951571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
7961571a7a1Sriastradh 	struct pp_display_clock_request clock_req;
7971571a7a1Sriastradh 
7981571a7a1Sriastradh 	if (!smu->ppt_funcs)
7991571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
8001571a7a1Sriastradh 
8011571a7a1Sriastradh 	clock_req.clock_type = amd_pp_mem_clock;
8021571a7a1Sriastradh 	clock_req.clock_freq_in_khz = mhz * 1000;
8031571a7a1Sriastradh 
8041571a7a1Sriastradh 	/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
8051571a7a1Sriastradh 	 * 1: fail
8061571a7a1Sriastradh 	 */
8071571a7a1Sriastradh 	if (smu_display_clock_voltage_request(smu, &clock_req))
8081571a7a1Sriastradh 		return PP_SMU_RESULT_FAIL;
8091571a7a1Sriastradh 
8101571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
8111571a7a1Sriastradh }
8121571a7a1Sriastradh 
pp_nv_set_pstate_handshake_support(struct pp_smu * pp,bool pstate_handshake_supported)8131571a7a1Sriastradh enum pp_smu_status pp_nv_set_pstate_handshake_support(
814*54ddf812Sriastradh 	struct pp_smu *pp, bool pstate_handshake_supported)
8151571a7a1Sriastradh {
8161571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
8171571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
8181571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
8191571a7a1Sriastradh 
8201571a7a1Sriastradh 	if (smu_display_disable_memory_clock_switch(smu, !pstate_handshake_supported))
8211571a7a1Sriastradh 		return PP_SMU_RESULT_FAIL;
8221571a7a1Sriastradh 
8231571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
8241571a7a1Sriastradh }
8251571a7a1Sriastradh 
pp_nv_set_voltage_by_freq(struct pp_smu * pp,enum pp_smu_nv_clock_id clock_id,int mhz)8261571a7a1Sriastradh enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp,
8271571a7a1Sriastradh 		enum pp_smu_nv_clock_id clock_id, int mhz)
8281571a7a1Sriastradh {
8291571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
8301571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
8311571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
8321571a7a1Sriastradh 	struct pp_display_clock_request clock_req;
8331571a7a1Sriastradh 
8341571a7a1Sriastradh 	if (!smu->ppt_funcs)
8351571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
8361571a7a1Sriastradh 
8371571a7a1Sriastradh 	switch (clock_id) {
8381571a7a1Sriastradh 	case PP_SMU_NV_DISPCLK:
8391571a7a1Sriastradh 		clock_req.clock_type = amd_pp_disp_clock;
8401571a7a1Sriastradh 		break;
8411571a7a1Sriastradh 	case PP_SMU_NV_PHYCLK:
8421571a7a1Sriastradh 		clock_req.clock_type = amd_pp_phy_clock;
8431571a7a1Sriastradh 		break;
8441571a7a1Sriastradh 	case PP_SMU_NV_PIXELCLK:
8451571a7a1Sriastradh 		clock_req.clock_type = amd_pp_pixel_clock;
8461571a7a1Sriastradh 		break;
8471571a7a1Sriastradh 	default:
8481571a7a1Sriastradh 		break;
8491571a7a1Sriastradh 	}
8501571a7a1Sriastradh 	clock_req.clock_freq_in_khz = mhz * 1000;
8511571a7a1Sriastradh 
8521571a7a1Sriastradh 	/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
8531571a7a1Sriastradh 	 * 1: fail
8541571a7a1Sriastradh 	 */
8551571a7a1Sriastradh 	if (smu_display_clock_voltage_request(smu, &clock_req))
8561571a7a1Sriastradh 		return PP_SMU_RESULT_FAIL;
8571571a7a1Sriastradh 
8581571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
8591571a7a1Sriastradh }
8601571a7a1Sriastradh 
pp_nv_get_maximum_sustainable_clocks(struct pp_smu * pp,struct pp_smu_nv_clock_table * max_clocks)8611571a7a1Sriastradh enum pp_smu_status pp_nv_get_maximum_sustainable_clocks(
8621571a7a1Sriastradh 		struct pp_smu *pp, struct pp_smu_nv_clock_table *max_clocks)
8631571a7a1Sriastradh {
8641571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
8651571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
8661571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
8671571a7a1Sriastradh 
8681571a7a1Sriastradh 	if (!smu->ppt_funcs)
8691571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
8701571a7a1Sriastradh 
8711571a7a1Sriastradh 	if (!smu->ppt_funcs->get_max_sustainable_clocks_by_dc)
8721571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
8731571a7a1Sriastradh 
8741571a7a1Sriastradh 	if (!smu_get_max_sustainable_clocks_by_dc(smu, max_clocks))
8751571a7a1Sriastradh 		return PP_SMU_RESULT_OK;
8761571a7a1Sriastradh 
8771571a7a1Sriastradh 	return PP_SMU_RESULT_FAIL;
8781571a7a1Sriastradh }
8791571a7a1Sriastradh 
pp_nv_get_uclk_dpm_states(struct pp_smu * pp,unsigned int * clock_values_in_khz,unsigned int * num_states)8801571a7a1Sriastradh enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp,
8811571a7a1Sriastradh 		unsigned int *clock_values_in_khz, unsigned int *num_states)
8821571a7a1Sriastradh {
8831571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
8841571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
8851571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
8861571a7a1Sriastradh 
8871571a7a1Sriastradh 	if (!smu->ppt_funcs)
8881571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
8891571a7a1Sriastradh 
8901571a7a1Sriastradh 	if (!smu->ppt_funcs->get_uclk_dpm_states)
8911571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
8921571a7a1Sriastradh 
8931571a7a1Sriastradh 	if (!smu_get_uclk_dpm_states(smu,
8941571a7a1Sriastradh 			clock_values_in_khz, num_states))
8951571a7a1Sriastradh 		return PP_SMU_RESULT_OK;
8961571a7a1Sriastradh 
8971571a7a1Sriastradh 	return PP_SMU_RESULT_FAIL;
8981571a7a1Sriastradh }
8991571a7a1Sriastradh 
pp_rn_get_dpm_clock_table(struct pp_smu * pp,struct dpm_clocks * clock_table)9001571a7a1Sriastradh enum pp_smu_status pp_rn_get_dpm_clock_table(
9011571a7a1Sriastradh 		struct pp_smu *pp, struct dpm_clocks *clock_table)
9021571a7a1Sriastradh {
9031571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
9041571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
9051571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
9061571a7a1Sriastradh 
9071571a7a1Sriastradh 	if (!smu->ppt_funcs)
9081571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
9091571a7a1Sriastradh 
9101571a7a1Sriastradh 	if (!smu->ppt_funcs->get_dpm_clock_table)
9111571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
9121571a7a1Sriastradh 
9131571a7a1Sriastradh 	if (!smu_get_dpm_clock_table(smu, clock_table))
9141571a7a1Sriastradh 		return PP_SMU_RESULT_OK;
9151571a7a1Sriastradh 
9161571a7a1Sriastradh 	return PP_SMU_RESULT_FAIL;
9171571a7a1Sriastradh }
9181571a7a1Sriastradh 
pp_rn_set_wm_ranges(struct pp_smu * pp,struct pp_smu_wm_range_sets * ranges)9191571a7a1Sriastradh enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp,
9201571a7a1Sriastradh 		struct pp_smu_wm_range_sets *ranges)
9211571a7a1Sriastradh {
9221571a7a1Sriastradh 	const struct dc_context *ctx = pp->dm;
9231571a7a1Sriastradh 	struct amdgpu_device *adev = ctx->driver_context;
9241571a7a1Sriastradh 	struct smu_context *smu = &adev->smu;
9251571a7a1Sriastradh 	struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
9261571a7a1Sriastradh 	struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks =
9271571a7a1Sriastradh 			wm_with_clock_ranges.wm_dmif_clocks_ranges;
9281571a7a1Sriastradh 	struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks =
9291571a7a1Sriastradh 			wm_with_clock_ranges.wm_mcif_clocks_ranges;
9301571a7a1Sriastradh 	int32_t i;
9311571a7a1Sriastradh 
9321571a7a1Sriastradh 	if (!smu->ppt_funcs)
9331571a7a1Sriastradh 		return PP_SMU_RESULT_UNSUPPORTED;
9341571a7a1Sriastradh 
9351571a7a1Sriastradh 	wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
9361571a7a1Sriastradh 	wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
9371571a7a1Sriastradh 
9381571a7a1Sriastradh 	for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
9391571a7a1Sriastradh 		if (ranges->reader_wm_sets[i].wm_inst > 3)
9401571a7a1Sriastradh 			wm_dce_clocks[i].wm_set_id = WM_SET_A;
9411571a7a1Sriastradh 		else
9421571a7a1Sriastradh 			wm_dce_clocks[i].wm_set_id =
9431571a7a1Sriastradh 					ranges->reader_wm_sets[i].wm_inst;
9441571a7a1Sriastradh 
9451571a7a1Sriastradh 		wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
9461571a7a1Sriastradh 			ranges->reader_wm_sets[i].min_drain_clk_mhz;
9471571a7a1Sriastradh 
9481571a7a1Sriastradh 		wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
9491571a7a1Sriastradh 			ranges->reader_wm_sets[i].max_drain_clk_mhz;
9501571a7a1Sriastradh 
9511571a7a1Sriastradh 		wm_dce_clocks[i].wm_min_mem_clk_in_khz =
9521571a7a1Sriastradh 			ranges->reader_wm_sets[i].min_fill_clk_mhz;
9531571a7a1Sriastradh 
9541571a7a1Sriastradh 		wm_dce_clocks[i].wm_max_mem_clk_in_khz =
9551571a7a1Sriastradh 			ranges->reader_wm_sets[i].max_fill_clk_mhz;
9561571a7a1Sriastradh 	}
9571571a7a1Sriastradh 
9581571a7a1Sriastradh 	for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
9591571a7a1Sriastradh 		if (ranges->writer_wm_sets[i].wm_inst > 3)
9601571a7a1Sriastradh 			wm_soc_clocks[i].wm_set_id = WM_SET_A;
9611571a7a1Sriastradh 		else
9621571a7a1Sriastradh 			wm_soc_clocks[i].wm_set_id =
9631571a7a1Sriastradh 					ranges->writer_wm_sets[i].wm_inst;
9641571a7a1Sriastradh 		wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
9651571a7a1Sriastradh 				ranges->writer_wm_sets[i].min_fill_clk_mhz;
9661571a7a1Sriastradh 
9671571a7a1Sriastradh 		wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
9681571a7a1Sriastradh 			ranges->writer_wm_sets[i].max_fill_clk_mhz;
9691571a7a1Sriastradh 
9701571a7a1Sriastradh 		wm_soc_clocks[i].wm_min_mem_clk_in_khz =
9711571a7a1Sriastradh 			ranges->writer_wm_sets[i].min_drain_clk_mhz;
9721571a7a1Sriastradh 
9731571a7a1Sriastradh 		wm_soc_clocks[i].wm_max_mem_clk_in_khz =
9741571a7a1Sriastradh 			ranges->writer_wm_sets[i].max_drain_clk_mhz;
9751571a7a1Sriastradh 	}
9761571a7a1Sriastradh 
9771571a7a1Sriastradh 	smu_set_watermarks_for_clock_ranges(&adev->smu, &wm_with_clock_ranges);
9781571a7a1Sriastradh 
9791571a7a1Sriastradh 	return PP_SMU_RESULT_OK;
9801571a7a1Sriastradh }
9811571a7a1Sriastradh 
dm_pp_get_funcs(struct dc_context * ctx,struct pp_smu_funcs * funcs)9821571a7a1Sriastradh void dm_pp_get_funcs(
9831571a7a1Sriastradh 		struct dc_context *ctx,
9841571a7a1Sriastradh 		struct pp_smu_funcs *funcs)
9851571a7a1Sriastradh {
9861571a7a1Sriastradh 	switch (ctx->dce_version) {
9871571a7a1Sriastradh 	case DCN_VERSION_1_0:
9881571a7a1Sriastradh 	case DCN_VERSION_1_01:
9891571a7a1Sriastradh 		funcs->ctx.ver = PP_SMU_VER_RV;
9901571a7a1Sriastradh 		funcs->rv_funcs.pp_smu.dm = ctx;
9911571a7a1Sriastradh 		funcs->rv_funcs.set_wm_ranges = pp_rv_set_wm_ranges;
9921571a7a1Sriastradh 		funcs->rv_funcs.set_pme_wa_enable = pp_rv_set_pme_wa_enable;
9931571a7a1Sriastradh 		funcs->rv_funcs.set_display_count =
9941571a7a1Sriastradh 				pp_rv_set_active_display_count;
9951571a7a1Sriastradh 		funcs->rv_funcs.set_min_deep_sleep_dcfclk =
9961571a7a1Sriastradh 				pp_rv_set_min_deep_sleep_dcfclk;
9971571a7a1Sriastradh 		funcs->rv_funcs.set_hard_min_dcfclk_by_freq =
9981571a7a1Sriastradh 				pp_rv_set_hard_min_dcefclk_by_freq;
9991571a7a1Sriastradh 		funcs->rv_funcs.set_hard_min_fclk_by_freq =
10001571a7a1Sriastradh 				pp_rv_set_hard_min_fclk_by_freq;
10011571a7a1Sriastradh 		break;
10021571a7a1Sriastradh 	case DCN_VERSION_2_0:
10031571a7a1Sriastradh 		funcs->ctx.ver = PP_SMU_VER_NV;
10041571a7a1Sriastradh 		funcs->nv_funcs.pp_smu.dm = ctx;
10051571a7a1Sriastradh 		funcs->nv_funcs.set_display_count = pp_nv_set_display_count;
10061571a7a1Sriastradh 		funcs->nv_funcs.set_hard_min_dcfclk_by_freq =
10071571a7a1Sriastradh 				pp_nv_set_hard_min_dcefclk_by_freq;
10081571a7a1Sriastradh 		funcs->nv_funcs.set_min_deep_sleep_dcfclk =
10091571a7a1Sriastradh 				pp_nv_set_min_deep_sleep_dcfclk;
10101571a7a1Sriastradh 		funcs->nv_funcs.set_voltage_by_freq =
10111571a7a1Sriastradh 				pp_nv_set_voltage_by_freq;
10121571a7a1Sriastradh 		funcs->nv_funcs.set_wm_ranges = pp_nv_set_wm_ranges;
10131571a7a1Sriastradh 
10141571a7a1Sriastradh 		/* todo set_pme_wa_enable cause 4k@6ohz display not light up */
10151571a7a1Sriastradh 		funcs->nv_funcs.set_pme_wa_enable = NULL;
10161571a7a1Sriastradh 		/* todo debug waring message */
10171571a7a1Sriastradh 		funcs->nv_funcs.set_hard_min_uclk_by_freq = pp_nv_set_hard_min_uclk_by_freq;
10181571a7a1Sriastradh 		/* todo  compare data with window driver*/
10191571a7a1Sriastradh 		funcs->nv_funcs.get_maximum_sustainable_clocks = pp_nv_get_maximum_sustainable_clocks;
10201571a7a1Sriastradh 		/*todo  compare data with window driver */
10211571a7a1Sriastradh 		funcs->nv_funcs.get_uclk_dpm_states = pp_nv_get_uclk_dpm_states;
10221571a7a1Sriastradh 		funcs->nv_funcs.set_pstate_handshake_support = pp_nv_set_pstate_handshake_support;
10231571a7a1Sriastradh 		break;
10241571a7a1Sriastradh 
10251571a7a1Sriastradh 	case DCN_VERSION_2_1:
10261571a7a1Sriastradh 		funcs->ctx.ver = PP_SMU_VER_RN;
10271571a7a1Sriastradh 		funcs->rn_funcs.pp_smu.dm = ctx;
10281571a7a1Sriastradh 		funcs->rn_funcs.set_wm_ranges = pp_rn_set_wm_ranges;
10291571a7a1Sriastradh 		funcs->rn_funcs.get_dpm_clock_table = pp_rn_get_dpm_clock_table;
10301571a7a1Sriastradh 		break;
10311571a7a1Sriastradh 	default:
10321571a7a1Sriastradh 		DRM_ERROR("smu version is not supported !\n");
10331571a7a1Sriastradh 		break;
10341571a7a1Sriastradh 	}
10351571a7a1Sriastradh }
1036