1/*	$NetBSD: amdgpu_dm_pp_smu.c,v 1.3 2021/12/19 10:59:01 riastradh Exp $	*/
2
3/*
4 * Copyright 2018 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 */
26#include <sys/cdefs.h>
27__KERNEL_RCSID(0, "$NetBSD: amdgpu_dm_pp_smu.c,v 1.3 2021/12/19 10:59:01 riastradh Exp $");
28
29#include <linux/string.h>
30#include <linux/acpi.h>
31
32#include <drm/drm_probe_helper.h>
33#include <drm/amdgpu_drm.h>
34#include "dm_services.h"
35#include "amdgpu.h"
36#include "amdgpu_dm.h"
37#include "amdgpu_dm_irq.h"
38#include "amdgpu_pm.h"
39#include "dm_pp_smu.h"
40#include "amdgpu_smu.h"
41
42
43bool dm_pp_apply_display_requirements(
44		const struct dc_context *ctx,
45		const struct dm_pp_display_configuration *pp_display_cfg)
46{
47	struct amdgpu_device *adev = ctx->driver_context;
48	struct smu_context *smu = &adev->smu;
49	int i;
50
51	if (adev->pm.dpm_enabled) {
52
53		memset(&adev->pm.pm_display_cfg, 0,
54				sizeof(adev->pm.pm_display_cfg));
55
56		adev->pm.pm_display_cfg.cpu_cc6_disable =
57			pp_display_cfg->cpu_cc6_disable;
58
59		adev->pm.pm_display_cfg.cpu_pstate_disable =
60			pp_display_cfg->cpu_pstate_disable;
61
62		adev->pm.pm_display_cfg.cpu_pstate_separation_time =
63			pp_display_cfg->cpu_pstate_separation_time;
64
65		adev->pm.pm_display_cfg.nb_pstate_switch_disable =
66			pp_display_cfg->nb_pstate_switch_disable;
67
68		adev->pm.pm_display_cfg.num_display =
69				pp_display_cfg->display_count;
70		adev->pm.pm_display_cfg.num_path_including_non_display =
71				pp_display_cfg->display_count;
72
73		adev->pm.pm_display_cfg.min_core_set_clock =
74				pp_display_cfg->min_engine_clock_khz/10;
75		adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
76				pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
77		adev->pm.pm_display_cfg.min_mem_set_clock =
78				pp_display_cfg->min_memory_clock_khz/10;
79
80		adev->pm.pm_display_cfg.min_dcef_deep_sleep_set_clk =
81				pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
82		adev->pm.pm_display_cfg.min_dcef_set_clk =
83				pp_display_cfg->min_dcfclock_khz/10;
84
85		adev->pm.pm_display_cfg.multi_monitor_in_sync =
86				pp_display_cfg->all_displays_in_sync;
87		adev->pm.pm_display_cfg.min_vblank_time =
88				pp_display_cfg->avail_mclk_switch_time_us;
89
90		adev->pm.pm_display_cfg.display_clk =
91				pp_display_cfg->disp_clk_khz/10;
92
93		adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
94				pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
95
96		adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
97		adev->pm.pm_display_cfg.line_time_in_us =
98				pp_display_cfg->line_time_in_us;
99
100		adev->pm.pm_display_cfg.vrefresh = pp_display_cfg->disp_configs[0].v_refresh;
101		adev->pm.pm_display_cfg.crossfire_display_index = -1;
102		adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
103
104		for (i = 0; i < pp_display_cfg->display_count; i++) {
105			const struct dm_pp_single_disp_config *dc_cfg =
106						&pp_display_cfg->disp_configs[i];
107			adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1;
108		}
109
110		if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_configuration_change)
111			adev->powerplay.pp_funcs->display_configuration_change(
112				adev->powerplay.pp_handle,
113				&adev->pm.pm_display_cfg);
114		else
115			smu_display_configuration_change(smu,
116							 &adev->pm.pm_display_cfg);
117
118		amdgpu_pm_compute_clocks(adev);
119	}
120
121	return true;
122}
123
124static void get_default_clock_levels(
125		enum dm_pp_clock_type clk_type,
126		struct dm_pp_clock_levels *clks)
127{
128	uint32_t disp_clks_in_khz[6] = {
129			300000, 400000, 496560, 626090, 685720, 757900 };
130	uint32_t sclks_in_khz[6] = {
131			300000, 360000, 423530, 514290, 626090, 720000 };
132	uint32_t mclks_in_khz[2] = { 333000, 800000 };
133
134	switch (clk_type) {
135	case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
136		clks->num_levels = 6;
137		memmove(clks->clocks_in_khz, disp_clks_in_khz,
138				sizeof(disp_clks_in_khz));
139		break;
140	case DM_PP_CLOCK_TYPE_ENGINE_CLK:
141		clks->num_levels = 6;
142		memmove(clks->clocks_in_khz, sclks_in_khz,
143				sizeof(sclks_in_khz));
144		break;
145	case DM_PP_CLOCK_TYPE_MEMORY_CLK:
146		clks->num_levels = 2;
147		memmove(clks->clocks_in_khz, mclks_in_khz,
148				sizeof(mclks_in_khz));
149		break;
150	default:
151		clks->num_levels = 0;
152		break;
153	}
154}
155
156static enum smu_clk_type dc_to_smu_clock_type(
157		enum dm_pp_clock_type dm_pp_clk_type)
158{
159	enum smu_clk_type smu_clk_type = SMU_CLK_COUNT;
160
161	switch (dm_pp_clk_type) {
162	case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
163		smu_clk_type = SMU_DISPCLK;
164		break;
165	case DM_PP_CLOCK_TYPE_ENGINE_CLK:
166		smu_clk_type = SMU_GFXCLK;
167		break;
168	case DM_PP_CLOCK_TYPE_MEMORY_CLK:
169		smu_clk_type = SMU_MCLK;
170		break;
171	case DM_PP_CLOCK_TYPE_DCEFCLK:
172		smu_clk_type = SMU_DCEFCLK;
173		break;
174	case DM_PP_CLOCK_TYPE_SOCCLK:
175		smu_clk_type = SMU_SOCCLK;
176		break;
177	default:
178		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
179			  dm_pp_clk_type);
180		break;
181	}
182
183	return smu_clk_type;
184}
185
186static enum amd_pp_clock_type dc_to_pp_clock_type(
187		enum dm_pp_clock_type dm_pp_clk_type)
188{
189	enum amd_pp_clock_type amd_pp_clk_type = 0;
190
191	switch (dm_pp_clk_type) {
192	case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
193		amd_pp_clk_type = amd_pp_disp_clock;
194		break;
195	case DM_PP_CLOCK_TYPE_ENGINE_CLK:
196		amd_pp_clk_type = amd_pp_sys_clock;
197		break;
198	case DM_PP_CLOCK_TYPE_MEMORY_CLK:
199		amd_pp_clk_type = amd_pp_mem_clock;
200		break;
201	case DM_PP_CLOCK_TYPE_DCEFCLK:
202		amd_pp_clk_type  = amd_pp_dcef_clock;
203		break;
204	case DM_PP_CLOCK_TYPE_DCFCLK:
205		amd_pp_clk_type = amd_pp_dcf_clock;
206		break;
207	case DM_PP_CLOCK_TYPE_PIXELCLK:
208		amd_pp_clk_type = amd_pp_pixel_clock;
209		break;
210	case DM_PP_CLOCK_TYPE_FCLK:
211		amd_pp_clk_type = amd_pp_f_clock;
212		break;
213	case DM_PP_CLOCK_TYPE_DISPLAYPHYCLK:
214		amd_pp_clk_type = amd_pp_phy_clock;
215		break;
216	case DM_PP_CLOCK_TYPE_DPPCLK:
217		amd_pp_clk_type = amd_pp_dpp_clock;
218		break;
219	default:
220		DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
221				dm_pp_clk_type);
222		break;
223	}
224
225	return amd_pp_clk_type;
226}
227
228static enum dm_pp_clocks_state pp_to_dc_powerlevel_state(
229			enum PP_DAL_POWERLEVEL max_clocks_state)
230{
231	switch (max_clocks_state) {
232	case PP_DAL_POWERLEVEL_0:
233		return DM_PP_CLOCKS_DPM_STATE_LEVEL_0;
234	case PP_DAL_POWERLEVEL_1:
235		return DM_PP_CLOCKS_DPM_STATE_LEVEL_1;
236	case PP_DAL_POWERLEVEL_2:
237		return DM_PP_CLOCKS_DPM_STATE_LEVEL_2;
238	case PP_DAL_POWERLEVEL_3:
239		return DM_PP_CLOCKS_DPM_STATE_LEVEL_3;
240	case PP_DAL_POWERLEVEL_4:
241		return DM_PP_CLOCKS_DPM_STATE_LEVEL_4;
242	case PP_DAL_POWERLEVEL_5:
243		return DM_PP_CLOCKS_DPM_STATE_LEVEL_5;
244	case PP_DAL_POWERLEVEL_6:
245		return DM_PP_CLOCKS_DPM_STATE_LEVEL_6;
246	case PP_DAL_POWERLEVEL_7:
247		return DM_PP_CLOCKS_DPM_STATE_LEVEL_7;
248	default:
249		DRM_ERROR("DM_PPLIB: invalid powerlevel state: %d!\n",
250				max_clocks_state);
251		return DM_PP_CLOCKS_STATE_INVALID;
252	}
253}
254
255static void pp_to_dc_clock_levels(
256		const struct amd_pp_clocks *pp_clks,
257		struct dm_pp_clock_levels *dc_clks,
258		enum dm_pp_clock_type dc_clk_type)
259{
260	uint32_t i;
261
262	if (pp_clks->count > DM_PP_MAX_CLOCK_LEVELS) {
263		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
264				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
265				pp_clks->count,
266				DM_PP_MAX_CLOCK_LEVELS);
267
268		dc_clks->num_levels = DM_PP_MAX_CLOCK_LEVELS;
269	} else
270		dc_clks->num_levels = pp_clks->count;
271
272	DRM_INFO("DM_PPLIB: values for %s clock\n",
273			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
274
275	for (i = 0; i < dc_clks->num_levels; i++) {
276		DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
277		dc_clks->clocks_in_khz[i] = pp_clks->clock[i];
278	}
279}
280
281static void pp_to_dc_clock_levels_with_latency(
282		const struct pp_clock_levels_with_latency *pp_clks,
283		struct dm_pp_clock_levels_with_latency *clk_level_info,
284		enum dm_pp_clock_type dc_clk_type)
285{
286	uint32_t i;
287
288	if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
289		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
290				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
291				pp_clks->num_levels,
292				DM_PP_MAX_CLOCK_LEVELS);
293
294		clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
295	} else
296		clk_level_info->num_levels = pp_clks->num_levels;
297
298	DRM_DEBUG("DM_PPLIB: values for %s clock\n",
299			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
300
301	for (i = 0; i < clk_level_info->num_levels; i++) {
302		DRM_DEBUG("DM_PPLIB:\t %d in kHz\n", pp_clks->data[i].clocks_in_khz);
303		clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz;
304		clk_level_info->data[i].latency_in_us = pp_clks->data[i].latency_in_us;
305	}
306}
307
308static void pp_to_dc_clock_levels_with_voltage(
309		const struct pp_clock_levels_with_voltage *pp_clks,
310		struct dm_pp_clock_levels_with_voltage *clk_level_info,
311		enum dm_pp_clock_type dc_clk_type)
312{
313	uint32_t i;
314
315	if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
316		DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
317				DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
318				pp_clks->num_levels,
319				DM_PP_MAX_CLOCK_LEVELS);
320
321		clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
322	} else
323		clk_level_info->num_levels = pp_clks->num_levels;
324
325	DRM_INFO("DM_PPLIB: values for %s clock\n",
326			DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
327
328	for (i = 0; i < clk_level_info->num_levels; i++) {
329		DRM_INFO("DM_PPLIB:\t %d in kHz, %d in mV\n", pp_clks->data[i].clocks_in_khz,
330			 pp_clks->data[i].voltage_in_mv);
331		clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz;
332		clk_level_info->data[i].voltage_in_mv = pp_clks->data[i].voltage_in_mv;
333	}
334}
335
336bool dm_pp_get_clock_levels_by_type(
337		const struct dc_context *ctx,
338		enum dm_pp_clock_type clk_type,
339		struct dm_pp_clock_levels *dc_clks)
340{
341	struct amdgpu_device *adev = ctx->driver_context;
342	void *pp_handle = adev->powerplay.pp_handle;
343	struct amd_pp_clocks pp_clks = { 0 };
344	struct amd_pp_simple_clock_info validation_clks = { 0 };
345	uint32_t i;
346
347	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) {
348		if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle,
349			dc_to_pp_clock_type(clk_type), &pp_clks)) {
350			/* Error in pplib. Provide default values. */
351			get_default_clock_levels(clk_type, dc_clks);
352			return true;
353		}
354	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_clock_by_type) {
355		if (smu_get_clock_by_type(&adev->smu,
356					  dc_to_pp_clock_type(clk_type),
357					  &pp_clks)) {
358			get_default_clock_levels(clk_type, dc_clks);
359			return true;
360		}
361	}
362
363	pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
364
365	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_display_mode_validation_clocks) {
366		if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks(
367						pp_handle, &validation_clks)) {
368			/* Error in pplib. Provide default values. */
369			DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
370			validation_clks.engine_max_clock = 72000;
371			validation_clks.memory_max_clock = 80000;
372			validation_clks.level = 0;
373		}
374	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_max_high_clocks) {
375		if (smu_get_max_high_clocks(&adev->smu, &validation_clks)) {
376			DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
377			validation_clks.engine_max_clock = 72000;
378			validation_clks.memory_max_clock = 80000;
379			validation_clks.level = 0;
380		}
381	}
382
383	DRM_INFO("DM_PPLIB: Validation clocks:\n");
384	DRM_INFO("DM_PPLIB:    engine_max_clock: %d\n",
385			validation_clks.engine_max_clock);
386	DRM_INFO("DM_PPLIB:    memory_max_clock: %d\n",
387			validation_clks.memory_max_clock);
388	DRM_INFO("DM_PPLIB:    level           : %d\n",
389			validation_clks.level);
390
391	/* Translate 10 kHz to kHz. */
392	validation_clks.engine_max_clock *= 10;
393	validation_clks.memory_max_clock *= 10;
394
395	/* Determine the highest non-boosted level from the Validation Clocks */
396	if (clk_type == DM_PP_CLOCK_TYPE_ENGINE_CLK) {
397		for (i = 0; i < dc_clks->num_levels; i++) {
398			if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
399				/* This clock is higher the validation clock.
400				 * Than means the previous one is the highest
401				 * non-boosted one. */
402				DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
403						dc_clks->num_levels, i);
404				dc_clks->num_levels = i > 0 ? i : 1;
405				break;
406			}
407		}
408	} else if (clk_type == DM_PP_CLOCK_TYPE_MEMORY_CLK) {
409		for (i = 0; i < dc_clks->num_levels; i++) {
410			if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
411				DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
412						dc_clks->num_levels, i);
413				dc_clks->num_levels = i > 0 ? i : 1;
414				break;
415			}
416		}
417	}
418
419	return true;
420}
421
422bool dm_pp_get_clock_levels_by_type_with_latency(
423	const struct dc_context *ctx,
424	enum dm_pp_clock_type clk_type,
425	struct dm_pp_clock_levels_with_latency *clk_level_info)
426{
427	struct amdgpu_device *adev = ctx->driver_context;
428	void *pp_handle = adev->powerplay.pp_handle;
429	struct pp_clock_levels_with_latency pp_clks = { 0 };
430	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
431	int ret;
432
433	if (pp_funcs && pp_funcs->get_clock_by_type_with_latency) {
434		ret = pp_funcs->get_clock_by_type_with_latency(pp_handle,
435						dc_to_pp_clock_type(clk_type),
436						&pp_clks);
437		if (ret)
438			return false;
439	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_clock_by_type_with_latency) {
440		if (smu_get_clock_by_type_with_latency(&adev->smu,
441						       dc_to_smu_clock_type(clk_type),
442						       &pp_clks))
443			return false;
444	}
445
446
447	pp_to_dc_clock_levels_with_latency(&pp_clks, clk_level_info, clk_type);
448
449	return true;
450}
451
452bool dm_pp_get_clock_levels_by_type_with_voltage(
453	const struct dc_context *ctx,
454	enum dm_pp_clock_type clk_type,
455	struct dm_pp_clock_levels_with_voltage *clk_level_info)
456{
457	struct amdgpu_device *adev = ctx->driver_context;
458	void *pp_handle = adev->powerplay.pp_handle;
459	struct pp_clock_levels_with_voltage pp_clk_info = {0};
460	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
461	int ret;
462
463	if (pp_funcs && pp_funcs->get_clock_by_type_with_voltage) {
464		ret = pp_funcs->get_clock_by_type_with_voltage(pp_handle,
465						dc_to_pp_clock_type(clk_type),
466						&pp_clk_info);
467		if (ret)
468			return false;
469	} else if (adev->smu.ppt_funcs && adev->smu.ppt_funcs->get_clock_by_type_with_voltage) {
470		if (smu_get_clock_by_type_with_voltage(&adev->smu,
471						       dc_to_pp_clock_type(clk_type),
472						       &pp_clk_info))
473			return false;
474	}
475
476	pp_to_dc_clock_levels_with_voltage(&pp_clk_info, clk_level_info, clk_type);
477
478	return true;
479}
480
481bool dm_pp_notify_wm_clock_changes(
482	const struct dc_context *ctx,
483	struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges)
484{
485	/* TODO: to be implemented */
486	return false;
487}
488
489bool dm_pp_apply_power_level_change_request(
490	const struct dc_context *ctx,
491	struct dm_pp_power_level_change_request *level_change_req)
492{
493	/* TODO: to be implemented */
494	return false;
495}
496
497bool dm_pp_apply_clock_for_voltage_request(
498	const struct dc_context *ctx,
499	struct dm_pp_clock_for_voltage_req *clock_for_voltage_req)
500{
501	struct amdgpu_device *adev = ctx->driver_context;
502	struct pp_display_clock_request pp_clock_request = {0};
503	int ret = 0;
504
505	pp_clock_request.clock_type = dc_to_pp_clock_type(clock_for_voltage_req->clk_type);
506	pp_clock_request.clock_freq_in_khz = clock_for_voltage_req->clocks_in_khz;
507
508	if (!pp_clock_request.clock_type)
509		return false;
510
511	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_clock_voltage_request)
512		ret = adev->powerplay.pp_funcs->display_clock_voltage_request(
513			adev->powerplay.pp_handle,
514			&pp_clock_request);
515	else if (adev->smu.ppt_funcs &&
516		 adev->smu.ppt_funcs->display_clock_voltage_request)
517		ret = smu_display_clock_voltage_request(&adev->smu,
518							&pp_clock_request);
519	if (ret)
520		return false;
521	return true;
522}
523
524bool dm_pp_get_static_clocks(
525	const struct dc_context *ctx,
526	struct dm_pp_static_clock_info *static_clk_info)
527{
528	struct amdgpu_device *adev = ctx->driver_context;
529	struct amd_pp_clock_info pp_clk_info = {0};
530	int ret = 0;
531
532	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_current_clocks)
533		ret = adev->powerplay.pp_funcs->get_current_clocks(
534			adev->powerplay.pp_handle,
535			&pp_clk_info);
536	else if (adev->smu.ppt_funcs)
537		ret = smu_get_current_clocks(&adev->smu, &pp_clk_info);
538	if (ret)
539		return false;
540
541	static_clk_info->max_clocks_state = pp_to_dc_powerlevel_state(pp_clk_info.max_clocks_state);
542	static_clk_info->max_mclk_khz = pp_clk_info.max_memory_clock * 10;
543	static_clk_info->max_sclk_khz = pp_clk_info.max_engine_clock * 10;
544
545	return true;
546}
547
548void pp_rv_set_wm_ranges(struct pp_smu *pp,
549		struct pp_smu_wm_range_sets *ranges)
550{
551	const struct dc_context *ctx = pp->dm;
552	struct amdgpu_device *adev = ctx->driver_context;
553	void *pp_handle = adev->powerplay.pp_handle;
554	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
555	struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
556	struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks = wm_with_clock_ranges.wm_dmif_clocks_ranges;
557	struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks = wm_with_clock_ranges.wm_mcif_clocks_ranges;
558	int32_t i;
559
560	wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
561	wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
562
563	for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
564		if (ranges->reader_wm_sets[i].wm_inst > 3)
565			wm_dce_clocks[i].wm_set_id = WM_SET_A;
566		else
567			wm_dce_clocks[i].wm_set_id =
568					ranges->reader_wm_sets[i].wm_inst;
569		wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
570				ranges->reader_wm_sets[i].max_drain_clk_mhz * 1000;
571		wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
572				ranges->reader_wm_sets[i].min_drain_clk_mhz * 1000;
573		wm_dce_clocks[i].wm_max_mem_clk_in_khz =
574				ranges->reader_wm_sets[i].max_fill_clk_mhz * 1000;
575		wm_dce_clocks[i].wm_min_mem_clk_in_khz =
576				ranges->reader_wm_sets[i].min_fill_clk_mhz * 1000;
577	}
578
579	for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
580		if (ranges->writer_wm_sets[i].wm_inst > 3)
581			wm_soc_clocks[i].wm_set_id = WM_SET_A;
582		else
583			wm_soc_clocks[i].wm_set_id =
584					ranges->writer_wm_sets[i].wm_inst;
585		wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
586				ranges->writer_wm_sets[i].max_fill_clk_mhz * 1000;
587		wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
588				ranges->writer_wm_sets[i].min_fill_clk_mhz * 1000;
589		wm_soc_clocks[i].wm_max_mem_clk_in_khz =
590				ranges->writer_wm_sets[i].max_drain_clk_mhz * 1000;
591		wm_soc_clocks[i].wm_min_mem_clk_in_khz =
592				ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000;
593	}
594
595	if (pp_funcs && pp_funcs->set_watermarks_for_clocks_ranges)
596		pp_funcs->set_watermarks_for_clocks_ranges(pp_handle,
597							   &wm_with_clock_ranges);
598	else
599		smu_set_watermarks_for_clock_ranges(&adev->smu,
600				&wm_with_clock_ranges);
601}
602
603void pp_rv_set_pme_wa_enable(struct pp_smu *pp)
604{
605	const struct dc_context *ctx = pp->dm;
606	struct amdgpu_device *adev = ctx->driver_context;
607	void *pp_handle = adev->powerplay.pp_handle;
608	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
609
610	if (pp_funcs && pp_funcs->notify_smu_enable_pwe)
611		pp_funcs->notify_smu_enable_pwe(pp_handle);
612	else if (adev->smu.ppt_funcs)
613		smu_notify_smu_enable_pwe(&adev->smu);
614}
615
616void pp_rv_set_active_display_count(struct pp_smu *pp, int count)
617{
618	const struct dc_context *ctx = pp->dm;
619	struct amdgpu_device *adev = ctx->driver_context;
620	void *pp_handle = adev->powerplay.pp_handle;
621	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
622
623	if (!pp_funcs || !pp_funcs->set_active_display_count)
624		return;
625
626	pp_funcs->set_active_display_count(pp_handle, count);
627}
628
629void pp_rv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int clock)
630{
631	const struct dc_context *ctx = pp->dm;
632	struct amdgpu_device *adev = ctx->driver_context;
633	void *pp_handle = adev->powerplay.pp_handle;
634	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
635
636	if (!pp_funcs || !pp_funcs->set_min_deep_sleep_dcefclk)
637		return;
638
639	pp_funcs->set_min_deep_sleep_dcefclk(pp_handle, clock);
640}
641
642void pp_rv_set_hard_min_dcefclk_by_freq(struct pp_smu *pp, int clock)
643{
644	const struct dc_context *ctx = pp->dm;
645	struct amdgpu_device *adev = ctx->driver_context;
646	void *pp_handle = adev->powerplay.pp_handle;
647	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
648
649	if (!pp_funcs || !pp_funcs->set_hard_min_dcefclk_by_freq)
650		return;
651
652	pp_funcs->set_hard_min_dcefclk_by_freq(pp_handle, clock);
653}
654
655void pp_rv_set_hard_min_fclk_by_freq(struct pp_smu *pp, int mhz)
656{
657	const struct dc_context *ctx = pp->dm;
658	struct amdgpu_device *adev = ctx->driver_context;
659	void *pp_handle = adev->powerplay.pp_handle;
660	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
661
662	if (!pp_funcs || !pp_funcs->set_hard_min_fclk_by_freq)
663		return;
664
665	pp_funcs->set_hard_min_fclk_by_freq(pp_handle, mhz);
666}
667
668enum pp_smu_status pp_nv_set_wm_ranges(struct pp_smu *pp,
669		struct pp_smu_wm_range_sets *ranges)
670{
671	const struct dc_context *ctx = pp->dm;
672	struct amdgpu_device *adev = ctx->driver_context;
673	struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
674	struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks =
675			wm_with_clock_ranges.wm_dmif_clocks_ranges;
676	struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks =
677			wm_with_clock_ranges.wm_mcif_clocks_ranges;
678	int32_t i;
679
680	wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
681	wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
682
683	for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
684		if (ranges->reader_wm_sets[i].wm_inst > 3)
685			wm_dce_clocks[i].wm_set_id = WM_SET_A;
686		else
687			wm_dce_clocks[i].wm_set_id =
688					ranges->reader_wm_sets[i].wm_inst;
689		wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
690			ranges->reader_wm_sets[i].max_drain_clk_mhz * 1000;
691		wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
692			ranges->reader_wm_sets[i].min_drain_clk_mhz * 1000;
693		wm_dce_clocks[i].wm_max_mem_clk_in_khz =
694			ranges->reader_wm_sets[i].max_fill_clk_mhz * 1000;
695		wm_dce_clocks[i].wm_min_mem_clk_in_khz =
696			ranges->reader_wm_sets[i].min_fill_clk_mhz * 1000;
697	}
698
699	for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
700		if (ranges->writer_wm_sets[i].wm_inst > 3)
701			wm_soc_clocks[i].wm_set_id = WM_SET_A;
702		else
703			wm_soc_clocks[i].wm_set_id =
704					ranges->writer_wm_sets[i].wm_inst;
705		wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
706			ranges->writer_wm_sets[i].max_fill_clk_mhz * 1000;
707		wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
708			ranges->writer_wm_sets[i].min_fill_clk_mhz * 1000;
709		wm_soc_clocks[i].wm_max_mem_clk_in_khz =
710			ranges->writer_wm_sets[i].max_drain_clk_mhz * 1000;
711		wm_soc_clocks[i].wm_min_mem_clk_in_khz =
712			ranges->writer_wm_sets[i].min_drain_clk_mhz * 1000;
713	}
714
715	smu_set_watermarks_for_clock_ranges(&adev->smu,	&wm_with_clock_ranges);
716
717	return PP_SMU_RESULT_OK;
718}
719
720enum pp_smu_status pp_nv_set_pme_wa_enable(struct pp_smu *pp)
721{
722	const struct dc_context *ctx = pp->dm;
723	struct amdgpu_device *adev = ctx->driver_context;
724	struct smu_context *smu = &adev->smu;
725
726	if (!smu->ppt_funcs)
727		return PP_SMU_RESULT_UNSUPPORTED;
728
729	/* 0: successful or smu.ppt_funcs->set_azalia_d3_pme = NULL;  1: fail */
730	if (smu_set_azalia_d3_pme(smu))
731		return PP_SMU_RESULT_FAIL;
732
733	return PP_SMU_RESULT_OK;
734}
735
736enum pp_smu_status pp_nv_set_display_count(struct pp_smu *pp, int count)
737{
738	const struct dc_context *ctx = pp->dm;
739	struct amdgpu_device *adev = ctx->driver_context;
740	struct smu_context *smu = &adev->smu;
741
742	if (!smu->ppt_funcs)
743		return PP_SMU_RESULT_UNSUPPORTED;
744
745	/* 0: successful or smu.ppt_funcs->set_display_count = NULL;  1: fail */
746	if (smu_set_display_count(smu, count))
747		return PP_SMU_RESULT_FAIL;
748
749	return PP_SMU_RESULT_OK;
750}
751
752enum pp_smu_status pp_nv_set_min_deep_sleep_dcfclk(struct pp_smu *pp, int mhz)
753{
754	const struct dc_context *ctx = pp->dm;
755	struct amdgpu_device *adev = ctx->driver_context;
756	struct smu_context *smu = &adev->smu;
757
758	if (!smu->ppt_funcs)
759		return PP_SMU_RESULT_UNSUPPORTED;
760
761	/* 0: successful or smu.ppt_funcs->set_deep_sleep_dcefclk = NULL;1: fail */
762	if (smu_set_deep_sleep_dcefclk(smu, mhz))
763		return PP_SMU_RESULT_FAIL;
764
765	return PP_SMU_RESULT_OK;
766}
767
768enum pp_smu_status pp_nv_set_hard_min_dcefclk_by_freq(
769		struct pp_smu *pp, int mhz)
770{
771	const struct dc_context *ctx = pp->dm;
772	struct amdgpu_device *adev = ctx->driver_context;
773	struct smu_context *smu = &adev->smu;
774	struct pp_display_clock_request clock_req;
775
776	if (!smu->ppt_funcs)
777		return PP_SMU_RESULT_UNSUPPORTED;
778
779	clock_req.clock_type = amd_pp_dcef_clock;
780	clock_req.clock_freq_in_khz = mhz * 1000;
781
782	/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
783	 * 1: fail
784	 */
785	if (smu_display_clock_voltage_request(smu, &clock_req))
786		return PP_SMU_RESULT_FAIL;
787
788	return PP_SMU_RESULT_OK;
789}
790
791enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz)
792{
793	const struct dc_context *ctx = pp->dm;
794	struct amdgpu_device *adev = ctx->driver_context;
795	struct smu_context *smu = &adev->smu;
796	struct pp_display_clock_request clock_req;
797
798	if (!smu->ppt_funcs)
799		return PP_SMU_RESULT_UNSUPPORTED;
800
801	clock_req.clock_type = amd_pp_mem_clock;
802	clock_req.clock_freq_in_khz = mhz * 1000;
803
804	/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
805	 * 1: fail
806	 */
807	if (smu_display_clock_voltage_request(smu, &clock_req))
808		return PP_SMU_RESULT_FAIL;
809
810	return PP_SMU_RESULT_OK;
811}
812
813enum pp_smu_status pp_nv_set_pstate_handshake_support(
814	struct pp_smu *pp, bool pstate_handshake_supported)
815{
816	const struct dc_context *ctx = pp->dm;
817	struct amdgpu_device *adev = ctx->driver_context;
818	struct smu_context *smu = &adev->smu;
819
820	if (smu_display_disable_memory_clock_switch(smu, !pstate_handshake_supported))
821		return PP_SMU_RESULT_FAIL;
822
823	return PP_SMU_RESULT_OK;
824}
825
826enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp,
827		enum pp_smu_nv_clock_id clock_id, int mhz)
828{
829	const struct dc_context *ctx = pp->dm;
830	struct amdgpu_device *adev = ctx->driver_context;
831	struct smu_context *smu = &adev->smu;
832	struct pp_display_clock_request clock_req;
833
834	if (!smu->ppt_funcs)
835		return PP_SMU_RESULT_UNSUPPORTED;
836
837	switch (clock_id) {
838	case PP_SMU_NV_DISPCLK:
839		clock_req.clock_type = amd_pp_disp_clock;
840		break;
841	case PP_SMU_NV_PHYCLK:
842		clock_req.clock_type = amd_pp_phy_clock;
843		break;
844	case PP_SMU_NV_PIXELCLK:
845		clock_req.clock_type = amd_pp_pixel_clock;
846		break;
847	default:
848		break;
849	}
850	clock_req.clock_freq_in_khz = mhz * 1000;
851
852	/* 0: successful or smu.ppt_funcs->display_clock_voltage_request = NULL
853	 * 1: fail
854	 */
855	if (smu_display_clock_voltage_request(smu, &clock_req))
856		return PP_SMU_RESULT_FAIL;
857
858	return PP_SMU_RESULT_OK;
859}
860
861enum pp_smu_status pp_nv_get_maximum_sustainable_clocks(
862		struct pp_smu *pp, struct pp_smu_nv_clock_table *max_clocks)
863{
864	const struct dc_context *ctx = pp->dm;
865	struct amdgpu_device *adev = ctx->driver_context;
866	struct smu_context *smu = &adev->smu;
867
868	if (!smu->ppt_funcs)
869		return PP_SMU_RESULT_UNSUPPORTED;
870
871	if (!smu->ppt_funcs->get_max_sustainable_clocks_by_dc)
872		return PP_SMU_RESULT_UNSUPPORTED;
873
874	if (!smu_get_max_sustainable_clocks_by_dc(smu, max_clocks))
875		return PP_SMU_RESULT_OK;
876
877	return PP_SMU_RESULT_FAIL;
878}
879
880enum pp_smu_status pp_nv_get_uclk_dpm_states(struct pp_smu *pp,
881		unsigned int *clock_values_in_khz, unsigned int *num_states)
882{
883	const struct dc_context *ctx = pp->dm;
884	struct amdgpu_device *adev = ctx->driver_context;
885	struct smu_context *smu = &adev->smu;
886
887	if (!smu->ppt_funcs)
888		return PP_SMU_RESULT_UNSUPPORTED;
889
890	if (!smu->ppt_funcs->get_uclk_dpm_states)
891		return PP_SMU_RESULT_UNSUPPORTED;
892
893	if (!smu_get_uclk_dpm_states(smu,
894			clock_values_in_khz, num_states))
895		return PP_SMU_RESULT_OK;
896
897	return PP_SMU_RESULT_FAIL;
898}
899
900enum pp_smu_status pp_rn_get_dpm_clock_table(
901		struct pp_smu *pp, struct dpm_clocks *clock_table)
902{
903	const struct dc_context *ctx = pp->dm;
904	struct amdgpu_device *adev = ctx->driver_context;
905	struct smu_context *smu = &adev->smu;
906
907	if (!smu->ppt_funcs)
908		return PP_SMU_RESULT_UNSUPPORTED;
909
910	if (!smu->ppt_funcs->get_dpm_clock_table)
911		return PP_SMU_RESULT_UNSUPPORTED;
912
913	if (!smu_get_dpm_clock_table(smu, clock_table))
914		return PP_SMU_RESULT_OK;
915
916	return PP_SMU_RESULT_FAIL;
917}
918
919enum pp_smu_status pp_rn_set_wm_ranges(struct pp_smu *pp,
920		struct pp_smu_wm_range_sets *ranges)
921{
922	const struct dc_context *ctx = pp->dm;
923	struct amdgpu_device *adev = ctx->driver_context;
924	struct smu_context *smu = &adev->smu;
925	struct dm_pp_wm_sets_with_clock_ranges_soc15 wm_with_clock_ranges;
926	struct dm_pp_clock_range_for_dmif_wm_set_soc15 *wm_dce_clocks =
927			wm_with_clock_ranges.wm_dmif_clocks_ranges;
928	struct dm_pp_clock_range_for_mcif_wm_set_soc15 *wm_soc_clocks =
929			wm_with_clock_ranges.wm_mcif_clocks_ranges;
930	int32_t i;
931
932	if (!smu->ppt_funcs)
933		return PP_SMU_RESULT_UNSUPPORTED;
934
935	wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets;
936	wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets;
937
938	for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) {
939		if (ranges->reader_wm_sets[i].wm_inst > 3)
940			wm_dce_clocks[i].wm_set_id = WM_SET_A;
941		else
942			wm_dce_clocks[i].wm_set_id =
943					ranges->reader_wm_sets[i].wm_inst;
944
945		wm_dce_clocks[i].wm_min_dcfclk_clk_in_khz =
946			ranges->reader_wm_sets[i].min_drain_clk_mhz;
947
948		wm_dce_clocks[i].wm_max_dcfclk_clk_in_khz =
949			ranges->reader_wm_sets[i].max_drain_clk_mhz;
950
951		wm_dce_clocks[i].wm_min_mem_clk_in_khz =
952			ranges->reader_wm_sets[i].min_fill_clk_mhz;
953
954		wm_dce_clocks[i].wm_max_mem_clk_in_khz =
955			ranges->reader_wm_sets[i].max_fill_clk_mhz;
956	}
957
958	for (i = 0; i < wm_with_clock_ranges.num_wm_mcif_sets; i++) {
959		if (ranges->writer_wm_sets[i].wm_inst > 3)
960			wm_soc_clocks[i].wm_set_id = WM_SET_A;
961		else
962			wm_soc_clocks[i].wm_set_id =
963					ranges->writer_wm_sets[i].wm_inst;
964		wm_soc_clocks[i].wm_min_socclk_clk_in_khz =
965				ranges->writer_wm_sets[i].min_fill_clk_mhz;
966
967		wm_soc_clocks[i].wm_max_socclk_clk_in_khz =
968			ranges->writer_wm_sets[i].max_fill_clk_mhz;
969
970		wm_soc_clocks[i].wm_min_mem_clk_in_khz =
971			ranges->writer_wm_sets[i].min_drain_clk_mhz;
972
973		wm_soc_clocks[i].wm_max_mem_clk_in_khz =
974			ranges->writer_wm_sets[i].max_drain_clk_mhz;
975	}
976
977	smu_set_watermarks_for_clock_ranges(&adev->smu, &wm_with_clock_ranges);
978
979	return PP_SMU_RESULT_OK;
980}
981
982void dm_pp_get_funcs(
983		struct dc_context *ctx,
984		struct pp_smu_funcs *funcs)
985{
986	switch (ctx->dce_version) {
987	case DCN_VERSION_1_0:
988	case DCN_VERSION_1_01:
989		funcs->ctx.ver = PP_SMU_VER_RV;
990		funcs->rv_funcs.pp_smu.dm = ctx;
991		funcs->rv_funcs.set_wm_ranges = pp_rv_set_wm_ranges;
992		funcs->rv_funcs.set_pme_wa_enable = pp_rv_set_pme_wa_enable;
993		funcs->rv_funcs.set_display_count =
994				pp_rv_set_active_display_count;
995		funcs->rv_funcs.set_min_deep_sleep_dcfclk =
996				pp_rv_set_min_deep_sleep_dcfclk;
997		funcs->rv_funcs.set_hard_min_dcfclk_by_freq =
998				pp_rv_set_hard_min_dcefclk_by_freq;
999		funcs->rv_funcs.set_hard_min_fclk_by_freq =
1000				pp_rv_set_hard_min_fclk_by_freq;
1001		break;
1002	case DCN_VERSION_2_0:
1003		funcs->ctx.ver = PP_SMU_VER_NV;
1004		funcs->nv_funcs.pp_smu.dm = ctx;
1005		funcs->nv_funcs.set_display_count = pp_nv_set_display_count;
1006		funcs->nv_funcs.set_hard_min_dcfclk_by_freq =
1007				pp_nv_set_hard_min_dcefclk_by_freq;
1008		funcs->nv_funcs.set_min_deep_sleep_dcfclk =
1009				pp_nv_set_min_deep_sleep_dcfclk;
1010		funcs->nv_funcs.set_voltage_by_freq =
1011				pp_nv_set_voltage_by_freq;
1012		funcs->nv_funcs.set_wm_ranges = pp_nv_set_wm_ranges;
1013
1014		/* todo set_pme_wa_enable cause 4k@6ohz display not light up */
1015		funcs->nv_funcs.set_pme_wa_enable = NULL;
1016		/* todo debug waring message */
1017		funcs->nv_funcs.set_hard_min_uclk_by_freq = pp_nv_set_hard_min_uclk_by_freq;
1018		/* todo  compare data with window driver*/
1019		funcs->nv_funcs.get_maximum_sustainable_clocks = pp_nv_get_maximum_sustainable_clocks;
1020		/*todo  compare data with window driver */
1021		funcs->nv_funcs.get_uclk_dpm_states = pp_nv_get_uclk_dpm_states;
1022		funcs->nv_funcs.set_pstate_handshake_support = pp_nv_set_pstate_handshake_support;
1023		break;
1024
1025	case DCN_VERSION_2_1:
1026		funcs->ctx.ver = PP_SMU_VER_RN;
1027		funcs->rn_funcs.pp_smu.dm = ctx;
1028		funcs->rn_funcs.set_wm_ranges = pp_rn_set_wm_ranges;
1029		funcs->rn_funcs.get_dpm_clock_table = pp_rn_get_dpm_clock_table;
1030		break;
1031	default:
1032		DRM_ERROR("smu version is not supported !\n");
1033		break;
1034	}
1035}
1036