aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0047-drm-amd-powerplay-add-CG-and-PG-support-for-carrizo.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0047-drm-amd-powerplay-add-CG-and-PG-support-for-carrizo.patch')
-rw-r--r--common/recipes-kernel/linux/files/0047-drm-amd-powerplay-add-CG-and-PG-support-for-carrizo.patch1366
1 files changed, 0 insertions, 1366 deletions
diff --git a/common/recipes-kernel/linux/files/0047-drm-amd-powerplay-add-CG-and-PG-support-for-carrizo.patch b/common/recipes-kernel/linux/files/0047-drm-amd-powerplay-add-CG-and-PG-support-for-carrizo.patch
deleted file mode 100644
index bac07469..00000000
--- a/common/recipes-kernel/linux/files/0047-drm-amd-powerplay-add-CG-and-PG-support-for-carrizo.patch
+++ /dev/null
@@ -1,1366 +0,0 @@
-From 728e3862515c8d99fecf457ca874e04b1892df75 Mon Sep 17 00:00:00 2001
-From: Rex Zhu <Rex.Zhu@amd.com>
-Date: Wed, 23 Sep 2015 15:14:38 +0800
-Subject: [PATCH 0047/1110] drm/amd/powerplay: add CG and PG support for
- carrizo
-
-This adds clock and powergating support for CZ.
-
-v2: squash in fixes
-
-Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
-Reviewed-by: Jammy Zhou <Jammy.Zhou@amd.com>
-Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
----
- drivers/gpu/drm/amd/powerplay/hwmgr/Makefile | 3 +-
- .../drm/amd/powerplay/hwmgr/cz_clockpowergating.c | 252 ++++++++++
- .../drm/amd/powerplay/hwmgr/cz_clockpowergating.h | 37 ++
- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 521 ++++++++++++++++++++-
- drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h | 12 +-
- .../gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c | 89 +++-
- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 10 +
- .../gpu/drm/amd/powerplay/inc/hardwaremanager.h | 53 ++-
- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 46 +-
- drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h | 47 ++
- 10 files changed, 1058 insertions(+), 12 deletions(-)
- create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
- create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h
- create mode 100644 drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h
-
-diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
-index 22d383e..46cc494 100644
---- a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
-+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
-@@ -3,7 +3,8 @@
- # It provides the hardware management services for the driver.
-
- HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \
-- hardwaremanager.o pp_acpi.o cz_hwmgr.o
-+ hardwaremanager.o pp_acpi.o cz_hwmgr.o \
-+ cz_clockpowergating.o
-
- AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
-
-diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
-new file mode 100644
-index 0000000..ad77008
---- /dev/null
-+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
-@@ -0,0 +1,252 @@
-+/*
-+ * Copyright 2015 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ */
-+
-+#include "hwmgr.h"
-+#include "cz_clockpowergating.h"
-+#include "cz_ppsmc.h"
-+
-+/* PhyID -> Status Mapping in DDI_PHY_GEN_STATUS
-+ 0 GFX0L (3:0), (27:24),
-+ 1 GFX0H (7:4), (31:28),
-+ 2 GFX1L (3:0), (19:16),
-+ 3 GFX1H (7:4), (23:20),
-+ 4 DDIL (3:0), (11: 8),
-+ 5 DDIH (7:4), (15:12),
-+ 6 DDI2L (3:0), ( 3: 0),
-+ 7 DDI2H (7:4), ( 7: 4),
-+*/
-+#define DDI_PHY_GEN_STATUS_VAL(phyID) (1 << ((3 - ((phyID & 0x07)/2))*8 + (phyID & 0x01)*4))
-+#define IS_PHY_ID_USED_BY_PLL(PhyID) (((0xF3 & (1 << PhyID)) & 0xFF) ? true : false)
-+
-+
-+int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating)
-+{
-+ int ret = 0;
-+
-+ switch (block) {
-+ case PHM_AsicBlock_UVD_MVC:
-+ case PHM_AsicBlock_UVD:
-+ case PHM_AsicBlock_UVD_HD:
-+ case PHM_AsicBlock_UVD_SD:
-+ if (gating == PHM_ClockGateSetting_StaticOff)
-+ ret = cz_dpm_powerdown_uvd(hwmgr);
-+ else
-+ ret = cz_dpm_powerup_uvd(hwmgr);
-+ break;
-+ case PHM_AsicBlock_GFX:
-+ default:
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+
-+bool cz_phm_is_safe_for_asic_block(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, enum PHM_AsicBlock block)
-+{
-+ return true;
-+}
-+
-+
-+int cz_phm_enable_disable_gfx_power_gating(struct pp_hwmgr *hwmgr, bool enable)
-+{
-+ return 0;
-+}
-+
-+int cz_phm_smu_power_up_down_pcie(struct pp_hwmgr *hwmgr, uint32_t target, bool up, uint32_t args)
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+int cz_phm_initialize_display_phy_access(struct pp_hwmgr *hwmgr, bool initialize, bool accesshw)
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+int cz_phm_get_display_phy_access_info(struct pp_hwmgr *hwmgr)
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+int cz_phm_gate_unused_display_phys(struct pp_hwmgr *hwmgr)
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+int cz_phm_ungate_all_display_phys(struct pp_hwmgr *hwmgr)
-+{
-+ /* TODO */
-+ return 0;
-+}
-+
-+static int cz_tf_uvd_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result)
-+{
-+ return 0;
-+}
-+
-+static int cz_tf_vce_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result)
-+{
-+ return 0;
-+}
-+
-+int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+ uint32_t dpm_features = 0;
-+
-+ if (enable &&
-+ phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_UVDDPM)) {
-+ cz_hwmgr->dpm_flags |= DPMFlags_UVD_Enabled;
-+ dpm_features |= UVD_DPM_MASK;
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_EnableAllSmuFeatures, dpm_features);
-+ } else {
-+ dpm_features |= UVD_DPM_MASK;
-+ cz_hwmgr->dpm_flags &= ~DPMFlags_UVD_Enabled;
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_DisableAllSmuFeatures, dpm_features);
-+ }
-+ return 0;
-+}
-+
-+int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+ uint32_t dpm_features = 0;
-+
-+ if (enable && phm_cap_enabled(
-+ hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_VCEDPM)) {
-+ cz_hwmgr->dpm_flags |= DPMFlags_VCE_Enabled;
-+ dpm_features |= VCE_DPM_MASK;
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_EnableAllSmuFeatures, dpm_features);
-+ } else {
-+ dpm_features |= VCE_DPM_MASK;
-+ cz_hwmgr->dpm_flags &= ~DPMFlags_VCE_Enabled;
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_DisableAllSmuFeatures, dpm_features);
-+ }
-+
-+ return 0;
-+}
-+
-+
-+int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+
-+ if (cz_hwmgr->uvd_power_gated == bgate)
-+ return 0;
-+
-+ cz_hwmgr->uvd_power_gated = bgate;
-+
-+ if (bgate) {
-+ cgs_set_clockgating_state(hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_UVD,
-+ AMD_CG_STATE_UNGATE);
-+ cgs_set_powergating_state(hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_UVD,
-+ AMD_PG_STATE_GATE);
-+ cz_dpm_update_uvd_dpm(hwmgr, true);
-+ cz_dpm_powerdown_uvd(hwmgr);
-+ } else {
-+ cz_dpm_powerup_uvd(hwmgr);
-+ cgs_set_clockgating_state(hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_UVD,
-+ AMD_PG_STATE_GATE);
-+ cgs_set_powergating_state(hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_UVD,
-+ AMD_CG_STATE_UNGATE);
-+ cz_dpm_update_uvd_dpm(hwmgr, false);
-+ }
-+
-+ return 0;
-+}
-+
-+int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_VCEPowerGating)) {
-+ if (cz_hwmgr->vce_power_gated != bgate) {
-+ if (bgate) {
-+ cgs_set_clockgating_state(
-+ hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_VCE,
-+ AMD_CG_STATE_UNGATE);
-+ cgs_set_powergating_state(
-+ hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_VCE,
-+ AMD_PG_STATE_GATE);
-+ cz_enable_disable_vce_dpm(hwmgr, false);
-+ /* TODO: to figure out why vce can't be poweroff*/
-+ cz_hwmgr->vce_power_gated = true;
-+ } else {
-+ cz_dpm_powerup_vce(hwmgr);
-+ cz_hwmgr->vce_power_gated = false;
-+ cgs_set_clockgating_state(
-+ hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_VCE,
-+ AMD_PG_STATE_GATE);
-+ cgs_set_powergating_state(
-+ hwmgr->device,
-+ AMD_IP_BLOCK_TYPE_VCE,
-+ AMD_CG_STATE_UNGATE);
-+ cz_dpm_update_vce_dpm(hwmgr);
-+ cz_enable_disable_vce_dpm(hwmgr, true);
-+ return 0;
-+ }
-+ }
-+ } else {
-+ cz_dpm_update_vce_dpm(hwmgr);
-+ cz_enable_disable_vce_dpm(hwmgr, true);
-+ return 0;
-+ }
-+
-+ if (!cz_hwmgr->vce_power_gated)
-+ cz_dpm_update_vce_dpm(hwmgr);
-+
-+ return 0;
-+}
-+
-+
-+static struct phm_master_table_item cz_enable_clock_power_gatings_list[] = {
-+ /*we don't need an exit table here, because there is only D3 cold on Kv*/
-+ { phm_cf_want_uvd_power_gating, cz_tf_uvd_power_gating_initialize },
-+ { phm_cf_want_vce_power_gating, cz_tf_vce_power_gating_initialize },
-+ /* to do { NULL, cz_tf_xdma_power_gating_enable }, */
-+ { NULL, NULL }
-+};
-+
-+struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = {
-+ 0,
-+ PHM_MasterTableFlag_None,
-+ cz_enable_clock_power_gatings_list
-+};
-diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h
-new file mode 100644
-index 0000000..bbbc057
---- /dev/null
-+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h
-@@ -0,0 +1,37 @@
-+/*
-+ * Copyright 2015 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ */
-+
-+#ifndef _CZ_CLOCK_POWER_GATING_H_
-+#define _CZ_CLOCK_POWER_GATING_H_
-+
-+#include "cz_hwmgr.h"
-+#include "pp_asicblocks.h"
-+
-+extern int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating);
-+extern struct phm_master_table_header cz_phm_enable_clock_power_gatings_master;
-+extern struct phm_master_table_header cz_phm_disable_clock_power_gatings_master;
-+extern int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
-+extern int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
-+extern int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
-+extern int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable);
-+#endif /* _CZ_CLOCK_POWER_GATING_H_ */
-diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
-index 0c49505..e187b3f 100644
---- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
-+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
-@@ -28,12 +28,23 @@
- #include "processpptables.h"
- #include "cgs_common.h"
- #include "smu/smu_8_0_d.h"
-+#include "smu8_fusion.h"
-+#include "smu/smu_8_0_sh_mask.h"
- #include "smumgr.h"
- #include "hwmgr.h"
- #include "hardwaremanager.h"
- #include "cz_ppsmc.h"
- #include "cz_hwmgr.h"
- #include "power_state.h"
-+#include "cz_clockpowergating.h"
-+
-+
-+#define ixSMUSVI_NB_CURRENTVID 0xD8230044
-+#define CURRENT_NB_VID_MASK 0xff000000
-+#define CURRENT_NB_VID__SHIFT 24
-+#define ixSMUSVI_GFX_CURRENTVID 0xD8230048
-+#define CURRENT_GFX_VID_MASK 0xff000000
-+#define CURRENT_GFX_VID__SHIFT 24
-
- static const unsigned long PhwCz_Magic = (unsigned long) PHM_Cz_Magic;
-
-@@ -45,6 +56,46 @@ static struct cz_power_state *cast_PhwCzPowerState(struct pp_hw_power_state *hw_
- return (struct cz_power_state *)hw_ps;
- }
-
-+static const struct cz_power_state *cast_const_PhwCzPowerState(
-+ const struct pp_hw_power_state *hw_ps)
-+{
-+ if (PhwCz_Magic != hw_ps->magic)
-+ return NULL;
-+
-+ return (struct cz_power_state *)hw_ps;
-+}
-+
-+uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr,
-+ uint32_t clock, uint32_t msg)
-+{
-+ int i = 0;
-+ struct phm_vce_clock_voltage_dependency_table *ptable =
-+ hwmgr->dyn_state.vce_clocl_voltage_dependency_table;
-+
-+ switch (msg) {
-+ case PPSMC_MSG_SetEclkSoftMin:
-+ case PPSMC_MSG_SetEclkHardMin:
-+ for (i = 0; i < (int)ptable->count; i++) {
-+ if (clock <= ptable->entries[i].ecclk)
-+ break;
-+ }
-+ break;
-+
-+ case PPSMC_MSG_SetEclkSoftMax:
-+ case PPSMC_MSG_SetEclkHardMax:
-+ for (i = ptable->count - 1; i >= 0; i--) {
-+ if (clock >= ptable->entries[i].ecclk)
-+ break;
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ return i;
-+}
-+
- static uint32_t cz_get_sclk_level(struct pp_hwmgr *hwmgr,
- uint32_t clock, uint32_t msg)
- {
-@@ -75,6 +126,37 @@ static uint32_t cz_get_sclk_level(struct pp_hwmgr *hwmgr,
- return i;
- }
-
-+static uint32_t cz_get_uvd_level(struct pp_hwmgr *hwmgr,
-+ uint32_t clock, uint32_t msg)
-+{
-+ int i = 0;
-+ struct phm_uvd_clock_voltage_dependency_table *ptable =
-+ hwmgr->dyn_state.uvd_clocl_voltage_dependency_table;
-+
-+ switch (msg) {
-+ case PPSMC_MSG_SetUvdSoftMin:
-+ case PPSMC_MSG_SetUvdHardMin:
-+ for (i = 0; i < (int)ptable->count; i++) {
-+ if (clock <= ptable->entries[i].vclk)
-+ break;
-+ }
-+ break;
-+
-+ case PPSMC_MSG_SetUvdSoftMax:
-+ case PPSMC_MSG_SetUvdHardMax:
-+ for (i = ptable->count - 1; i >= 0; i--) {
-+ if (clock >= ptable->entries[i].vclk)
-+ break;
-+ }
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ return i;
-+}
-+
- static uint32_t cz_get_max_sclk_level(struct pp_hwmgr *hwmgr)
- {
- struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-@@ -504,6 +586,175 @@ static int cz_tf_init_sclk_threshold(struct pp_hwmgr *hwmgr, void *input,
-
- return 0;
- }
-+static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr,
-+ void *input, void *output,
-+ void *storage, int result)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+ struct phm_clock_voltage_dependency_table *table =
-+ hwmgr->dyn_state.vddc_dependency_on_sclk;
-+
-+ unsigned long clock = 0;
-+ unsigned long level;
-+ unsigned long stable_pstate_sclk;
-+ struct PP_Clocks clocks;
-+ unsigned long percentage;
-+
-+ cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk;
-+ level = cz_get_max_sclk_level(hwmgr) - 1;
-+
-+ if (level < table->count)
-+ cz_hwmgr->sclk_dpm.soft_max_clk = table->entries[level].clk;
-+ else
-+ cz_hwmgr->sclk_dpm.soft_max_clk = table->entries[table->count - 1].clk;
-+
-+ /*PECI_GetMinClockSettings(pHwMgr->pPECI, &clocks);*/
-+ clock = clocks.engineClock;
-+
-+ if (cz_hwmgr->sclk_dpm.hard_min_clk != clock) {
-+ cz_hwmgr->sclk_dpm.hard_min_clk = clock;
-+
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetSclkHardMin,
-+ cz_get_sclk_level(hwmgr,
-+ cz_hwmgr->sclk_dpm.hard_min_clk,
-+ PPSMC_MSG_SetSclkHardMin));
-+ }
-+
-+ clock = cz_hwmgr->sclk_dpm.soft_min_clk;
-+
-+ /* update minimum clocks for Stable P-State feature */
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_StablePState)) {
-+ percentage = 75;
-+ /*Sclk - calculate sclk value based on percentage and find FLOOR sclk from VddcDependencyOnSCLK table */
-+ stable_pstate_sclk = (hwmgr->dyn_state.max_clock_voltage_on_ac.mclk *
-+ percentage) / 100;
-+
-+ if (clock < stable_pstate_sclk)
-+ clock = stable_pstate_sclk;
-+ } else {
-+ if (clock < hwmgr->gfx_arbiter.sclk)
-+ clock = hwmgr->gfx_arbiter.sclk;
-+ }
-+
-+ if (cz_hwmgr->sclk_dpm.soft_min_clk != clock) {
-+ cz_hwmgr->sclk_dpm.soft_min_clk = clock;
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetSclkSoftMin,
-+ cz_get_sclk_level(hwmgr,
-+ cz_hwmgr->sclk_dpm.soft_min_clk,
-+ PPSMC_MSG_SetSclkSoftMin));
-+ }
-+
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_StablePState) &&
-+ cz_hwmgr->sclk_dpm.soft_max_clk != clock) {
-+ cz_hwmgr->sclk_dpm.soft_max_clk = clock;
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetSclkSoftMax,
-+ cz_get_sclk_level(hwmgr,
-+ cz_hwmgr->sclk_dpm.soft_max_clk,
-+ PPSMC_MSG_SetSclkSoftMax));
-+ }
-+
-+ return 0;
-+}
-+
-+static int cz_tf_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr,
-+ void *input, void *output,
-+ void *storage, int result)
-+{
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_SclkDeepSleep)) {
-+ /* TO DO get from dal PECI_GetMinClockSettings(pHwMgr->pPECI, &clocks); */
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetMinDeepSleepSclk,
-+ CZ_MIN_DEEP_SLEEP_SCLK);
-+ }
-+
-+ return 0;
-+}
-+
-+static int cz_tf_set_watermark_threshold(struct pp_hwmgr *hwmgr,
-+ void *input, void *output,
-+ void *storage, int result)
-+{
-+ struct cz_hwmgr *cz_hwmgr =
-+ (struct cz_hwmgr *)(hwmgr->backend);
-+
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetWatermarkFrequency,
-+ cz_hwmgr->sclk_dpm.soft_max_clk);
-+
-+ return 0;
-+}
-+
-+static int cz_tf_set_enabled_levels(struct pp_hwmgr *hwmgr,
-+ void *input, void *output,
-+ void *storage, int result)
-+{
-+ return 0;
-+}
-+
-+static int cz_tf_enable_nb_dpm(struct pp_hwmgr *hwmgr,
-+ void *input, void *output,
-+ void *storage, int result)
-+{
-+ int ret = 0;
-+ struct cz_hwmgr *cz_hwmgr =
-+ (struct cz_hwmgr *)(hwmgr->backend);
-+ unsigned long dpm_features = 0;
-+
-+ if (!cz_hwmgr->is_nb_dpm_enabled &&
-+ cz_hwmgr->is_nb_dpm_enabled_by_driver) { /* also depend on dal NBPStateDisableRequired */
-+ dpm_features |= NB_DPM_MASK;
-+ ret = smum_send_msg_to_smc_with_parameter(
-+ hwmgr->smumgr,
-+ PPSMC_MSG_EnableAllSmuFeatures,
-+ dpm_features);
-+ if (ret == 0)
-+ cz_hwmgr->is_nb_dpm_enabled = true;
-+ }
-+ return ret;
-+}
-+
-+static int cz_tf_update_low_mem_pstate(struct pp_hwmgr *hwmgr,
-+ void *input, void *output,
-+ void *storage, int result)
-+{
-+
-+ struct cz_hwmgr *cz_hwmgr =
-+ (struct cz_hwmgr *)(hwmgr->backend);
-+ const struct phm_set_power_state_input *states = (struct phm_set_power_state_input *)input;
-+ const struct cz_power_state *pnew_state = cast_const_PhwCzPowerState(states->pnew_state);
-+
-+ if (cz_hwmgr->sys_info.nb_dpm_enable) {
-+ if (pnew_state->action == FORCE_HIGH)
-+ smum_send_msg_to_smc(hwmgr->smumgr,
-+ PPSMC_MSG_DisableLowMemoryPstate);
-+ else
-+ smum_send_msg_to_smc(hwmgr->smumgr,
-+ PPSMC_MSG_EnableLowMemoryPstate);
-+ }
-+ return 0;
-+}
-+
-+static struct phm_master_table_item cz_set_power_state_list[] = {
-+ {NULL, cz_tf_update_sclk_limit},
-+ {NULL, cz_tf_set_deep_sleep_sclk_threshold},
-+ {NULL, cz_tf_set_watermark_threshold},
-+ {NULL, cz_tf_set_enabled_levels},
-+ {NULL, cz_tf_enable_nb_dpm},
-+ {NULL, cz_tf_update_low_mem_pstate},
-+ {NULL, NULL}
-+};
-+
-+static struct phm_master_table_header cz_set_power_state_master = {
-+ 0,
-+ PHM_MasterTableFlag_None,
-+ cz_set_power_state_list
-+};
-
- static struct phm_master_table_item cz_setup_asic_list[] = {
- {NULL, cz_tf_reset_active_process_mask},
-@@ -649,6 +900,56 @@ static struct phm_master_table_header cz_enable_dpm_master = {
- cz_enable_dpm_list
- };
-
-+static int cz_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
-+ struct pp_power_state *prequest_ps,
-+ const struct pp_power_state *pcurrent_ps)
-+{
-+ struct cz_power_state *cz_ps =
-+ cast_PhwCzPowerState(&prequest_ps->hardware);
-+
-+ const struct cz_power_state *cz_current_ps =
-+ cast_const_PhwCzPowerState(&pcurrent_ps->hardware);
-+
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+ struct PP_Clocks clocks;
-+ bool force_high;
-+ unsigned long num_of_active_displays = 4;
-+
-+ cz_ps->evclk = hwmgr->vce_arbiter.evclk;
-+ cz_ps->ecclk = hwmgr->vce_arbiter.ecclk;
-+
-+ cz_ps->need_dfs_bypass = true;
-+
-+ cz_hwmgr->video_start = (hwmgr->uvd_arbiter.vclk != 0 || hwmgr->uvd_arbiter.dclk != 0 ||
-+ hwmgr->vce_arbiter.evclk != 0 || hwmgr->vce_arbiter.ecclk != 0);
-+
-+ cz_hwmgr->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label);
-+
-+ /* to do PECI_GetMinClockSettings(pHwMgr->pPECI, &clocks); */
-+ /* PECI_GetNumberOfActiveDisplays(pHwMgr->pPECI, &numOfActiveDisplays); */
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
-+ clocks.memoryClock = hwmgr->dyn_state.max_clock_voltage_on_ac.mclk;
-+ else
-+ clocks.memoryClock = 0;
-+
-+ if (clocks.memoryClock < hwmgr->gfx_arbiter.mclk)
-+ clocks.memoryClock = hwmgr->gfx_arbiter.mclk;
-+
-+ force_high = (clocks.memoryClock > cz_hwmgr->sys_info.nbp_memory_clock[CZ_NUM_NBPMEMORYCLOCK - 1])
-+ || (num_of_active_displays >= 3);
-+
-+ cz_ps->action = cz_current_ps->action;
-+
-+ if ((force_high == false) && (cz_ps->action == FORCE_HIGH))
-+ cz_ps->action = CANCEL_FORCE_HIGH;
-+ else if ((force_high == true) && (cz_ps->action != FORCE_HIGH))
-+ cz_ps->action = FORCE_HIGH;
-+ else
-+ cz_ps->action = DO_NOTHING;
-+
-+ return 0;
-+}
-+
- static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
- {
- int result = 0;
-@@ -676,10 +977,28 @@ static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
-
- result = phm_construct_table(hwmgr, &cz_disable_dpm_master,
- &(hwmgr->disable_dynamic_state_management));
--
-+ if (result != 0) {
-+ printk(KERN_ERR "[ powerplay ] Fail to disable_dynamic_state\n");
-+ return result;
-+ }
- result = phm_construct_table(hwmgr, &cz_enable_dpm_master,
- &(hwmgr->enable_dynamic_state_management));
-+ if (result != 0) {
-+ printk(KERN_ERR "[ powerplay ] Fail to enable_dynamic_state\n");
-+ return result;
-+ }
-+ result = phm_construct_table(hwmgr, &cz_set_power_state_master,
-+ &(hwmgr->set_power_state));
-+ if (result != 0) {
-+ printk(KERN_ERR "[ powerplay ] Fail to construct set_power_state\n");
-+ return result;
-+ }
-
-+ result = phm_construct_table(hwmgr, &cz_phm_enable_clock_power_gatings_master, &(hwmgr->enable_clock_power_gatings));
-+ if (result != 0) {
-+ printk(KERN_ERR "[ powerplay ] Fail to construct enable_clock_power_gatings\n");
-+ return result;
-+ }
- return result;
- }
-
-@@ -793,6 +1112,138 @@ static int cz_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
- return ret;
- }
-
-+int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr)
-+{
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_UVDPowerGating))
-+ return smum_send_msg_to_smc(hwmgr->smumgr,
-+ PPSMC_MSG_UVDPowerOFF);
-+ return 0;
-+}
-+
-+int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr)
-+{
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_UVDPowerGating)) {
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_UVDDynamicPowerGating)) {
-+ return smum_send_msg_to_smc_with_parameter(
-+ hwmgr->smumgr,
-+ PPSMC_MSG_UVDPowerON, 1);
-+ } else {
-+ return smum_send_msg_to_smc_with_parameter(
-+ hwmgr->smumgr,
-+ PPSMC_MSG_UVDPowerON, 0);
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+ struct phm_uvd_clock_voltage_dependency_table *ptable =
-+ hwmgr->dyn_state.uvd_clocl_voltage_dependency_table;
-+
-+ if (!bgate) {
-+ /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_StablePState)) {
-+ cz_hwmgr->uvd_dpm.hard_min_clk =
-+ ptable->entries[ptable->count - 1].vclk;
-+
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetUvdHardMin,
-+ cz_get_uvd_level(hwmgr,
-+ cz_hwmgr->uvd_dpm.hard_min_clk,
-+ PPSMC_MSG_SetUvdHardMin));
-+
-+ cz_enable_disable_uvd_dpm(hwmgr, true);
-+ } else
-+ cz_enable_disable_uvd_dpm(hwmgr, true);
-+ } else
-+ cz_enable_disable_uvd_dpm(hwmgr, false);
-+
-+ return 0;
-+}
-+
-+int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+ struct phm_vce_clock_voltage_dependency_table *ptable =
-+ hwmgr->dyn_state.vce_clocl_voltage_dependency_table;
-+
-+ /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_StablePState)) {
-+ cz_hwmgr->vce_dpm.hard_min_clk =
-+ ptable->entries[ptable->count - 1].ecclk;
-+
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetEclkHardMin,
-+ cz_get_eclk_level(hwmgr,
-+ cz_hwmgr->vce_dpm.hard_min_clk,
-+ PPSMC_MSG_SetEclkHardMin));
-+ } else {
-+ /*EPR# 419220 -HW limitation to to */
-+ cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
-+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-+ PPSMC_MSG_SetEclkHardMin,
-+ cz_get_eclk_level(hwmgr,
-+ cz_hwmgr->vce_dpm.hard_min_clk,
-+ PPSMC_MSG_SetEclkHardMin));
-+
-+ }
-+ return 0;
-+}
-+
-+int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr)
-+{
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_VCEPowerGating))
-+ return smum_send_msg_to_smc(hwmgr->smumgr,
-+ PPSMC_MSG_VCEPowerOFF);
-+ return 0;
-+}
-+
-+int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr)
-+{
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_VCEPowerGating))
-+ return smum_send_msg_to_smc(hwmgr->smumgr,
-+ PPSMC_MSG_VCEPowerON);
-+ return 0;
-+}
-+
-+static int cz_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+
-+ return cz_hwmgr->sys_info.bootup_uma_clock;
-+}
-+
-+static int cz_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
-+{
-+ struct pp_power_state *ps;
-+ struct cz_power_state *cz_ps;
-+
-+ if (hwmgr == NULL)
-+ return -EINVAL;
-+
-+ ps = hwmgr->request_ps;
-+
-+ if (ps == NULL)
-+ return -EINVAL;
-+
-+ cz_ps = cast_PhwCzPowerState(&ps->hardware);
-+
-+ if (low)
-+ return cz_ps->levels[0].engineClock;
-+ else
-+ return cz_ps->levels[cz_ps->level-1].engineClock;
-+}
-+
- static int cz_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
- struct pp_hw_power_state *hw_ps)
- {
-@@ -871,15 +1322,83 @@ int cz_get_power_state_size(struct pp_hwmgr *hwmgr)
- return sizeof(struct cz_power_state);
- }
-
-+static void
-+cz_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m)
-+{
-+ struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
-+
-+ struct phm_clock_voltage_dependency_table *table =
-+ hwmgr->dyn_state.vddc_dependency_on_sclk;
-+
-+ struct phm_vce_clock_voltage_dependency_table *vce_table =
-+ hwmgr->dyn_state.vce_clocl_voltage_dependency_table;
-+
-+ struct phm_uvd_clock_voltage_dependency_table *uvd_table =
-+ hwmgr->dyn_state.uvd_clocl_voltage_dependency_table;
-+
-+ uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX),
-+ TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);
-+ uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
-+ TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);
-+ uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
-+ TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
-+
-+ uint32_t sclk, vclk, dclk, ecclk, tmp;
-+ uint16_t vddnb, vddgfx;
-+
-+ if (sclk_index >= NUM_SCLK_LEVELS) {
-+ seq_printf(m, "\n invalid sclk dpm profile %d\n", sclk_index);
-+ } else {
-+ sclk = table->entries[sclk_index].clk;
-+ seq_printf(m, "\n index: %u sclk: %u MHz\n", sclk_index, sclk/100);
-+ }
-+
-+ tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) &
-+ CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;
-+ vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp);
-+ tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) &
-+ CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;
-+ vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp);
-+ seq_printf(m, "\n vddnb: %u vddgfx: %u\n", vddnb, vddgfx);
-+
-+ seq_printf(m, "\n uvd %sabled\n", cz_hwmgr->uvd_power_gated ? "dis" : "en");
-+ if (!cz_hwmgr->uvd_power_gated) {
-+ if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
-+ seq_printf(m, "\n invalid uvd dpm level %d\n", uvd_index);
-+ } else {
-+ vclk = uvd_table->entries[uvd_index].vclk;
-+ dclk = uvd_table->entries[uvd_index].dclk;
-+ seq_printf(m, "\n index: %u uvd vclk: %u MHz dclk: %u MHz\n", uvd_index, vclk/100, dclk/100);
-+ }
-+ }
-+
-+ seq_printf(m, "\n vce %sabled\n", cz_hwmgr->vce_power_gated ? "dis" : "en");
-+ if (!cz_hwmgr->vce_power_gated) {
-+ if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
-+ seq_printf(m, "\n invalid vce dpm level %d\n", vce_index);
-+ } else {
-+ ecclk = vce_table->entries[vce_index].ecclk;
-+ seq_printf(m, "\n index: %u vce ecclk: %u MHz\n", vce_index, ecclk/100);
-+ }
-+ }
-+}
-+
- static const struct pp_hwmgr_func cz_hwmgr_funcs = {
- .backend_init = cz_hwmgr_backend_init,
- .backend_fini = cz_hwmgr_backend_fini,
- .asic_setup = NULL,
-+ .apply_state_adjust_rules = cz_apply_state_adjust_rules,
- .force_dpm_level = cz_dpm_force_dpm_level,
- .get_power_state_size = cz_get_power_state_size,
-+ .powerdown_uvd = cz_dpm_powerdown_uvd,
-+ .powergate_uvd = cz_dpm_powergate_uvd,
-+ .powergate_vce = cz_dpm_powergate_vce,
-+ .get_mclk = cz_dpm_get_mclk,
-+ .get_sclk = cz_dpm_get_sclk,
- .patch_boot_state = cz_dpm_patch_boot_state,
- .get_pp_table_entry = cz_dpm_get_pp_table_entry,
- .get_num_of_pp_table_entries = cz_dpm_get_num_of_pp_table_entries,
-+ .print_current_perforce_level = cz_print_current_perforce_level,
- };
-
- int cz_hwmgr_init(struct pp_hwmgr *hwmgr)
-diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h
-index 05849fd..70b0e51 100644
---- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h
-+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h
-@@ -32,6 +32,7 @@
- #define CZ_AT_DFLT 30
- #define CZ_MAX_HARDWARE_POWERLEVELS 8
- #define PPCZ_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102
-+#define CZ_MIN_DEEP_SLEEP_SCLK 800
-
- /* Carrizo device IDs */
- #define DEVICE_ID_CZ_9870 0x9870
-@@ -198,6 +199,9 @@ struct cz_hwmgr {
- struct cz_sys_info sys_info;
-
- struct cz_power_level boot_power_level;
-+ struct cz_power_state *cz_current_ps;
-+ struct cz_power_state *cz_requested_ps;
-+
- uint32_t mgcg_cgtt_local0;
- uint32_t mgcg_cgtt_local1;
-
-@@ -299,11 +303,15 @@ struct cz_hwmgr {
-
- uint32_t max_sclk_level;
- uint32_t num_of_clk_entries;
-- struct cz_power_state *cz_ps;
- };
-
- struct pp_hwmgr;
-
- int cz_hwmgr_init(struct pp_hwmgr *hwmgr);
--
-+int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr);
-+int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr);
-+int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr);
-+int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr);
-+int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
-+int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr);
- #endif /* _CZ_HWMGR_H_ */
-diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
-index 7317e43..aec9f6d 100644
---- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
-+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
-@@ -23,6 +23,7 @@
- #include <linux/errno.h>
- #include "hwmgr.h"
- #include "hardwaremanager.h"
-+#include "power_state.h"
- #include "pp_acpi.h"
- #include "amd_acpi.h"
-
-@@ -55,6 +56,17 @@ void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr)
- phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest);
- }
-
-+bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr)
-+{
-+ return hwmgr->block_hw_access;
-+}
-+
-+int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block)
-+{
-+ hwmgr->block_hw_access = block;
-+ return 0;
-+}
-+
- int phm_setup_asic(struct pp_hwmgr *hwmgr)
- {
- if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-@@ -62,13 +74,33 @@ int phm_setup_asic(struct pp_hwmgr *hwmgr)
- if (NULL != hwmgr->hwmgr_func->asic_setup)
- return hwmgr->hwmgr_func->asic_setup(hwmgr);
- } else {
-- return phm_dispatch_table (hwmgr, &(hwmgr->setup_asic),
-+ return phm_dispatch_table(hwmgr, &(hwmgr->setup_asic),
- NULL, NULL);
- }
-
- return 0;
- }
-
-+int phm_set_power_state(struct pp_hwmgr *hwmgr,
-+ const struct pp_hw_power_state *pcurrent_state,
-+ const struct pp_hw_power_state *pnew_power_state)
-+{
-+ struct phm_set_power_state_input states;
-+
-+ states.pcurrent_state = pcurrent_state;
-+ states.pnew_state = pnew_power_state;
-+
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_TablelessHardwareInterface)) {
-+ if (NULL != hwmgr->hwmgr_func->power_state_set)
-+ return hwmgr->hwmgr_func->power_state_set(hwmgr, &states);
-+ } else {
-+ return phm_dispatch_table(hwmgr, &(hwmgr->set_power_state), &states, NULL);
-+ }
-+
-+ return 0;
-+}
-+
- int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
- {
- if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-@@ -76,9 +108,62 @@ int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
- if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable)
- return hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr);
- } else {
-- return phm_dispatch_table (hwmgr,
-+ return phm_dispatch_table(hwmgr,
- &(hwmgr->enable_dynamic_state_management),
- NULL, NULL);
- }
- return 0;
- }
-+
-+int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level)
-+{
-+ if (hwmgr->hwmgr_func->force_dpm_level != NULL)
-+ return hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
-+
-+ return 0;
-+}
-+
-+int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
-+ struct pp_power_state *adjusted_ps,
-+ const struct pp_power_state *current_ps)
-+{
-+ if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL)
-+ return hwmgr->hwmgr_func->apply_state_adjust_rules(
-+ hwmgr,
-+ adjusted_ps,
-+ current_ps);
-+ return 0;
-+}
-+
-+int phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
-+{
-+ if (hwmgr->hwmgr_func->powerdown_uvd != NULL)
-+ return hwmgr->hwmgr_func->powerdown_uvd(hwmgr);
-+ return 0;
-+}
-+
-+int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate)
-+{
-+ if (hwmgr->hwmgr_func->powergate_uvd != NULL)
-+ return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
-+ return 0;
-+}
-+
-+int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate)
-+{
-+ if (hwmgr->hwmgr_func->powergate_vce != NULL)
-+ return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
-+ return 0;
-+}
-+
-+int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr)
-+{
-+ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-+ PHM_PlatformCaps_TablelessHardwareInterface)) {
-+ if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating)
-+ return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr);
-+ } else {
-+ return phm_dispatch_table(hwmgr, &(hwmgr->enable_clock_power_gatings), NULL, NULL);
-+ }
-+ return 0;
-+}
-diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
-index e26df90..5d1ba90 100644
---- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
-+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
-@@ -201,3 +201,13 @@ void phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr,
- phm_wait_for_register_unequal(hwmgr, indirect_port + 1,
- value, mask);
- }
-+
-+bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr)
-+{
-+ return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating);
-+}
-+
-+bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr)
-+{
-+ return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating);
-+}
-diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
-index 26e1256..a69b379 100644
---- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
-+++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
-@@ -23,7 +23,12 @@
- #ifndef _HARDWARE_MANAGER_H_
- #define _HARDWARE_MANAGER_H_
-
-+
-+
- struct pp_hwmgr;
-+struct pp_hw_power_state;
-+struct pp_power_state;
-+enum amd_dpm_forced_level;
-
- /* Automatic Power State Throttling */
- enum PHM_AutoThrottleSource
-@@ -206,6 +211,24 @@ struct pp_hw_descriptor {
- uint32_t hw_caps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES];
- };
-
-+enum PHM_PerformanceLevelDesignation {
-+ PHM_PerformanceLevelDesignation_Activity,
-+ PHM_PerformanceLevelDesignation_PowerContainment
-+};
-+
-+typedef enum PHM_PerformanceLevelDesignation PHM_PerformanceLevelDesignation;
-+
-+struct PHM_PerformanceLevel {
-+ uint32_t coreClock;
-+ uint32_t memory_clock;
-+ uint32_t vddc;
-+ uint32_t vddci;
-+ uint32_t nonLocalMemoryFreq;
-+ uint32_t nonLocalMemoryWidth;
-+};
-+
-+typedef struct PHM_PerformanceLevel PHM_PerformanceLevel;
-+
- /* Function for setting a platform cap */
- static inline void phm_cap_set(uint32_t *caps,
- enum phm_platform_caps c)
-@@ -226,6 +249,20 @@ static inline bool phm_cap_enabled(const uint32_t *caps, enum phm_platform_caps
- (1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1)))));
- }
-
-+#define PP_PCIEGenInvalid 0xffff
-+enum PP_PCIEGen {
-+ PP_PCIEGen1 = 0, /* PCIE 1.0 - Transfer rate of 2.5 GT/s */
-+ PP_PCIEGen2, /*PCIE 2.0 - Transfer rate of 5.0 GT/s */
-+ PP_PCIEGen3 /*PCIE 3.0 - Transfer rate of 8.0 GT/s */
-+};
-+
-+typedef enum PP_PCIEGen PP_PCIEGen;
-+
-+#define PP_Min_PCIEGen PP_PCIEGen1
-+#define PP_Max_PCIEGen PP_PCIEGen3
-+#define PP_Min_PCIELane 1
-+#define PP_Max_PCIELane 32
-+
- enum phm_clock_Type {
- PHM_DispClock = 1,
- PHM_SClock,
-@@ -273,8 +310,22 @@ struct phm_clocks {
- uint32_t num_of_entries;
- uint32_t clock[MAX_NUM_CLOCKS];
- };
--
-+extern int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr);
-+extern int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate);
-+extern int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate);
-+extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
- extern int phm_setup_asic(struct pp_hwmgr *hwmgr);
- extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr);
- extern void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr);
-+extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr);
-+extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block);
-+extern int phm_set_power_state(struct pp_hwmgr *hwmgr,
-+ const struct pp_hw_power_state *pcurrent_state,
-+ const struct pp_hw_power_state *pnew_power_state);
-+
-+extern int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
-+ struct pp_power_state *adjusted_ps,
-+ const struct pp_power_state *current_ps);
-+
-+extern int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level);
- #endif /* _HARDWARE_MANAGER_H_ */
-diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
-index 07fba41..18b5ab1 100644
---- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
-+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
-@@ -23,6 +23,7 @@
- #ifndef _HWMGR_H_
- #define _HWMGR_H_
-
-+#include <linux/seq_file.h>
- #include "amd_powerplay.h"
- #include "pp_instance.h"
- #include "hardwaremanager.h"
-@@ -85,6 +86,11 @@ typedef int (*phm_table_function)(struct pp_hwmgr *hwmgr, void *input,
-
- typedef bool (*phm_check_function)(struct pp_hwmgr *hwmgr);
-
-+struct phm_set_power_state_input {
-+ const struct pp_hw_power_state *pcurrent_state;
-+ const struct pp_hw_power_state *pnew_state;
-+};
-+
- struct phm_acp_arbiter {
- uint32_t acpclk;
- };
-@@ -252,11 +258,34 @@ struct pp_hwmgr_func {
- int (*backend_fini)(struct pp_hwmgr *hw_mgr);
- int (*asic_setup)(struct pp_hwmgr *hw_mgr);
- int (*get_power_state_size)(struct pp_hwmgr *hw_mgr);
-- int (*force_dpm_level)(struct pp_hwmgr *hw_mgr, enum amd_dpm_forced_level level);
-- int (*dynamic_state_management_enable)(struct pp_hwmgr *hw_mgr);
-- int (*patch_boot_state)(struct pp_hwmgr *hwmgr, struct pp_hw_power_state *hw_ps);
-- int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr, unsigned long, struct pp_power_state *);
-+
-+ int (*apply_state_adjust_rules)(struct pp_hwmgr *hwmgr,
-+ struct pp_power_state *prequest_ps,
-+ const struct pp_power_state *pcurrent_ps);
-+
-+ int (*force_dpm_level)(struct pp_hwmgr *hw_mgr,
-+ enum amd_dpm_forced_level level);
-+
-+ int (*dynamic_state_management_enable)(
-+ struct pp_hwmgr *hw_mgr);
-+
-+ int (*patch_boot_state)(struct pp_hwmgr *hwmgr,
-+ struct pp_hw_power_state *hw_ps);
-+
-+ int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr,
-+ unsigned long, struct pp_power_state *);
-+
- int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr);
-+ int (*powerdown_uvd)(struct pp_hwmgr *hwmgr);
-+ int (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate);
-+ int (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate);
-+ int (*get_mclk)(struct pp_hwmgr *hwmgr, bool low);
-+ int (*get_sclk)(struct pp_hwmgr *hwmgr, bool low);
-+ int (*power_state_set)(struct pp_hwmgr *hwmgr,
-+ const void *state);
-+ void (*print_current_perforce_level)(struct pp_hwmgr *hwmgr,
-+ struct seq_file *m);
-+ int (*enable_clock_power_gating)(struct pp_hwmgr *hwmgr);
- };
-
- struct pp_table_func {
-@@ -416,7 +445,7 @@ struct pp_hwmgr {
- struct pp_smumgr *smumgr;
- const void *soft_pp_table;
- enum amd_dpm_forced_level dpm_level;
--
-+ bool block_hw_access;
- struct phm_gfx_arbiter gfx_arbiter;
- struct phm_acp_arbiter acp_arbiter;
- struct phm_uvd_arbiter uvd_arbiter;
-@@ -430,6 +459,8 @@ struct pp_hwmgr {
- struct phm_runtime_table_header setup_asic;
- struct phm_runtime_table_header disable_dynamic_state_management;
- struct phm_runtime_table_header enable_dynamic_state_management;
-+ struct phm_runtime_table_header set_power_state;
-+ struct phm_runtime_table_header enable_clock_power_gatings;
- const struct pp_hwmgr_func *hwmgr_func;
- const struct pp_table_func *pptable_func;
- struct pp_power_state *ps;
-@@ -471,6 +502,11 @@ extern void phm_wait_for_indirect_register_unequal(
- uint32_t value,
- uint32_t mask);
-
-+bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr);
-+bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr);
-+
-+#define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU
-+
- #define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
- #define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK
-
-diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h b/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h
-new file mode 100644
-index 0000000..0c1593e
---- /dev/null
-+++ b/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h
-@@ -0,0 +1,47 @@
-+/*
-+ * Copyright 2015 Advanced Micro Devices, Inc.
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
-+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-+ * OTHER DEALINGS IN THE SOFTWARE.
-+ *
-+ */
-+#ifndef PP_ASICBLOCKS_H
-+#define PP_ASICBLOCKS_H
-+
-+
-+enum PHM_AsicBlock {
-+ PHM_AsicBlock_GFX,
-+ PHM_AsicBlock_UVD_MVC,
-+ PHM_AsicBlock_UVD,
-+ PHM_AsicBlock_UVD_HD,
-+ PHM_AsicBlock_UVD_SD,
-+ PHM_AsicBlock_Count
-+};
-+
-+enum PHM_ClockGateSetting {
-+ PHM_ClockGateSetting_StaticOn,
-+ PHM_ClockGateSetting_StaticOff,
-+ PHM_ClockGateSetting_Dynamic
-+};
-+
-+struct phm_asic_blocks {
-+ bool gfx : 1;
-+ bool uvd : 1;
-+};
-+
-+#endif
---
-2.7.4
-