18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2011 Advanced Micro Devices, Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software.
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * Authors: Alex Deucher
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include "amdgpu.h"
268c2ecf20Sopenharmony_ci#include "amdgpu_atombios.h"
278c2ecf20Sopenharmony_ci#include "amdgpu_i2c.h"
288c2ecf20Sopenharmony_ci#include "amdgpu_dpm.h"
298c2ecf20Sopenharmony_ci#include "atom.h"
308c2ecf20Sopenharmony_ci#include "amd_pcie.h"
318c2ecf20Sopenharmony_ci#include "amdgpu_display.h"
328c2ecf20Sopenharmony_ci#include "hwmgr.h"
338c2ecf20Sopenharmony_ci#include <linux/power_supply.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define WIDTH_4K 3840
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_civoid amdgpu_dpm_print_class_info(u32 class, u32 class2)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	const char *s;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) {
428c2ecf20Sopenharmony_ci	case ATOM_PPLIB_CLASSIFICATION_UI_NONE:
438c2ecf20Sopenharmony_ci	default:
448c2ecf20Sopenharmony_ci		s = "none";
458c2ecf20Sopenharmony_ci		break;
468c2ecf20Sopenharmony_ci	case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY:
478c2ecf20Sopenharmony_ci		s = "battery";
488c2ecf20Sopenharmony_ci		break;
498c2ecf20Sopenharmony_ci	case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED:
508c2ecf20Sopenharmony_ci		s = "balanced";
518c2ecf20Sopenharmony_ci		break;
528c2ecf20Sopenharmony_ci	case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE:
538c2ecf20Sopenharmony_ci		s = "performance";
548c2ecf20Sopenharmony_ci		break;
558c2ecf20Sopenharmony_ci	}
568c2ecf20Sopenharmony_ci	printk("\tui class: %s\n", s);
578c2ecf20Sopenharmony_ci	printk("\tinternal class:");
588c2ecf20Sopenharmony_ci	if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) &&
598c2ecf20Sopenharmony_ci	    (class2 == 0))
608c2ecf20Sopenharmony_ci		pr_cont(" none");
618c2ecf20Sopenharmony_ci	else {
628c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_BOOT)
638c2ecf20Sopenharmony_ci			pr_cont(" boot");
648c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
658c2ecf20Sopenharmony_ci			pr_cont(" thermal");
668c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)
678c2ecf20Sopenharmony_ci			pr_cont(" limited_pwr");
688c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_REST)
698c2ecf20Sopenharmony_ci			pr_cont(" rest");
708c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_FORCED)
718c2ecf20Sopenharmony_ci			pr_cont(" forced");
728c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
738c2ecf20Sopenharmony_ci			pr_cont(" 3d_perf");
748c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)
758c2ecf20Sopenharmony_ci			pr_cont(" ovrdrv");
768c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
778c2ecf20Sopenharmony_ci			pr_cont(" uvd");
788c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW)
798c2ecf20Sopenharmony_ci			pr_cont(" 3d_low");
808c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_ACPI)
818c2ecf20Sopenharmony_ci			pr_cont(" acpi");
828c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
838c2ecf20Sopenharmony_ci			pr_cont(" uvd_hd2");
848c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
858c2ecf20Sopenharmony_ci			pr_cont(" uvd_hd");
868c2ecf20Sopenharmony_ci		if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
878c2ecf20Sopenharmony_ci			pr_cont(" uvd_sd");
888c2ecf20Sopenharmony_ci		if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)
898c2ecf20Sopenharmony_ci			pr_cont(" limited_pwr2");
908c2ecf20Sopenharmony_ci		if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
918c2ecf20Sopenharmony_ci			pr_cont(" ulv");
928c2ecf20Sopenharmony_ci		if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
938c2ecf20Sopenharmony_ci			pr_cont(" uvd_mvc");
948c2ecf20Sopenharmony_ci	}
958c2ecf20Sopenharmony_ci	pr_cont("\n");
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_civoid amdgpu_dpm_print_cap_info(u32 caps)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	printk("\tcaps:");
1018c2ecf20Sopenharmony_ci	if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
1028c2ecf20Sopenharmony_ci		pr_cont(" single_disp");
1038c2ecf20Sopenharmony_ci	if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK)
1048c2ecf20Sopenharmony_ci		pr_cont(" video");
1058c2ecf20Sopenharmony_ci	if (caps & ATOM_PPLIB_DISALLOW_ON_DC)
1068c2ecf20Sopenharmony_ci		pr_cont(" no_dc");
1078c2ecf20Sopenharmony_ci	pr_cont("\n");
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_civoid amdgpu_dpm_print_ps_status(struct amdgpu_device *adev,
1118c2ecf20Sopenharmony_ci				struct amdgpu_ps *rps)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	printk("\tstatus:");
1148c2ecf20Sopenharmony_ci	if (rps == adev->pm.dpm.current_ps)
1158c2ecf20Sopenharmony_ci		pr_cont(" c");
1168c2ecf20Sopenharmony_ci	if (rps == adev->pm.dpm.requested_ps)
1178c2ecf20Sopenharmony_ci		pr_cont(" r");
1188c2ecf20Sopenharmony_ci	if (rps == adev->pm.dpm.boot_ps)
1198c2ecf20Sopenharmony_ci		pr_cont(" b");
1208c2ecf20Sopenharmony_ci	pr_cont("\n");
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_civoid amdgpu_dpm_get_active_displays(struct amdgpu_device *adev)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	struct drm_device *ddev = adev_to_drm(adev);
1268c2ecf20Sopenharmony_ci	struct drm_crtc *crtc;
1278c2ecf20Sopenharmony_ci	struct amdgpu_crtc *amdgpu_crtc;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	adev->pm.dpm.new_active_crtcs = 0;
1308c2ecf20Sopenharmony_ci	adev->pm.dpm.new_active_crtc_count = 0;
1318c2ecf20Sopenharmony_ci	if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
1328c2ecf20Sopenharmony_ci		list_for_each_entry(crtc,
1338c2ecf20Sopenharmony_ci				    &ddev->mode_config.crtc_list, head) {
1348c2ecf20Sopenharmony_ci			amdgpu_crtc = to_amdgpu_crtc(crtc);
1358c2ecf20Sopenharmony_ci			if (amdgpu_crtc->enabled) {
1368c2ecf20Sopenharmony_ci				adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
1378c2ecf20Sopenharmony_ci				adev->pm.dpm.new_active_crtc_count++;
1388c2ecf20Sopenharmony_ci			}
1398c2ecf20Sopenharmony_ci		}
1408c2ecf20Sopenharmony_ci	}
1418c2ecf20Sopenharmony_ci}
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ciu32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	struct drm_device *dev = adev_to_drm(adev);
1478c2ecf20Sopenharmony_ci	struct drm_crtc *crtc;
1488c2ecf20Sopenharmony_ci	struct amdgpu_crtc *amdgpu_crtc;
1498c2ecf20Sopenharmony_ci	u32 vblank_in_pixels;
1508c2ecf20Sopenharmony_ci	u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
1538c2ecf20Sopenharmony_ci		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1548c2ecf20Sopenharmony_ci			amdgpu_crtc = to_amdgpu_crtc(crtc);
1558c2ecf20Sopenharmony_ci			if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
1568c2ecf20Sopenharmony_ci				vblank_in_pixels =
1578c2ecf20Sopenharmony_ci					amdgpu_crtc->hw_mode.crtc_htotal *
1588c2ecf20Sopenharmony_ci					(amdgpu_crtc->hw_mode.crtc_vblank_end -
1598c2ecf20Sopenharmony_ci					amdgpu_crtc->hw_mode.crtc_vdisplay +
1608c2ecf20Sopenharmony_ci					(amdgpu_crtc->v_border * 2));
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci				vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock;
1638c2ecf20Sopenharmony_ci				break;
1648c2ecf20Sopenharmony_ci			}
1658c2ecf20Sopenharmony_ci		}
1668c2ecf20Sopenharmony_ci	}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	return vblank_time_us;
1698c2ecf20Sopenharmony_ci}
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ciu32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	struct drm_device *dev = adev_to_drm(adev);
1748c2ecf20Sopenharmony_ci	struct drm_crtc *crtc;
1758c2ecf20Sopenharmony_ci	struct amdgpu_crtc *amdgpu_crtc;
1768c2ecf20Sopenharmony_ci	u32 vrefresh = 0;
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) {
1798c2ecf20Sopenharmony_ci		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1808c2ecf20Sopenharmony_ci			amdgpu_crtc = to_amdgpu_crtc(crtc);
1818c2ecf20Sopenharmony_ci			if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
1828c2ecf20Sopenharmony_ci				vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
1838c2ecf20Sopenharmony_ci				break;
1848c2ecf20Sopenharmony_ci			}
1858c2ecf20Sopenharmony_ci		}
1868c2ecf20Sopenharmony_ci	}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	return vrefresh;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cibool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	switch (sensor) {
1948c2ecf20Sopenharmony_ci	case THERMAL_TYPE_RV6XX:
1958c2ecf20Sopenharmony_ci	case THERMAL_TYPE_RV770:
1968c2ecf20Sopenharmony_ci	case THERMAL_TYPE_EVERGREEN:
1978c2ecf20Sopenharmony_ci	case THERMAL_TYPE_SUMO:
1988c2ecf20Sopenharmony_ci	case THERMAL_TYPE_NI:
1998c2ecf20Sopenharmony_ci	case THERMAL_TYPE_SI:
2008c2ecf20Sopenharmony_ci	case THERMAL_TYPE_CI:
2018c2ecf20Sopenharmony_ci	case THERMAL_TYPE_KV:
2028c2ecf20Sopenharmony_ci		return true;
2038c2ecf20Sopenharmony_ci	case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
2048c2ecf20Sopenharmony_ci	case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
2058c2ecf20Sopenharmony_ci		return false; /* need special handling */
2068c2ecf20Sopenharmony_ci	case THERMAL_TYPE_NONE:
2078c2ecf20Sopenharmony_ci	case THERMAL_TYPE_EXTERNAL:
2088c2ecf20Sopenharmony_ci	case THERMAL_TYPE_EXTERNAL_GPIO:
2098c2ecf20Sopenharmony_ci	default:
2108c2ecf20Sopenharmony_ci		return false;
2118c2ecf20Sopenharmony_ci	}
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ciunion power_info {
2158c2ecf20Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO info;
2168c2ecf20Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V2 info_2;
2178c2ecf20Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V3 info_3;
2188c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
2198c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
2208c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
2218c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4;
2228c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5;
2238c2ecf20Sopenharmony_ci};
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ciunion fan_info {
2268c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_FANTABLE fan;
2278c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_FANTABLE2 fan2;
2288c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_FANTABLE3 fan3;
2298c2ecf20Sopenharmony_ci};
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table,
2328c2ecf20Sopenharmony_ci					      ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	u32 size = atom_table->ucNumEntries *
2358c2ecf20Sopenharmony_ci		sizeof(struct amdgpu_clock_voltage_dependency_entry);
2368c2ecf20Sopenharmony_ci	int i;
2378c2ecf20Sopenharmony_ci	ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	amdgpu_table->entries = kzalloc(size, GFP_KERNEL);
2408c2ecf20Sopenharmony_ci	if (!amdgpu_table->entries)
2418c2ecf20Sopenharmony_ci		return -ENOMEM;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	entry = &atom_table->entries[0];
2448c2ecf20Sopenharmony_ci	for (i = 0; i < atom_table->ucNumEntries; i++) {
2458c2ecf20Sopenharmony_ci		amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) |
2468c2ecf20Sopenharmony_ci			(entry->ucClockHigh << 16);
2478c2ecf20Sopenharmony_ci		amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage);
2488c2ecf20Sopenharmony_ci		entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *)
2498c2ecf20Sopenharmony_ci			((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record));
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci	amdgpu_table->count = atom_table->ucNumEntries;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	return 0;
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ciint amdgpu_get_platform_caps(struct amdgpu_device *adev)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct amdgpu_mode_info *mode_info = &adev->mode_info;
2598c2ecf20Sopenharmony_ci	union power_info *power_info;
2608c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2618c2ecf20Sopenharmony_ci	u16 data_offset;
2628c2ecf20Sopenharmony_ci	u8 frev, crev;
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
2658c2ecf20Sopenharmony_ci				   &frev, &crev, &data_offset))
2668c2ecf20Sopenharmony_ci		return -EINVAL;
2678c2ecf20Sopenharmony_ci	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
2708c2ecf20Sopenharmony_ci	adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
2718c2ecf20Sopenharmony_ci	adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	return 0;
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */
2778c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12
2788c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14
2798c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16
2808c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18
2818c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20
2828c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22
2838c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24
2848c2ecf20Sopenharmony_ci#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ciint amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	struct amdgpu_mode_info *mode_info = &adev->mode_info;
2898c2ecf20Sopenharmony_ci	union power_info *power_info;
2908c2ecf20Sopenharmony_ci	union fan_info *fan_info;
2918c2ecf20Sopenharmony_ci	ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table;
2928c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2938c2ecf20Sopenharmony_ci	u16 data_offset;
2948c2ecf20Sopenharmony_ci	u8 frev, crev;
2958c2ecf20Sopenharmony_ci	int ret, i;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
2988c2ecf20Sopenharmony_ci				   &frev, &crev, &data_offset))
2998c2ecf20Sopenharmony_ci		return -EINVAL;
3008c2ecf20Sopenharmony_ci	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	/* fan table */
3038c2ecf20Sopenharmony_ci	if (le16_to_cpu(power_info->pplib.usTableSize) >=
3048c2ecf20Sopenharmony_ci	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
3058c2ecf20Sopenharmony_ci		if (power_info->pplib3.usFanTableOffset) {
3068c2ecf20Sopenharmony_ci			fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset +
3078c2ecf20Sopenharmony_ci						      le16_to_cpu(power_info->pplib3.usFanTableOffset));
3088c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst;
3098c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin);
3108c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed);
3118c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh);
3128c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin);
3138c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed);
3148c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh);
3158c2ecf20Sopenharmony_ci			if (fan_info->fan.ucFanTableFormat >= 2)
3168c2ecf20Sopenharmony_ci				adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax);
3178c2ecf20Sopenharmony_ci			else
3188c2ecf20Sopenharmony_ci				adev->pm.dpm.fan.t_max = 10900;
3198c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.cycle_delay = 100000;
3208c2ecf20Sopenharmony_ci			if (fan_info->fan.ucFanTableFormat >= 3) {
3218c2ecf20Sopenharmony_ci				adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode;
3228c2ecf20Sopenharmony_ci				adev->pm.dpm.fan.default_max_fan_pwm =
3238c2ecf20Sopenharmony_ci					le16_to_cpu(fan_info->fan3.usFanPWMMax);
3248c2ecf20Sopenharmony_ci				adev->pm.dpm.fan.default_fan_output_sensitivity = 4836;
3258c2ecf20Sopenharmony_ci				adev->pm.dpm.fan.fan_output_sensitivity =
3268c2ecf20Sopenharmony_ci					le16_to_cpu(fan_info->fan3.usFanOutputSensitivity);
3278c2ecf20Sopenharmony_ci			}
3288c2ecf20Sopenharmony_ci			adev->pm.dpm.fan.ucode_fan_control = true;
3298c2ecf20Sopenharmony_ci		}
3308c2ecf20Sopenharmony_ci	}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	/* clock dependancy tables, shedding tables */
3338c2ecf20Sopenharmony_ci	if (le16_to_cpu(power_info->pplib.usTableSize) >=
3348c2ecf20Sopenharmony_ci	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) {
3358c2ecf20Sopenharmony_ci		if (power_info->pplib4.usVddcDependencyOnSCLKOffset) {
3368c2ecf20Sopenharmony_ci			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
3378c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
3388c2ecf20Sopenharmony_ci				 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset));
3398c2ecf20Sopenharmony_ci			ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
3408c2ecf20Sopenharmony_ci								 dep_table);
3418c2ecf20Sopenharmony_ci			if (ret) {
3428c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
3438c2ecf20Sopenharmony_ci				return ret;
3448c2ecf20Sopenharmony_ci			}
3458c2ecf20Sopenharmony_ci		}
3468c2ecf20Sopenharmony_ci		if (power_info->pplib4.usVddciDependencyOnMCLKOffset) {
3478c2ecf20Sopenharmony_ci			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
3488c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
3498c2ecf20Sopenharmony_ci				 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset));
3508c2ecf20Sopenharmony_ci			ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
3518c2ecf20Sopenharmony_ci								 dep_table);
3528c2ecf20Sopenharmony_ci			if (ret) {
3538c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
3548c2ecf20Sopenharmony_ci				return ret;
3558c2ecf20Sopenharmony_ci			}
3568c2ecf20Sopenharmony_ci		}
3578c2ecf20Sopenharmony_ci		if (power_info->pplib4.usVddcDependencyOnMCLKOffset) {
3588c2ecf20Sopenharmony_ci			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
3598c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
3608c2ecf20Sopenharmony_ci				 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset));
3618c2ecf20Sopenharmony_ci			ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
3628c2ecf20Sopenharmony_ci								 dep_table);
3638c2ecf20Sopenharmony_ci			if (ret) {
3648c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
3658c2ecf20Sopenharmony_ci				return ret;
3668c2ecf20Sopenharmony_ci			}
3678c2ecf20Sopenharmony_ci		}
3688c2ecf20Sopenharmony_ci		if (power_info->pplib4.usMvddDependencyOnMCLKOffset) {
3698c2ecf20Sopenharmony_ci			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
3708c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
3718c2ecf20Sopenharmony_ci				 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset));
3728c2ecf20Sopenharmony_ci			ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk,
3738c2ecf20Sopenharmony_ci								 dep_table);
3748c2ecf20Sopenharmony_ci			if (ret) {
3758c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
3768c2ecf20Sopenharmony_ci				return ret;
3778c2ecf20Sopenharmony_ci			}
3788c2ecf20Sopenharmony_ci		}
3798c2ecf20Sopenharmony_ci		if (power_info->pplib4.usMaxClockVoltageOnDCOffset) {
3808c2ecf20Sopenharmony_ci			ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v =
3818c2ecf20Sopenharmony_ci				(ATOM_PPLIB_Clock_Voltage_Limit_Table *)
3828c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
3838c2ecf20Sopenharmony_ci				 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset));
3848c2ecf20Sopenharmony_ci			if (clk_v->ucNumEntries) {
3858c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk =
3868c2ecf20Sopenharmony_ci					le16_to_cpu(clk_v->entries[0].usSclkLow) |
3878c2ecf20Sopenharmony_ci					(clk_v->entries[0].ucSclkHigh << 16);
3888c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk =
3898c2ecf20Sopenharmony_ci					le16_to_cpu(clk_v->entries[0].usMclkLow) |
3908c2ecf20Sopenharmony_ci					(clk_v->entries[0].ucMclkHigh << 16);
3918c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc =
3928c2ecf20Sopenharmony_ci					le16_to_cpu(clk_v->entries[0].usVddc);
3938c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci =
3948c2ecf20Sopenharmony_ci					le16_to_cpu(clk_v->entries[0].usVddci);
3958c2ecf20Sopenharmony_ci			}
3968c2ecf20Sopenharmony_ci		}
3978c2ecf20Sopenharmony_ci		if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) {
3988c2ecf20Sopenharmony_ci			ATOM_PPLIB_PhaseSheddingLimits_Table *psl =
3998c2ecf20Sopenharmony_ci				(ATOM_PPLIB_PhaseSheddingLimits_Table *)
4008c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
4018c2ecf20Sopenharmony_ci				 le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset));
4028c2ecf20Sopenharmony_ci			ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
4058c2ecf20Sopenharmony_ci				kcalloc(psl->ucNumEntries,
4068c2ecf20Sopenharmony_ci					sizeof(struct amdgpu_phase_shedding_limits_entry),
4078c2ecf20Sopenharmony_ci					GFP_KERNEL);
4088c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
4098c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
4108c2ecf20Sopenharmony_ci				return -ENOMEM;
4118c2ecf20Sopenharmony_ci			}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci			entry = &psl->entries[0];
4148c2ecf20Sopenharmony_ci			for (i = 0; i < psl->ucNumEntries; i++) {
4158c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk =
4168c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16);
4178c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk =
4188c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16);
4198c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage =
4208c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usVoltage);
4218c2ecf20Sopenharmony_ci				entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *)
4228c2ecf20Sopenharmony_ci					((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record));
4238c2ecf20Sopenharmony_ci			}
4248c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.phase_shedding_limits_table.count =
4258c2ecf20Sopenharmony_ci				psl->ucNumEntries;
4268c2ecf20Sopenharmony_ci		}
4278c2ecf20Sopenharmony_ci	}
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	/* cac data */
4308c2ecf20Sopenharmony_ci	if (le16_to_cpu(power_info->pplib.usTableSize) >=
4318c2ecf20Sopenharmony_ci	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) {
4328c2ecf20Sopenharmony_ci		adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit);
4338c2ecf20Sopenharmony_ci		adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit);
4348c2ecf20Sopenharmony_ci		adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit;
4358c2ecf20Sopenharmony_ci		adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit);
4368c2ecf20Sopenharmony_ci		if (adev->pm.dpm.tdp_od_limit)
4378c2ecf20Sopenharmony_ci			adev->pm.dpm.power_control = true;
4388c2ecf20Sopenharmony_ci		else
4398c2ecf20Sopenharmony_ci			adev->pm.dpm.power_control = false;
4408c2ecf20Sopenharmony_ci		adev->pm.dpm.tdp_adjustment = 0;
4418c2ecf20Sopenharmony_ci		adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold);
4428c2ecf20Sopenharmony_ci		adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage);
4438c2ecf20Sopenharmony_ci		adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope);
4448c2ecf20Sopenharmony_ci		if (power_info->pplib5.usCACLeakageTableOffset) {
4458c2ecf20Sopenharmony_ci			ATOM_PPLIB_CAC_Leakage_Table *cac_table =
4468c2ecf20Sopenharmony_ci				(ATOM_PPLIB_CAC_Leakage_Table *)
4478c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
4488c2ecf20Sopenharmony_ci				 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset));
4498c2ecf20Sopenharmony_ci			ATOM_PPLIB_CAC_Leakage_Record *entry;
4508c2ecf20Sopenharmony_ci			u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table);
4518c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL);
4528c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) {
4538c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
4548c2ecf20Sopenharmony_ci				return -ENOMEM;
4558c2ecf20Sopenharmony_ci			}
4568c2ecf20Sopenharmony_ci			entry = &cac_table->entries[0];
4578c2ecf20Sopenharmony_ci			for (i = 0; i < cac_table->ucNumEntries; i++) {
4588c2ecf20Sopenharmony_ci				if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) {
4598c2ecf20Sopenharmony_ci					adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 =
4608c2ecf20Sopenharmony_ci						le16_to_cpu(entry->usVddc1);
4618c2ecf20Sopenharmony_ci					adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 =
4628c2ecf20Sopenharmony_ci						le16_to_cpu(entry->usVddc2);
4638c2ecf20Sopenharmony_ci					adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 =
4648c2ecf20Sopenharmony_ci						le16_to_cpu(entry->usVddc3);
4658c2ecf20Sopenharmony_ci				} else {
4668c2ecf20Sopenharmony_ci					adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc =
4678c2ecf20Sopenharmony_ci						le16_to_cpu(entry->usVddc);
4688c2ecf20Sopenharmony_ci					adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage =
4698c2ecf20Sopenharmony_ci						le32_to_cpu(entry->ulLeakageValue);
4708c2ecf20Sopenharmony_ci				}
4718c2ecf20Sopenharmony_ci				entry = (ATOM_PPLIB_CAC_Leakage_Record *)
4728c2ecf20Sopenharmony_ci					((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record));
4738c2ecf20Sopenharmony_ci			}
4748c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries;
4758c2ecf20Sopenharmony_ci		}
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	/* ext tables */
4798c2ecf20Sopenharmony_ci	if (le16_to_cpu(power_info->pplib.usTableSize) >=
4808c2ecf20Sopenharmony_ci	    sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) {
4818c2ecf20Sopenharmony_ci		ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *)
4828c2ecf20Sopenharmony_ci			(mode_info->atom_context->bios + data_offset +
4838c2ecf20Sopenharmony_ci			 le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset));
4848c2ecf20Sopenharmony_ci		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) &&
4858c2ecf20Sopenharmony_ci			ext_hdr->usVCETableOffset) {
4868c2ecf20Sopenharmony_ci			VCEClockInfoArray *array = (VCEClockInfoArray *)
4878c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
4888c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1);
4898c2ecf20Sopenharmony_ci			ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits =
4908c2ecf20Sopenharmony_ci				(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)
4918c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
4928c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
4938c2ecf20Sopenharmony_ci				 1 + array->ucNumEntries * sizeof(VCEClockInfo));
4948c2ecf20Sopenharmony_ci			ATOM_PPLIB_VCE_State_Table *states =
4958c2ecf20Sopenharmony_ci				(ATOM_PPLIB_VCE_State_Table *)
4968c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
4978c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 +
4988c2ecf20Sopenharmony_ci				 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) +
4998c2ecf20Sopenharmony_ci				 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)));
5008c2ecf20Sopenharmony_ci			ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry;
5018c2ecf20Sopenharmony_ci			ATOM_PPLIB_VCE_State_Record *state_entry;
5028c2ecf20Sopenharmony_ci			VCEClockInfo *vce_clk;
5038c2ecf20Sopenharmony_ci			u32 size = limits->numEntries *
5048c2ecf20Sopenharmony_ci				sizeof(struct amdgpu_vce_clock_voltage_dependency_entry);
5058c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries =
5068c2ecf20Sopenharmony_ci				kzalloc(size, GFP_KERNEL);
5078c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) {
5088c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
5098c2ecf20Sopenharmony_ci				return -ENOMEM;
5108c2ecf20Sopenharmony_ci			}
5118c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count =
5128c2ecf20Sopenharmony_ci				limits->numEntries;
5138c2ecf20Sopenharmony_ci			entry = &limits->entries[0];
5148c2ecf20Sopenharmony_ci			state_entry = &states->entries[0];
5158c2ecf20Sopenharmony_ci			for (i = 0; i < limits->numEntries; i++) {
5168c2ecf20Sopenharmony_ci				vce_clk = (VCEClockInfo *)
5178c2ecf20Sopenharmony_ci					((u8 *)&array->entries[0] +
5188c2ecf20Sopenharmony_ci					 (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
5198c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk =
5208c2ecf20Sopenharmony_ci					le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
5218c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk =
5228c2ecf20Sopenharmony_ci					le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
5238c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v =
5248c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usVoltage);
5258c2ecf20Sopenharmony_ci				entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
5268c2ecf20Sopenharmony_ci					((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
5278c2ecf20Sopenharmony_ci			}
5288c2ecf20Sopenharmony_ci			adev->pm.dpm.num_of_vce_states =
5298c2ecf20Sopenharmony_ci					states->numEntries > AMD_MAX_VCE_LEVELS ?
5308c2ecf20Sopenharmony_ci					AMD_MAX_VCE_LEVELS : states->numEntries;
5318c2ecf20Sopenharmony_ci			for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
5328c2ecf20Sopenharmony_ci				vce_clk = (VCEClockInfo *)
5338c2ecf20Sopenharmony_ci					((u8 *)&array->entries[0] +
5348c2ecf20Sopenharmony_ci					 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
5358c2ecf20Sopenharmony_ci				adev->pm.dpm.vce_states[i].evclk =
5368c2ecf20Sopenharmony_ci					le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16);
5378c2ecf20Sopenharmony_ci				adev->pm.dpm.vce_states[i].ecclk =
5388c2ecf20Sopenharmony_ci					le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16);
5398c2ecf20Sopenharmony_ci				adev->pm.dpm.vce_states[i].clk_idx =
5408c2ecf20Sopenharmony_ci					state_entry->ucClockInfoIndex & 0x3f;
5418c2ecf20Sopenharmony_ci				adev->pm.dpm.vce_states[i].pstate =
5428c2ecf20Sopenharmony_ci					(state_entry->ucClockInfoIndex & 0xc0) >> 6;
5438c2ecf20Sopenharmony_ci				state_entry = (ATOM_PPLIB_VCE_State_Record *)
5448c2ecf20Sopenharmony_ci					((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record));
5458c2ecf20Sopenharmony_ci			}
5468c2ecf20Sopenharmony_ci		}
5478c2ecf20Sopenharmony_ci		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) &&
5488c2ecf20Sopenharmony_ci			ext_hdr->usUVDTableOffset) {
5498c2ecf20Sopenharmony_ci			UVDClockInfoArray *array = (UVDClockInfoArray *)
5508c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
5518c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1);
5528c2ecf20Sopenharmony_ci			ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits =
5538c2ecf20Sopenharmony_ci				(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)
5548c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
5558c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 +
5568c2ecf20Sopenharmony_ci				 1 + (array->ucNumEntries * sizeof (UVDClockInfo)));
5578c2ecf20Sopenharmony_ci			ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry;
5588c2ecf20Sopenharmony_ci			u32 size = limits->numEntries *
5598c2ecf20Sopenharmony_ci				sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry);
5608c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries =
5618c2ecf20Sopenharmony_ci				kzalloc(size, GFP_KERNEL);
5628c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) {
5638c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
5648c2ecf20Sopenharmony_ci				return -ENOMEM;
5658c2ecf20Sopenharmony_ci			}
5668c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count =
5678c2ecf20Sopenharmony_ci				limits->numEntries;
5688c2ecf20Sopenharmony_ci			entry = &limits->entries[0];
5698c2ecf20Sopenharmony_ci			for (i = 0; i < limits->numEntries; i++) {
5708c2ecf20Sopenharmony_ci				UVDClockInfo *uvd_clk = (UVDClockInfo *)
5718c2ecf20Sopenharmony_ci					((u8 *)&array->entries[0] +
5728c2ecf20Sopenharmony_ci					 (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo)));
5738c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk =
5748c2ecf20Sopenharmony_ci					le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16);
5758c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk =
5768c2ecf20Sopenharmony_ci					le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16);
5778c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v =
5788c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usVoltage);
5798c2ecf20Sopenharmony_ci				entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *)
5808c2ecf20Sopenharmony_ci					((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record));
5818c2ecf20Sopenharmony_ci			}
5828c2ecf20Sopenharmony_ci		}
5838c2ecf20Sopenharmony_ci		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) &&
5848c2ecf20Sopenharmony_ci			ext_hdr->usSAMUTableOffset) {
5858c2ecf20Sopenharmony_ci			ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits =
5868c2ecf20Sopenharmony_ci				(ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)
5878c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
5888c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1);
5898c2ecf20Sopenharmony_ci			ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry;
5908c2ecf20Sopenharmony_ci			u32 size = limits->numEntries *
5918c2ecf20Sopenharmony_ci				sizeof(struct amdgpu_clock_voltage_dependency_entry);
5928c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries =
5938c2ecf20Sopenharmony_ci				kzalloc(size, GFP_KERNEL);
5948c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) {
5958c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
5968c2ecf20Sopenharmony_ci				return -ENOMEM;
5978c2ecf20Sopenharmony_ci			}
5988c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count =
5998c2ecf20Sopenharmony_ci				limits->numEntries;
6008c2ecf20Sopenharmony_ci			entry = &limits->entries[0];
6018c2ecf20Sopenharmony_ci			for (i = 0; i < limits->numEntries; i++) {
6028c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk =
6038c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16);
6048c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v =
6058c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usVoltage);
6068c2ecf20Sopenharmony_ci				entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *)
6078c2ecf20Sopenharmony_ci					((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record));
6088c2ecf20Sopenharmony_ci			}
6098c2ecf20Sopenharmony_ci		}
6108c2ecf20Sopenharmony_ci		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) &&
6118c2ecf20Sopenharmony_ci		    ext_hdr->usPPMTableOffset) {
6128c2ecf20Sopenharmony_ci			ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *)
6138c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
6148c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usPPMTableOffset));
6158c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table =
6168c2ecf20Sopenharmony_ci				kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL);
6178c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.ppm_table) {
6188c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
6198c2ecf20Sopenharmony_ci				return -ENOMEM;
6208c2ecf20Sopenharmony_ci			}
6218c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign;
6228c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->cpu_core_number =
6238c2ecf20Sopenharmony_ci				le16_to_cpu(ppm->usCpuCoreNumber);
6248c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->platform_tdp =
6258c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulPlatformTDP);
6268c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp =
6278c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulSmallACPlatformTDP);
6288c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->platform_tdc =
6298c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulPlatformTDC);
6308c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc =
6318c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulSmallACPlatformTDC);
6328c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->apu_tdp =
6338c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulApuTDP);
6348c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp =
6358c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulDGpuTDP);
6368c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power =
6378c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulDGpuUlvPower);
6388c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.ppm_table->tj_max =
6398c2ecf20Sopenharmony_ci				le32_to_cpu(ppm->ulTjmax);
6408c2ecf20Sopenharmony_ci		}
6418c2ecf20Sopenharmony_ci		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) &&
6428c2ecf20Sopenharmony_ci			ext_hdr->usACPTableOffset) {
6438c2ecf20Sopenharmony_ci			ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits =
6448c2ecf20Sopenharmony_ci				(ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)
6458c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
6468c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usACPTableOffset) + 1);
6478c2ecf20Sopenharmony_ci			ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry;
6488c2ecf20Sopenharmony_ci			u32 size = limits->numEntries *
6498c2ecf20Sopenharmony_ci				sizeof(struct amdgpu_clock_voltage_dependency_entry);
6508c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries =
6518c2ecf20Sopenharmony_ci				kzalloc(size, GFP_KERNEL);
6528c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) {
6538c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
6548c2ecf20Sopenharmony_ci				return -ENOMEM;
6558c2ecf20Sopenharmony_ci			}
6568c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count =
6578c2ecf20Sopenharmony_ci				limits->numEntries;
6588c2ecf20Sopenharmony_ci			entry = &limits->entries[0];
6598c2ecf20Sopenharmony_ci			for (i = 0; i < limits->numEntries; i++) {
6608c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk =
6618c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16);
6628c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v =
6638c2ecf20Sopenharmony_ci					le16_to_cpu(entry->usVoltage);
6648c2ecf20Sopenharmony_ci				entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *)
6658c2ecf20Sopenharmony_ci					((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record));
6668c2ecf20Sopenharmony_ci			}
6678c2ecf20Sopenharmony_ci		}
6688c2ecf20Sopenharmony_ci		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) &&
6698c2ecf20Sopenharmony_ci			ext_hdr->usPowerTuneTableOffset) {
6708c2ecf20Sopenharmony_ci			u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset +
6718c2ecf20Sopenharmony_ci					 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
6728c2ecf20Sopenharmony_ci			ATOM_PowerTune_Table *pt;
6738c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table =
6748c2ecf20Sopenharmony_ci				kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL);
6758c2ecf20Sopenharmony_ci			if (!adev->pm.dpm.dyn_state.cac_tdp_table) {
6768c2ecf20Sopenharmony_ci				amdgpu_free_extended_power_table(adev);
6778c2ecf20Sopenharmony_ci				return -ENOMEM;
6788c2ecf20Sopenharmony_ci			}
6798c2ecf20Sopenharmony_ci			if (rev > 0) {
6808c2ecf20Sopenharmony_ci				ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *)
6818c2ecf20Sopenharmony_ci					(mode_info->atom_context->bios + data_offset +
6828c2ecf20Sopenharmony_ci					 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
6838c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit =
6848c2ecf20Sopenharmony_ci					ppt->usMaximumPowerDeliveryLimit;
6858c2ecf20Sopenharmony_ci				pt = &ppt->power_tune_table;
6868c2ecf20Sopenharmony_ci			} else {
6878c2ecf20Sopenharmony_ci				ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *)
6888c2ecf20Sopenharmony_ci					(mode_info->atom_context->bios + data_offset +
6898c2ecf20Sopenharmony_ci					 le16_to_cpu(ext_hdr->usPowerTuneTableOffset));
6908c2ecf20Sopenharmony_ci				adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255;
6918c2ecf20Sopenharmony_ci				pt = &ppt->power_tune_table;
6928c2ecf20Sopenharmony_ci			}
6938c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP);
6948c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp =
6958c2ecf20Sopenharmony_ci				le16_to_cpu(pt->usConfigurableTDP);
6968c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC);
6978c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit =
6988c2ecf20Sopenharmony_ci				le16_to_cpu(pt->usBatteryPowerLimit);
6998c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit =
7008c2ecf20Sopenharmony_ci				le16_to_cpu(pt->usSmallPowerLimit);
7018c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage =
7028c2ecf20Sopenharmony_ci				le16_to_cpu(pt->usLowCACLeakage);
7038c2ecf20Sopenharmony_ci			adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage =
7048c2ecf20Sopenharmony_ci				le16_to_cpu(pt->usHighCACLeakage);
7058c2ecf20Sopenharmony_ci		}
7068c2ecf20Sopenharmony_ci		if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) &&
7078c2ecf20Sopenharmony_ci				ext_hdr->usSclkVddgfxTableOffset) {
7088c2ecf20Sopenharmony_ci			dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)
7098c2ecf20Sopenharmony_ci				(mode_info->atom_context->bios + data_offset +
7108c2ecf20Sopenharmony_ci				 le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset));
7118c2ecf20Sopenharmony_ci			ret = amdgpu_parse_clk_voltage_dep_table(
7128c2ecf20Sopenharmony_ci					&adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk,
7138c2ecf20Sopenharmony_ci					dep_table);
7148c2ecf20Sopenharmony_ci			if (ret) {
7158c2ecf20Sopenharmony_ci				kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries);
7168c2ecf20Sopenharmony_ci				return ret;
7178c2ecf20Sopenharmony_ci			}
7188c2ecf20Sopenharmony_ci		}
7198c2ecf20Sopenharmony_ci	}
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	return 0;
7228c2ecf20Sopenharmony_ci}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_civoid amdgpu_free_extended_power_table(struct amdgpu_device *adev)
7258c2ecf20Sopenharmony_ci{
7268c2ecf20Sopenharmony_ci	struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	kfree(dyn_state->vddc_dependency_on_sclk.entries);
7298c2ecf20Sopenharmony_ci	kfree(dyn_state->vddci_dependency_on_mclk.entries);
7308c2ecf20Sopenharmony_ci	kfree(dyn_state->vddc_dependency_on_mclk.entries);
7318c2ecf20Sopenharmony_ci	kfree(dyn_state->mvdd_dependency_on_mclk.entries);
7328c2ecf20Sopenharmony_ci	kfree(dyn_state->cac_leakage_table.entries);
7338c2ecf20Sopenharmony_ci	kfree(dyn_state->phase_shedding_limits_table.entries);
7348c2ecf20Sopenharmony_ci	kfree(dyn_state->ppm_table);
7358c2ecf20Sopenharmony_ci	kfree(dyn_state->cac_tdp_table);
7368c2ecf20Sopenharmony_ci	kfree(dyn_state->vce_clock_voltage_dependency_table.entries);
7378c2ecf20Sopenharmony_ci	kfree(dyn_state->uvd_clock_voltage_dependency_table.entries);
7388c2ecf20Sopenharmony_ci	kfree(dyn_state->samu_clock_voltage_dependency_table.entries);
7398c2ecf20Sopenharmony_ci	kfree(dyn_state->acp_clock_voltage_dependency_table.entries);
7408c2ecf20Sopenharmony_ci	kfree(dyn_state->vddgfx_dependency_on_sclk.entries);
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cistatic const char *pp_lib_thermal_controller_names[] = {
7448c2ecf20Sopenharmony_ci	"NONE",
7458c2ecf20Sopenharmony_ci	"lm63",
7468c2ecf20Sopenharmony_ci	"adm1032",
7478c2ecf20Sopenharmony_ci	"adm1030",
7488c2ecf20Sopenharmony_ci	"max6649",
7498c2ecf20Sopenharmony_ci	"lm64",
7508c2ecf20Sopenharmony_ci	"f75375",
7518c2ecf20Sopenharmony_ci	"RV6xx",
7528c2ecf20Sopenharmony_ci	"RV770",
7538c2ecf20Sopenharmony_ci	"adt7473",
7548c2ecf20Sopenharmony_ci	"NONE",
7558c2ecf20Sopenharmony_ci	"External GPIO",
7568c2ecf20Sopenharmony_ci	"Evergreen",
7578c2ecf20Sopenharmony_ci	"emc2103",
7588c2ecf20Sopenharmony_ci	"Sumo",
7598c2ecf20Sopenharmony_ci	"Northern Islands",
7608c2ecf20Sopenharmony_ci	"Southern Islands",
7618c2ecf20Sopenharmony_ci	"lm96163",
7628c2ecf20Sopenharmony_ci	"Sea Islands",
7638c2ecf20Sopenharmony_ci	"Kaveri/Kabini",
7648c2ecf20Sopenharmony_ci};
7658c2ecf20Sopenharmony_ci
7668c2ecf20Sopenharmony_civoid amdgpu_add_thermal_controller(struct amdgpu_device *adev)
7678c2ecf20Sopenharmony_ci{
7688c2ecf20Sopenharmony_ci	struct amdgpu_mode_info *mode_info = &adev->mode_info;
7698c2ecf20Sopenharmony_ci	ATOM_PPLIB_POWERPLAYTABLE *power_table;
7708c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
7718c2ecf20Sopenharmony_ci	ATOM_PPLIB_THERMALCONTROLLER *controller;
7728c2ecf20Sopenharmony_ci	struct amdgpu_i2c_bus_rec i2c_bus;
7738c2ecf20Sopenharmony_ci	u16 data_offset;
7748c2ecf20Sopenharmony_ci	u8 frev, crev;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL,
7778c2ecf20Sopenharmony_ci				   &frev, &crev, &data_offset))
7788c2ecf20Sopenharmony_ci		return;
7798c2ecf20Sopenharmony_ci	power_table = (ATOM_PPLIB_POWERPLAYTABLE *)
7808c2ecf20Sopenharmony_ci		(mode_info->atom_context->bios + data_offset);
7818c2ecf20Sopenharmony_ci	controller = &power_table->sThermalController;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	/* add the i2c bus for thermal/fan chip */
7848c2ecf20Sopenharmony_ci	if (controller->ucType > 0) {
7858c2ecf20Sopenharmony_ci		if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN)
7868c2ecf20Sopenharmony_ci			adev->pm.no_fan = true;
7878c2ecf20Sopenharmony_ci		adev->pm.fan_pulses_per_revolution =
7888c2ecf20Sopenharmony_ci			controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
7898c2ecf20Sopenharmony_ci		if (adev->pm.fan_pulses_per_revolution) {
7908c2ecf20Sopenharmony_ci			adev->pm.fan_min_rpm = controller->ucFanMinRPM;
7918c2ecf20Sopenharmony_ci			adev->pm.fan_max_rpm = controller->ucFanMaxRPM;
7928c2ecf20Sopenharmony_ci		}
7938c2ecf20Sopenharmony_ci		if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) {
7948c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
7958c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
7968c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
7978c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX;
7988c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) {
7998c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
8008c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8018c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8028c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_RV770;
8038c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) {
8048c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
8058c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8068c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8078c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN;
8088c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) {
8098c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
8108c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8118c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8128c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_SUMO;
8138c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) {
8148c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
8158c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8168c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8178c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_NI;
8188c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) {
8198c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
8208c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8218c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8228c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_SI;
8238c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) {
8248c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
8258c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8268c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8278c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_CI;
8288c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) {
8298c2ecf20Sopenharmony_ci			DRM_INFO("Internal thermal controller %s fan control\n",
8308c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8318c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8328c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_KV;
8338c2ecf20Sopenharmony_ci		} else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
8348c2ecf20Sopenharmony_ci			DRM_INFO("External GPIO thermal controller %s fan control\n",
8358c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8368c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8378c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
8388c2ecf20Sopenharmony_ci		} else if (controller->ucType ==
8398c2ecf20Sopenharmony_ci			   ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
8408c2ecf20Sopenharmony_ci			DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
8418c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8428c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8438c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
8448c2ecf20Sopenharmony_ci		} else if (controller->ucType ==
8458c2ecf20Sopenharmony_ci			   ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
8468c2ecf20Sopenharmony_ci			DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
8478c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8488c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8498c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
8508c2ecf20Sopenharmony_ci		} else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
8518c2ecf20Sopenharmony_ci			DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
8528c2ecf20Sopenharmony_ci				 pp_lib_thermal_controller_names[controller->ucType],
8538c2ecf20Sopenharmony_ci				 controller->ucI2cAddress >> 1,
8548c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8558c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8568c2ecf20Sopenharmony_ci			adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
8578c2ecf20Sopenharmony_ci			i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine);
8588c2ecf20Sopenharmony_ci			adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus);
8598c2ecf20Sopenharmony_ci			if (adev->pm.i2c_bus) {
8608c2ecf20Sopenharmony_ci				struct i2c_board_info info = { };
8618c2ecf20Sopenharmony_ci				const char *name = pp_lib_thermal_controller_names[controller->ucType];
8628c2ecf20Sopenharmony_ci				info.addr = controller->ucI2cAddress >> 1;
8638c2ecf20Sopenharmony_ci				strlcpy(info.type, name, sizeof(info.type));
8648c2ecf20Sopenharmony_ci				i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info);
8658c2ecf20Sopenharmony_ci			}
8668c2ecf20Sopenharmony_ci		} else {
8678c2ecf20Sopenharmony_ci			DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n",
8688c2ecf20Sopenharmony_ci				 controller->ucType,
8698c2ecf20Sopenharmony_ci				 controller->ucI2cAddress >> 1,
8708c2ecf20Sopenharmony_ci				 (controller->ucFanParameters &
8718c2ecf20Sopenharmony_ci				  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
8728c2ecf20Sopenharmony_ci		}
8738c2ecf20Sopenharmony_ci	}
8748c2ecf20Sopenharmony_ci}
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_cienum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev,
8778c2ecf20Sopenharmony_ci						 u32 sys_mask,
8788c2ecf20Sopenharmony_ci						 enum amdgpu_pcie_gen asic_gen,
8798c2ecf20Sopenharmony_ci						 enum amdgpu_pcie_gen default_gen)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	switch (asic_gen) {
8828c2ecf20Sopenharmony_ci	case AMDGPU_PCIE_GEN1:
8838c2ecf20Sopenharmony_ci		return AMDGPU_PCIE_GEN1;
8848c2ecf20Sopenharmony_ci	case AMDGPU_PCIE_GEN2:
8858c2ecf20Sopenharmony_ci		return AMDGPU_PCIE_GEN2;
8868c2ecf20Sopenharmony_ci	case AMDGPU_PCIE_GEN3:
8878c2ecf20Sopenharmony_ci		return AMDGPU_PCIE_GEN3;
8888c2ecf20Sopenharmony_ci	default:
8898c2ecf20Sopenharmony_ci		if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) &&
8908c2ecf20Sopenharmony_ci		    (default_gen == AMDGPU_PCIE_GEN3))
8918c2ecf20Sopenharmony_ci			return AMDGPU_PCIE_GEN3;
8928c2ecf20Sopenharmony_ci		else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) &&
8938c2ecf20Sopenharmony_ci			 (default_gen == AMDGPU_PCIE_GEN2))
8948c2ecf20Sopenharmony_ci			return AMDGPU_PCIE_GEN2;
8958c2ecf20Sopenharmony_ci		else
8968c2ecf20Sopenharmony_ci			return AMDGPU_PCIE_GEN1;
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci	return AMDGPU_PCIE_GEN1;
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_cistruct amd_vce_state*
9028c2ecf20Sopenharmony_ciamdgpu_get_vce_clock_state(void *handle, u32 idx)
9038c2ecf20Sopenharmony_ci{
9048c2ecf20Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	if (idx < adev->pm.dpm.num_of_vce_states)
9078c2ecf20Sopenharmony_ci		return &adev->pm.dpm.vce_states[idx];
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	return NULL;
9108c2ecf20Sopenharmony_ci}
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ciint amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low)
9138c2ecf20Sopenharmony_ci{
9148c2ecf20Sopenharmony_ci	uint32_t clk_freq;
9158c2ecf20Sopenharmony_ci	int ret = 0;
9168c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
9178c2ecf20Sopenharmony_ci		ret = smu_get_dpm_freq_range(&adev->smu, SMU_GFXCLK,
9188c2ecf20Sopenharmony_ci					     low ? &clk_freq : NULL,
9198c2ecf20Sopenharmony_ci					     !low ? &clk_freq : NULL);
9208c2ecf20Sopenharmony_ci		if (ret)
9218c2ecf20Sopenharmony_ci			return 0;
9228c2ecf20Sopenharmony_ci		return clk_freq * 100;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	} else {
9258c2ecf20Sopenharmony_ci		return (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (low));
9268c2ecf20Sopenharmony_ci	}
9278c2ecf20Sopenharmony_ci}
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ciint amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	uint32_t clk_freq;
9328c2ecf20Sopenharmony_ci	int ret = 0;
9338c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
9348c2ecf20Sopenharmony_ci		ret = smu_get_dpm_freq_range(&adev->smu, SMU_UCLK,
9358c2ecf20Sopenharmony_ci					     low ? &clk_freq : NULL,
9368c2ecf20Sopenharmony_ci					     !low ? &clk_freq : NULL);
9378c2ecf20Sopenharmony_ci		if (ret)
9388c2ecf20Sopenharmony_ci			return 0;
9398c2ecf20Sopenharmony_ci		return clk_freq * 100;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	} else {
9428c2ecf20Sopenharmony_ci		return (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (low));
9438c2ecf20Sopenharmony_ci	}
9448c2ecf20Sopenharmony_ci}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ciint amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate)
9478c2ecf20Sopenharmony_ci{
9488c2ecf20Sopenharmony_ci	int ret = 0;
9498c2ecf20Sopenharmony_ci	bool swsmu = is_support_sw_smu(adev);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci	switch (block_type) {
9528c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_UVD:
9538c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_VCE:
9548c2ecf20Sopenharmony_ci		if (swsmu) {
9558c2ecf20Sopenharmony_ci			ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate);
9568c2ecf20Sopenharmony_ci		} else if (adev->powerplay.pp_funcs &&
9578c2ecf20Sopenharmony_ci			   adev->powerplay.pp_funcs->set_powergating_by_smu) {
9588c2ecf20Sopenharmony_ci			/*
9598c2ecf20Sopenharmony_ci			 * TODO: need a better lock mechanism
9608c2ecf20Sopenharmony_ci			 *
9618c2ecf20Sopenharmony_ci			 * Here adev->pm.mutex lock protection is enforced on
9628c2ecf20Sopenharmony_ci			 * UVD and VCE cases only. Since for other cases, there
9638c2ecf20Sopenharmony_ci			 * may be already lock protection in amdgpu_pm.c.
9648c2ecf20Sopenharmony_ci			 * This is a quick fix for the deadlock issue below.
9658c2ecf20Sopenharmony_ci			 *     NFO: task ocltst:2028 blocked for more than 120 seconds.
9668c2ecf20Sopenharmony_ci			 *     Tainted: G           OE     5.0.0-37-generic #40~18.04.1-Ubuntu
9678c2ecf20Sopenharmony_ci			 *     echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
9688c2ecf20Sopenharmony_ci			 *     cltst          D    0  2028   2026 0x00000000
9698c2ecf20Sopenharmony_ci			 *     all Trace:
9708c2ecf20Sopenharmony_ci			 *     __schedule+0x2c0/0x870
9718c2ecf20Sopenharmony_ci			 *     schedule+0x2c/0x70
9728c2ecf20Sopenharmony_ci			 *     schedule_preempt_disabled+0xe/0x10
9738c2ecf20Sopenharmony_ci			 *     __mutex_lock.isra.9+0x26d/0x4e0
9748c2ecf20Sopenharmony_ci			 *     __mutex_lock_slowpath+0x13/0x20
9758c2ecf20Sopenharmony_ci			 *     ? __mutex_lock_slowpath+0x13/0x20
9768c2ecf20Sopenharmony_ci			 *     mutex_lock+0x2f/0x40
9778c2ecf20Sopenharmony_ci			 *     amdgpu_dpm_set_powergating_by_smu+0x64/0xe0 [amdgpu]
9788c2ecf20Sopenharmony_ci			 *     gfx_v8_0_enable_gfx_static_mg_power_gating+0x3c/0x70 [amdgpu]
9798c2ecf20Sopenharmony_ci			 *     gfx_v8_0_set_powergating_state+0x66/0x260 [amdgpu]
9808c2ecf20Sopenharmony_ci			 *     amdgpu_device_ip_set_powergating_state+0x62/0xb0 [amdgpu]
9818c2ecf20Sopenharmony_ci			 *     pp_dpm_force_performance_level+0xe7/0x100 [amdgpu]
9828c2ecf20Sopenharmony_ci			 *     amdgpu_set_dpm_forced_performance_level+0x129/0x330 [amdgpu]
9838c2ecf20Sopenharmony_ci			 */
9848c2ecf20Sopenharmony_ci			mutex_lock(&adev->pm.mutex);
9858c2ecf20Sopenharmony_ci			ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
9868c2ecf20Sopenharmony_ci				(adev)->powerplay.pp_handle, block_type, gate));
9878c2ecf20Sopenharmony_ci			mutex_unlock(&adev->pm.mutex);
9888c2ecf20Sopenharmony_ci		}
9898c2ecf20Sopenharmony_ci		break;
9908c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_GFX:
9918c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_VCN:
9928c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_SDMA:
9938c2ecf20Sopenharmony_ci		if (swsmu)
9948c2ecf20Sopenharmony_ci			ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate);
9958c2ecf20Sopenharmony_ci		else if (adev->powerplay.pp_funcs &&
9968c2ecf20Sopenharmony_ci			 adev->powerplay.pp_funcs->set_powergating_by_smu)
9978c2ecf20Sopenharmony_ci			ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
9988c2ecf20Sopenharmony_ci				(adev)->powerplay.pp_handle, block_type, gate));
9998c2ecf20Sopenharmony_ci		break;
10008c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_JPEG:
10018c2ecf20Sopenharmony_ci		if (swsmu)
10028c2ecf20Sopenharmony_ci			ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate);
10038c2ecf20Sopenharmony_ci		break;
10048c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_GMC:
10058c2ecf20Sopenharmony_ci	case AMD_IP_BLOCK_TYPE_ACP:
10068c2ecf20Sopenharmony_ci		if (adev->powerplay.pp_funcs &&
10078c2ecf20Sopenharmony_ci		    adev->powerplay.pp_funcs->set_powergating_by_smu)
10088c2ecf20Sopenharmony_ci			ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu(
10098c2ecf20Sopenharmony_ci				(adev)->powerplay.pp_handle, block_type, gate));
10108c2ecf20Sopenharmony_ci		break;
10118c2ecf20Sopenharmony_ci	default:
10128c2ecf20Sopenharmony_ci		break;
10138c2ecf20Sopenharmony_ci	}
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	return ret;
10168c2ecf20Sopenharmony_ci}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ciint amdgpu_dpm_baco_enter(struct amdgpu_device *adev)
10198c2ecf20Sopenharmony_ci{
10208c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10218c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
10228c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
10238c2ecf20Sopenharmony_ci	int ret = 0;
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
10268c2ecf20Sopenharmony_ci		ret = smu_baco_enter(smu);
10278c2ecf20Sopenharmony_ci	} else {
10288c2ecf20Sopenharmony_ci		if (!pp_funcs || !pp_funcs->set_asic_baco_state)
10298c2ecf20Sopenharmony_ci			return -ENOENT;
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci		/* enter BACO state */
10328c2ecf20Sopenharmony_ci		ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
10338c2ecf20Sopenharmony_ci	}
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	return ret;
10368c2ecf20Sopenharmony_ci}
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ciint amdgpu_dpm_baco_exit(struct amdgpu_device *adev)
10398c2ecf20Sopenharmony_ci{
10408c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10418c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
10428c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
10438c2ecf20Sopenharmony_ci	int ret = 0;
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
10468c2ecf20Sopenharmony_ci		ret = smu_baco_exit(smu);
10478c2ecf20Sopenharmony_ci	} else {
10488c2ecf20Sopenharmony_ci		if (!pp_funcs || !pp_funcs->set_asic_baco_state)
10498c2ecf20Sopenharmony_ci			return -ENOENT;
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci		/* exit BACO state */
10528c2ecf20Sopenharmony_ci		ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
10538c2ecf20Sopenharmony_ci	}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	return ret;
10568c2ecf20Sopenharmony_ci}
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ciint amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev,
10598c2ecf20Sopenharmony_ci			     enum pp_mp1_state mp1_state)
10608c2ecf20Sopenharmony_ci{
10618c2ecf20Sopenharmony_ci	int ret = 0;
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
10648c2ecf20Sopenharmony_ci		ret = smu_set_mp1_state(&adev->smu, mp1_state);
10658c2ecf20Sopenharmony_ci	} else if (adev->powerplay.pp_funcs &&
10668c2ecf20Sopenharmony_ci		   adev->powerplay.pp_funcs->set_mp1_state) {
10678c2ecf20Sopenharmony_ci		ret = adev->powerplay.pp_funcs->set_mp1_state(
10688c2ecf20Sopenharmony_ci				adev->powerplay.pp_handle,
10698c2ecf20Sopenharmony_ci				mp1_state);
10708c2ecf20Sopenharmony_ci	}
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	return ret;
10738c2ecf20Sopenharmony_ci}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_cibool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev)
10768c2ecf20Sopenharmony_ci{
10778c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10788c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
10798c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
10808c2ecf20Sopenharmony_ci	bool baco_cap;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
10838c2ecf20Sopenharmony_ci		return smu_baco_is_support(smu);
10848c2ecf20Sopenharmony_ci	} else {
10858c2ecf20Sopenharmony_ci		if (!pp_funcs || !pp_funcs->get_asic_baco_capability)
10868c2ecf20Sopenharmony_ci			return false;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci		if (pp_funcs->get_asic_baco_capability(pp_handle, &baco_cap))
10898c2ecf20Sopenharmony_ci			return false;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci		return baco_cap ? true : false;
10928c2ecf20Sopenharmony_ci	}
10938c2ecf20Sopenharmony_ci}
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ciint amdgpu_dpm_mode2_reset(struct amdgpu_device *adev)
10968c2ecf20Sopenharmony_ci{
10978c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
10988c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
10998c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
11028c2ecf20Sopenharmony_ci		return smu_mode2_reset(smu);
11038c2ecf20Sopenharmony_ci	} else {
11048c2ecf20Sopenharmony_ci		if (!pp_funcs || !pp_funcs->asic_reset_mode_2)
11058c2ecf20Sopenharmony_ci			return -ENOENT;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci		return pp_funcs->asic_reset_mode_2(pp_handle);
11088c2ecf20Sopenharmony_ci	}
11098c2ecf20Sopenharmony_ci}
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ciint amdgpu_dpm_baco_reset(struct amdgpu_device *adev)
11128c2ecf20Sopenharmony_ci{
11138c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
11148c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
11158c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
11168c2ecf20Sopenharmony_ci	int ret = 0;
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
11198c2ecf20Sopenharmony_ci		ret = smu_baco_enter(smu);
11208c2ecf20Sopenharmony_ci		if (ret)
11218c2ecf20Sopenharmony_ci			return ret;
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci		ret = smu_baco_exit(smu);
11248c2ecf20Sopenharmony_ci		if (ret)
11258c2ecf20Sopenharmony_ci			return ret;
11268c2ecf20Sopenharmony_ci	} else {
11278c2ecf20Sopenharmony_ci		if (!pp_funcs
11288c2ecf20Sopenharmony_ci		    || !pp_funcs->set_asic_baco_state)
11298c2ecf20Sopenharmony_ci			return -ENOENT;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci		/* enter BACO state */
11328c2ecf20Sopenharmony_ci		ret = pp_funcs->set_asic_baco_state(pp_handle, 1);
11338c2ecf20Sopenharmony_ci		if (ret)
11348c2ecf20Sopenharmony_ci			return ret;
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci		/* exit BACO state */
11378c2ecf20Sopenharmony_ci		ret = pp_funcs->set_asic_baco_state(pp_handle, 0);
11388c2ecf20Sopenharmony_ci		if (ret)
11398c2ecf20Sopenharmony_ci			return ret;
11408c2ecf20Sopenharmony_ci	}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci	return 0;
11438c2ecf20Sopenharmony_ci}
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_cibool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev)
11468c2ecf20Sopenharmony_ci{
11478c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
11508c2ecf20Sopenharmony_ci		return smu_mode1_reset_is_support(smu);
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ci	return false;
11538c2ecf20Sopenharmony_ci}
11548c2ecf20Sopenharmony_ci
11558c2ecf20Sopenharmony_ciint amdgpu_dpm_mode1_reset(struct amdgpu_device *adev)
11568c2ecf20Sopenharmony_ci{
11578c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
11608c2ecf20Sopenharmony_ci		return smu_mode1_reset(smu);
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	return -EOPNOTSUPP;
11638c2ecf20Sopenharmony_ci}
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ciint amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
11668c2ecf20Sopenharmony_ci				    enum PP_SMC_POWER_PROFILE type,
11678c2ecf20Sopenharmony_ci				    bool en)
11688c2ecf20Sopenharmony_ci{
11698c2ecf20Sopenharmony_ci	int ret = 0;
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
11728c2ecf20Sopenharmony_ci		ret = smu_switch_power_profile(&adev->smu, type, en);
11738c2ecf20Sopenharmony_ci	else if (adev->powerplay.pp_funcs &&
11748c2ecf20Sopenharmony_ci		 adev->powerplay.pp_funcs->switch_power_profile)
11758c2ecf20Sopenharmony_ci		ret = adev->powerplay.pp_funcs->switch_power_profile(
11768c2ecf20Sopenharmony_ci			adev->powerplay.pp_handle, type, en);
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	return ret;
11798c2ecf20Sopenharmony_ci}
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ciint amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev,
11828c2ecf20Sopenharmony_ci			       uint32_t pstate)
11838c2ecf20Sopenharmony_ci{
11848c2ecf20Sopenharmony_ci	int ret = 0;
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
11878c2ecf20Sopenharmony_ci		ret = smu_set_xgmi_pstate(&adev->smu, pstate);
11888c2ecf20Sopenharmony_ci	else if (adev->powerplay.pp_funcs &&
11898c2ecf20Sopenharmony_ci		 adev->powerplay.pp_funcs->set_xgmi_pstate)
11908c2ecf20Sopenharmony_ci		ret = adev->powerplay.pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle,
11918c2ecf20Sopenharmony_ci								pstate);
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci	return ret;
11948c2ecf20Sopenharmony_ci}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ciint amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev,
11978c2ecf20Sopenharmony_ci			     uint32_t cstate)
11988c2ecf20Sopenharmony_ci{
11998c2ecf20Sopenharmony_ci	int ret = 0;
12008c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
12018c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
12028c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
12058c2ecf20Sopenharmony_ci		ret = smu_set_df_cstate(smu, cstate);
12068c2ecf20Sopenharmony_ci	else if (pp_funcs &&
12078c2ecf20Sopenharmony_ci		 pp_funcs->set_df_cstate)
12088c2ecf20Sopenharmony_ci		ret = pp_funcs->set_df_cstate(pp_handle, cstate);
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	return ret;
12118c2ecf20Sopenharmony_ci}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ciint amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en)
12148c2ecf20Sopenharmony_ci{
12158c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
12188c2ecf20Sopenharmony_ci		return smu_allow_xgmi_power_down(smu, en);
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	return 0;
12218c2ecf20Sopenharmony_ci}
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_ciint amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev)
12248c2ecf20Sopenharmony_ci{
12258c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
12268c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs =
12278c2ecf20Sopenharmony_ci			adev->powerplay.pp_funcs;
12288c2ecf20Sopenharmony_ci	struct smu_context *smu = &adev->smu;
12298c2ecf20Sopenharmony_ci	int ret = 0;
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
12328c2ecf20Sopenharmony_ci		ret = smu_enable_mgpu_fan_boost(smu);
12338c2ecf20Sopenharmony_ci	else if (pp_funcs && pp_funcs->enable_mgpu_fan_boost)
12348c2ecf20Sopenharmony_ci		ret = pp_funcs->enable_mgpu_fan_boost(pp_handle);
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	return ret;
12378c2ecf20Sopenharmony_ci}
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ciint amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev,
12408c2ecf20Sopenharmony_ci				      uint32_t msg_id)
12418c2ecf20Sopenharmony_ci{
12428c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
12438c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs =
12448c2ecf20Sopenharmony_ci			adev->powerplay.pp_funcs;
12458c2ecf20Sopenharmony_ci	int ret = 0;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	if (pp_funcs && pp_funcs->set_clockgating_by_smu)
12488c2ecf20Sopenharmony_ci		ret = pp_funcs->set_clockgating_by_smu(pp_handle,
12498c2ecf20Sopenharmony_ci						       msg_id);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	return ret;
12528c2ecf20Sopenharmony_ci}
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ciint amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev,
12558c2ecf20Sopenharmony_ci				  bool acquire)
12568c2ecf20Sopenharmony_ci{
12578c2ecf20Sopenharmony_ci	void *pp_handle = adev->powerplay.pp_handle;
12588c2ecf20Sopenharmony_ci	const struct amd_pm_funcs *pp_funcs =
12598c2ecf20Sopenharmony_ci			adev->powerplay.pp_funcs;
12608c2ecf20Sopenharmony_ci	int ret = -EOPNOTSUPP;
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	if (pp_funcs && pp_funcs->smu_i2c_bus_access)
12638c2ecf20Sopenharmony_ci		ret = pp_funcs->smu_i2c_bus_access(pp_handle,
12648c2ecf20Sopenharmony_ci						   acquire);
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	return ret;
12678c2ecf20Sopenharmony_ci}
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_civoid amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev)
12708c2ecf20Sopenharmony_ci{
12718c2ecf20Sopenharmony_ci	if (adev->pm.dpm_enabled) {
12728c2ecf20Sopenharmony_ci		mutex_lock(&adev->pm.mutex);
12738c2ecf20Sopenharmony_ci		if (power_supply_is_system_supplied() > 0)
12748c2ecf20Sopenharmony_ci			adev->pm.ac_power = true;
12758c2ecf20Sopenharmony_ci		else
12768c2ecf20Sopenharmony_ci			adev->pm.ac_power = false;
12778c2ecf20Sopenharmony_ci		if (adev->powerplay.pp_funcs &&
12788c2ecf20Sopenharmony_ci		    adev->powerplay.pp_funcs->enable_bapm)
12798c2ecf20Sopenharmony_ci			amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power);
12808c2ecf20Sopenharmony_ci		mutex_unlock(&adev->pm.mutex);
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci		if (is_support_sw_smu(adev))
12838c2ecf20Sopenharmony_ci			smu_set_ac_dc(&adev->smu);
12848c2ecf20Sopenharmony_ci	}
12858c2ecf20Sopenharmony_ci}
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ciint amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor,
12888c2ecf20Sopenharmony_ci			   void *data, uint32_t *size)
12898c2ecf20Sopenharmony_ci{
12908c2ecf20Sopenharmony_ci	int ret = 0;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	if (!data || !size)
12938c2ecf20Sopenharmony_ci		return -EINVAL;
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev))
12968c2ecf20Sopenharmony_ci		ret = smu_read_sensor(&adev->smu, sensor, data, size);
12978c2ecf20Sopenharmony_ci	else {
12988c2ecf20Sopenharmony_ci		if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor)
12998c2ecf20Sopenharmony_ci			ret = adev->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle,
13008c2ecf20Sopenharmony_ci								    sensor, data, size);
13018c2ecf20Sopenharmony_ci		else
13028c2ecf20Sopenharmony_ci			ret = -EINVAL;
13038c2ecf20Sopenharmony_ci	}
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci	return ret;
13068c2ecf20Sopenharmony_ci}
13078c2ecf20Sopenharmony_ci
13088c2ecf20Sopenharmony_civoid amdgpu_dpm_thermal_work_handler(struct work_struct *work)
13098c2ecf20Sopenharmony_ci{
13108c2ecf20Sopenharmony_ci	struct amdgpu_device *adev =
13118c2ecf20Sopenharmony_ci		container_of(work, struct amdgpu_device,
13128c2ecf20Sopenharmony_ci			     pm.dpm.thermal.work);
13138c2ecf20Sopenharmony_ci	/* switch to the thermal state */
13148c2ecf20Sopenharmony_ci	enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL;
13158c2ecf20Sopenharmony_ci	int temp, size = sizeof(temp);
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_ci	if (!adev->pm.dpm_enabled)
13188c2ecf20Sopenharmony_ci		return;
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP,
13218c2ecf20Sopenharmony_ci				    (void *)&temp, &size)) {
13228c2ecf20Sopenharmony_ci		if (temp < adev->pm.dpm.thermal.min_temp)
13238c2ecf20Sopenharmony_ci			/* switch back the user state */
13248c2ecf20Sopenharmony_ci			dpm_state = adev->pm.dpm.user_state;
13258c2ecf20Sopenharmony_ci	} else {
13268c2ecf20Sopenharmony_ci		if (adev->pm.dpm.thermal.high_to_low)
13278c2ecf20Sopenharmony_ci			/* switch back the user state */
13288c2ecf20Sopenharmony_ci			dpm_state = adev->pm.dpm.user_state;
13298c2ecf20Sopenharmony_ci	}
13308c2ecf20Sopenharmony_ci	mutex_lock(&adev->pm.mutex);
13318c2ecf20Sopenharmony_ci	if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL)
13328c2ecf20Sopenharmony_ci		adev->pm.dpm.thermal_active = true;
13338c2ecf20Sopenharmony_ci	else
13348c2ecf20Sopenharmony_ci		adev->pm.dpm.thermal_active = false;
13358c2ecf20Sopenharmony_ci	adev->pm.dpm.state = dpm_state;
13368c2ecf20Sopenharmony_ci	mutex_unlock(&adev->pm.mutex);
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	amdgpu_pm_compute_clocks(adev);
13398c2ecf20Sopenharmony_ci}
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_cistatic struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev,
13428c2ecf20Sopenharmony_ci						     enum amd_pm_state_type dpm_state)
13438c2ecf20Sopenharmony_ci{
13448c2ecf20Sopenharmony_ci	int i;
13458c2ecf20Sopenharmony_ci	struct amdgpu_ps *ps;
13468c2ecf20Sopenharmony_ci	u32 ui_class;
13478c2ecf20Sopenharmony_ci	bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ?
13488c2ecf20Sopenharmony_ci		true : false;
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	/* check if the vblank period is too short to adjust the mclk */
13518c2ecf20Sopenharmony_ci	if (single_display && adev->powerplay.pp_funcs->vblank_too_short) {
13528c2ecf20Sopenharmony_ci		if (amdgpu_dpm_vblank_too_short(adev))
13538c2ecf20Sopenharmony_ci			single_display = false;
13548c2ecf20Sopenharmony_ci	}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	/* certain older asics have a separare 3D performance state,
13578c2ecf20Sopenharmony_ci	 * so try that first if the user selected performance
13588c2ecf20Sopenharmony_ci	 */
13598c2ecf20Sopenharmony_ci	if (dpm_state == POWER_STATE_TYPE_PERFORMANCE)
13608c2ecf20Sopenharmony_ci		dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF;
13618c2ecf20Sopenharmony_ci	/* balanced states don't exist at the moment */
13628c2ecf20Sopenharmony_ci	if (dpm_state == POWER_STATE_TYPE_BALANCED)
13638c2ecf20Sopenharmony_ci		dpm_state = POWER_STATE_TYPE_PERFORMANCE;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_cirestart_search:
13668c2ecf20Sopenharmony_ci	/* Pick the best power state based on current conditions */
13678c2ecf20Sopenharmony_ci	for (i = 0; i < adev->pm.dpm.num_ps; i++) {
13688c2ecf20Sopenharmony_ci		ps = &adev->pm.dpm.ps[i];
13698c2ecf20Sopenharmony_ci		ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK;
13708c2ecf20Sopenharmony_ci		switch (dpm_state) {
13718c2ecf20Sopenharmony_ci		/* user states */
13728c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_BATTERY:
13738c2ecf20Sopenharmony_ci			if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) {
13748c2ecf20Sopenharmony_ci				if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
13758c2ecf20Sopenharmony_ci					if (single_display)
13768c2ecf20Sopenharmony_ci						return ps;
13778c2ecf20Sopenharmony_ci				} else
13788c2ecf20Sopenharmony_ci					return ps;
13798c2ecf20Sopenharmony_ci			}
13808c2ecf20Sopenharmony_ci			break;
13818c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_BALANCED:
13828c2ecf20Sopenharmony_ci			if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) {
13838c2ecf20Sopenharmony_ci				if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
13848c2ecf20Sopenharmony_ci					if (single_display)
13858c2ecf20Sopenharmony_ci						return ps;
13868c2ecf20Sopenharmony_ci				} else
13878c2ecf20Sopenharmony_ci					return ps;
13888c2ecf20Sopenharmony_ci			}
13898c2ecf20Sopenharmony_ci			break;
13908c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_PERFORMANCE:
13918c2ecf20Sopenharmony_ci			if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
13928c2ecf20Sopenharmony_ci				if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) {
13938c2ecf20Sopenharmony_ci					if (single_display)
13948c2ecf20Sopenharmony_ci						return ps;
13958c2ecf20Sopenharmony_ci				} else
13968c2ecf20Sopenharmony_ci					return ps;
13978c2ecf20Sopenharmony_ci			}
13988c2ecf20Sopenharmony_ci			break;
13998c2ecf20Sopenharmony_ci		/* internal states */
14008c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_UVD:
14018c2ecf20Sopenharmony_ci			if (adev->pm.dpm.uvd_ps)
14028c2ecf20Sopenharmony_ci				return adev->pm.dpm.uvd_ps;
14038c2ecf20Sopenharmony_ci			else
14048c2ecf20Sopenharmony_ci				break;
14058c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_UVD_SD:
14068c2ecf20Sopenharmony_ci			if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE)
14078c2ecf20Sopenharmony_ci				return ps;
14088c2ecf20Sopenharmony_ci			break;
14098c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_UVD_HD:
14108c2ecf20Sopenharmony_ci			if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE)
14118c2ecf20Sopenharmony_ci				return ps;
14128c2ecf20Sopenharmony_ci			break;
14138c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
14148c2ecf20Sopenharmony_ci			if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE)
14158c2ecf20Sopenharmony_ci				return ps;
14168c2ecf20Sopenharmony_ci			break;
14178c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
14188c2ecf20Sopenharmony_ci			if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC)
14198c2ecf20Sopenharmony_ci				return ps;
14208c2ecf20Sopenharmony_ci			break;
14218c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_BOOT:
14228c2ecf20Sopenharmony_ci			return adev->pm.dpm.boot_ps;
14238c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_THERMAL:
14248c2ecf20Sopenharmony_ci			if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
14258c2ecf20Sopenharmony_ci				return ps;
14268c2ecf20Sopenharmony_ci			break;
14278c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_ACPI:
14288c2ecf20Sopenharmony_ci			if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI)
14298c2ecf20Sopenharmony_ci				return ps;
14308c2ecf20Sopenharmony_ci			break;
14318c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_ULV:
14328c2ecf20Sopenharmony_ci			if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV)
14338c2ecf20Sopenharmony_ci				return ps;
14348c2ecf20Sopenharmony_ci			break;
14358c2ecf20Sopenharmony_ci		case POWER_STATE_TYPE_INTERNAL_3DPERF:
14368c2ecf20Sopenharmony_ci			if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)
14378c2ecf20Sopenharmony_ci				return ps;
14388c2ecf20Sopenharmony_ci			break;
14398c2ecf20Sopenharmony_ci		default:
14408c2ecf20Sopenharmony_ci			break;
14418c2ecf20Sopenharmony_ci		}
14428c2ecf20Sopenharmony_ci	}
14438c2ecf20Sopenharmony_ci	/* use a fallback state if we didn't match */
14448c2ecf20Sopenharmony_ci	switch (dpm_state) {
14458c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_INTERNAL_UVD_SD:
14468c2ecf20Sopenharmony_ci		dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD;
14478c2ecf20Sopenharmony_ci		goto restart_search;
14488c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_INTERNAL_UVD_HD:
14498c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_INTERNAL_UVD_HD2:
14508c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_INTERNAL_UVD_MVC:
14518c2ecf20Sopenharmony_ci		if (adev->pm.dpm.uvd_ps) {
14528c2ecf20Sopenharmony_ci			return adev->pm.dpm.uvd_ps;
14538c2ecf20Sopenharmony_ci		} else {
14548c2ecf20Sopenharmony_ci			dpm_state = POWER_STATE_TYPE_PERFORMANCE;
14558c2ecf20Sopenharmony_ci			goto restart_search;
14568c2ecf20Sopenharmony_ci		}
14578c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_INTERNAL_THERMAL:
14588c2ecf20Sopenharmony_ci		dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI;
14598c2ecf20Sopenharmony_ci		goto restart_search;
14608c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_INTERNAL_ACPI:
14618c2ecf20Sopenharmony_ci		dpm_state = POWER_STATE_TYPE_BATTERY;
14628c2ecf20Sopenharmony_ci		goto restart_search;
14638c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_BATTERY:
14648c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_BALANCED:
14658c2ecf20Sopenharmony_ci	case POWER_STATE_TYPE_INTERNAL_3DPERF:
14668c2ecf20Sopenharmony_ci		dpm_state = POWER_STATE_TYPE_PERFORMANCE;
14678c2ecf20Sopenharmony_ci		goto restart_search;
14688c2ecf20Sopenharmony_ci	default:
14698c2ecf20Sopenharmony_ci		break;
14708c2ecf20Sopenharmony_ci	}
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	return NULL;
14738c2ecf20Sopenharmony_ci}
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_cistatic void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
14768c2ecf20Sopenharmony_ci{
14778c2ecf20Sopenharmony_ci	struct amdgpu_ps *ps;
14788c2ecf20Sopenharmony_ci	enum amd_pm_state_type dpm_state;
14798c2ecf20Sopenharmony_ci	int ret;
14808c2ecf20Sopenharmony_ci	bool equal = false;
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci	/* if dpm init failed */
14838c2ecf20Sopenharmony_ci	if (!adev->pm.dpm_enabled)
14848c2ecf20Sopenharmony_ci		return;
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci	if (adev->pm.dpm.user_state != adev->pm.dpm.state) {
14878c2ecf20Sopenharmony_ci		/* add other state override checks here */
14888c2ecf20Sopenharmony_ci		if ((!adev->pm.dpm.thermal_active) &&
14898c2ecf20Sopenharmony_ci		    (!adev->pm.dpm.uvd_active))
14908c2ecf20Sopenharmony_ci			adev->pm.dpm.state = adev->pm.dpm.user_state;
14918c2ecf20Sopenharmony_ci	}
14928c2ecf20Sopenharmony_ci	dpm_state = adev->pm.dpm.state;
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	ps = amdgpu_dpm_pick_power_state(adev, dpm_state);
14958c2ecf20Sopenharmony_ci	if (ps)
14968c2ecf20Sopenharmony_ci		adev->pm.dpm.requested_ps = ps;
14978c2ecf20Sopenharmony_ci	else
14988c2ecf20Sopenharmony_ci		return;
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) {
15018c2ecf20Sopenharmony_ci		printk("switching from power state:\n");
15028c2ecf20Sopenharmony_ci		amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps);
15038c2ecf20Sopenharmony_ci		printk("switching to power state:\n");
15048c2ecf20Sopenharmony_ci		amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps);
15058c2ecf20Sopenharmony_ci	}
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci	/* update whether vce is active */
15088c2ecf20Sopenharmony_ci	ps->vce_active = adev->pm.dpm.vce_active;
15098c2ecf20Sopenharmony_ci	if (adev->powerplay.pp_funcs->display_configuration_changed)
15108c2ecf20Sopenharmony_ci		amdgpu_dpm_display_configuration_changed(adev);
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	ret = amdgpu_dpm_pre_set_power_state(adev);
15138c2ecf20Sopenharmony_ci	if (ret)
15148c2ecf20Sopenharmony_ci		return;
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	if (adev->powerplay.pp_funcs->check_state_equal) {
15178c2ecf20Sopenharmony_ci		if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal))
15188c2ecf20Sopenharmony_ci			equal = false;
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	if (equal)
15228c2ecf20Sopenharmony_ci		return;
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	amdgpu_dpm_set_power_state(adev);
15258c2ecf20Sopenharmony_ci	amdgpu_dpm_post_set_power_state(adev);
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
15288c2ecf20Sopenharmony_ci	adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci	if (adev->powerplay.pp_funcs->force_performance_level) {
15318c2ecf20Sopenharmony_ci		if (adev->pm.dpm.thermal_active) {
15328c2ecf20Sopenharmony_ci			enum amd_dpm_forced_level level = adev->pm.dpm.forced_level;
15338c2ecf20Sopenharmony_ci			/* force low perf level for thermal */
15348c2ecf20Sopenharmony_ci			amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW);
15358c2ecf20Sopenharmony_ci			/* save the user's level */
15368c2ecf20Sopenharmony_ci			adev->pm.dpm.forced_level = level;
15378c2ecf20Sopenharmony_ci		} else {
15388c2ecf20Sopenharmony_ci			/* otherwise, user selected level */
15398c2ecf20Sopenharmony_ci			amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level);
15408c2ecf20Sopenharmony_ci		}
15418c2ecf20Sopenharmony_ci	}
15428c2ecf20Sopenharmony_ci}
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_civoid amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
15458c2ecf20Sopenharmony_ci{
15468c2ecf20Sopenharmony_ci	int i = 0;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	if (!adev->pm.dpm_enabled)
15498c2ecf20Sopenharmony_ci		return;
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	if (adev->mode_info.num_crtc)
15528c2ecf20Sopenharmony_ci		amdgpu_display_bandwidth_update(adev);
15538c2ecf20Sopenharmony_ci
15548c2ecf20Sopenharmony_ci	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
15558c2ecf20Sopenharmony_ci		struct amdgpu_ring *ring = adev->rings[i];
15568c2ecf20Sopenharmony_ci		if (ring && ring->sched.ready)
15578c2ecf20Sopenharmony_ci			amdgpu_fence_wait_empty(ring);
15588c2ecf20Sopenharmony_ci	}
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	if (is_support_sw_smu(adev)) {
15618c2ecf20Sopenharmony_ci		struct smu_dpm_context *smu_dpm = &adev->smu.smu_dpm;
15628c2ecf20Sopenharmony_ci		smu_handle_task(&adev->smu,
15638c2ecf20Sopenharmony_ci				smu_dpm->dpm_level,
15648c2ecf20Sopenharmony_ci				AMD_PP_TASK_DISPLAY_CONFIG_CHANGE,
15658c2ecf20Sopenharmony_ci				true);
15668c2ecf20Sopenharmony_ci	} else {
15678c2ecf20Sopenharmony_ci		if (adev->powerplay.pp_funcs->dispatch_tasks) {
15688c2ecf20Sopenharmony_ci			if (!amdgpu_device_has_dc_support(adev)) {
15698c2ecf20Sopenharmony_ci				mutex_lock(&adev->pm.mutex);
15708c2ecf20Sopenharmony_ci				amdgpu_dpm_get_active_displays(adev);
15718c2ecf20Sopenharmony_ci				adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count;
15728c2ecf20Sopenharmony_ci				adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev);
15738c2ecf20Sopenharmony_ci				adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev);
15748c2ecf20Sopenharmony_ci				/* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */
15758c2ecf20Sopenharmony_ci				if (adev->pm.pm_display_cfg.vrefresh > 120)
15768c2ecf20Sopenharmony_ci					adev->pm.pm_display_cfg.min_vblank_time = 0;
15778c2ecf20Sopenharmony_ci				if (adev->powerplay.pp_funcs->display_configuration_change)
15788c2ecf20Sopenharmony_ci					adev->powerplay.pp_funcs->display_configuration_change(
15798c2ecf20Sopenharmony_ci									adev->powerplay.pp_handle,
15808c2ecf20Sopenharmony_ci									&adev->pm.pm_display_cfg);
15818c2ecf20Sopenharmony_ci				mutex_unlock(&adev->pm.mutex);
15828c2ecf20Sopenharmony_ci			}
15838c2ecf20Sopenharmony_ci			amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL);
15848c2ecf20Sopenharmony_ci		} else {
15858c2ecf20Sopenharmony_ci			mutex_lock(&adev->pm.mutex);
15868c2ecf20Sopenharmony_ci			amdgpu_dpm_get_active_displays(adev);
15878c2ecf20Sopenharmony_ci			amdgpu_dpm_change_power_state_locked(adev);
15888c2ecf20Sopenharmony_ci			mutex_unlock(&adev->pm.mutex);
15898c2ecf20Sopenharmony_ci		}
15908c2ecf20Sopenharmony_ci	}
15918c2ecf20Sopenharmony_ci}
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_civoid amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable)
15948c2ecf20Sopenharmony_ci{
15958c2ecf20Sopenharmony_ci	int ret = 0;
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	if (adev->family == AMDGPU_FAMILY_SI) {
15988c2ecf20Sopenharmony_ci		mutex_lock(&adev->pm.mutex);
15998c2ecf20Sopenharmony_ci		if (enable) {
16008c2ecf20Sopenharmony_ci			adev->pm.dpm.uvd_active = true;
16018c2ecf20Sopenharmony_ci			adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD;
16028c2ecf20Sopenharmony_ci		} else {
16038c2ecf20Sopenharmony_ci			adev->pm.dpm.uvd_active = false;
16048c2ecf20Sopenharmony_ci		}
16058c2ecf20Sopenharmony_ci		mutex_unlock(&adev->pm.mutex);
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci		amdgpu_pm_compute_clocks(adev);
16088c2ecf20Sopenharmony_ci	} else {
16098c2ecf20Sopenharmony_ci		ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable);
16108c2ecf20Sopenharmony_ci		if (ret)
16118c2ecf20Sopenharmony_ci			DRM_ERROR("Dpm %s uvd failed, ret = %d. \n",
16128c2ecf20Sopenharmony_ci				  enable ? "enable" : "disable", ret);
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci		/* enable/disable Low Memory PState for UVD (4k videos) */
16158c2ecf20Sopenharmony_ci		if (adev->asic_type == CHIP_STONEY &&
16168c2ecf20Sopenharmony_ci			adev->uvd.decode_image_width >= WIDTH_4K) {
16178c2ecf20Sopenharmony_ci			struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
16188c2ecf20Sopenharmony_ci
16198c2ecf20Sopenharmony_ci			if (hwmgr && hwmgr->hwmgr_func &&
16208c2ecf20Sopenharmony_ci			    hwmgr->hwmgr_func->update_nbdpm_pstate)
16218c2ecf20Sopenharmony_ci				hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr,
16228c2ecf20Sopenharmony_ci								       !enable,
16238c2ecf20Sopenharmony_ci								       true);
16248c2ecf20Sopenharmony_ci		}
16258c2ecf20Sopenharmony_ci	}
16268c2ecf20Sopenharmony_ci}
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_civoid amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
16298c2ecf20Sopenharmony_ci{
16308c2ecf20Sopenharmony_ci	int ret = 0;
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci	if (adev->family == AMDGPU_FAMILY_SI) {
16338c2ecf20Sopenharmony_ci		mutex_lock(&adev->pm.mutex);
16348c2ecf20Sopenharmony_ci		if (enable) {
16358c2ecf20Sopenharmony_ci			adev->pm.dpm.vce_active = true;
16368c2ecf20Sopenharmony_ci			/* XXX select vce level based on ring/task */
16378c2ecf20Sopenharmony_ci			adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
16388c2ecf20Sopenharmony_ci		} else {
16398c2ecf20Sopenharmony_ci			adev->pm.dpm.vce_active = false;
16408c2ecf20Sopenharmony_ci		}
16418c2ecf20Sopenharmony_ci		mutex_unlock(&adev->pm.mutex);
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci		amdgpu_pm_compute_clocks(adev);
16448c2ecf20Sopenharmony_ci	} else {
16458c2ecf20Sopenharmony_ci		ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable);
16468c2ecf20Sopenharmony_ci		if (ret)
16478c2ecf20Sopenharmony_ci			DRM_ERROR("Dpm %s vce failed, ret = %d. \n",
16488c2ecf20Sopenharmony_ci				  enable ? "enable" : "disable", ret);
16498c2ecf20Sopenharmony_ci	}
16508c2ecf20Sopenharmony_ci}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_civoid amdgpu_pm_print_power_states(struct amdgpu_device *adev)
16538c2ecf20Sopenharmony_ci{
16548c2ecf20Sopenharmony_ci	int i;
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	if (adev->powerplay.pp_funcs->print_power_state == NULL)
16578c2ecf20Sopenharmony_ci		return;
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	for (i = 0; i < adev->pm.dpm.num_ps; i++)
16608c2ecf20Sopenharmony_ci		amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]);
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci}
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_civoid amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable)
16658c2ecf20Sopenharmony_ci{
16668c2ecf20Sopenharmony_ci	int ret = 0;
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci	ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable);
16698c2ecf20Sopenharmony_ci	if (ret)
16708c2ecf20Sopenharmony_ci		DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n",
16718c2ecf20Sopenharmony_ci			  enable ? "enable" : "disable", ret);
16728c2ecf20Sopenharmony_ci}
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ciint amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version)
16758c2ecf20Sopenharmony_ci{
16768c2ecf20Sopenharmony_ci	int r;
16778c2ecf20Sopenharmony_ci
16788c2ecf20Sopenharmony_ci	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) {
16798c2ecf20Sopenharmony_ci		r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle);
16808c2ecf20Sopenharmony_ci		if (r) {
16818c2ecf20Sopenharmony_ci			pr_err("smu firmware loading failed\n");
16828c2ecf20Sopenharmony_ci			return r;
16838c2ecf20Sopenharmony_ci		}
16848c2ecf20Sopenharmony_ci		*smu_version = adev->pm.fw_version;
16858c2ecf20Sopenharmony_ci	}
16868c2ecf20Sopenharmony_ci	return 0;
16878c2ecf20Sopenharmony_ci}
1688