aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3797-drm-amd-pp-Replace-rv_-with-smu10_.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3797-drm-amd-pp-Replace-rv_-with-smu10_.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3797-drm-amd-pp-Replace-rv_-with-smu10_.patch3770
1 files changed, 3770 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3797-drm-amd-pp-Replace-rv_-with-smu10_.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3797-drm-amd-pp-Replace-rv_-with-smu10_.patch
new file mode 100644
index 00000000..169741c1
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3797-drm-amd-pp-Replace-rv_-with-smu10_.patch
@@ -0,0 +1,3770 @@
+From 92c3fc499b8caa2bd1a8a5322d8edc4d8dce6cd6 Mon Sep 17 00:00:00 2001
+From: Rex Zhu <Rex.Zhu@amd.com>
+Date: Tue, 6 Mar 2018 17:28:38 +0800
+Subject: [PATCH 3797/4131] drm/amd/pp: Replace rv_* with smu10_*
+
+Powerplay is for the hw ip smu, for RV, smu10 is used,
+so use smu10 as the prefix of the files name/function name.
+
+Change-Id: Ib47ab34a7e7870a61ebde2e18105b4222fc91e49
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
+Signed-off-by: Kalyan Alle <kalyan.alle@amd.com>
+---
+ drivers/gpu/drm/amd/powerplay/hwmgr/Makefile | 2 +-
+ drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 6 +-
+ drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c | 1043 --------------------
+ drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h | 320 ------
+ drivers/gpu/drm/amd/powerplay/hwmgr/rv_inc.h | 43 -
+ drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 1042 +++++++++++++++++++
+ drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h | 322 ++++++
+ drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h | 43 +
+ drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 2 +-
+ drivers/gpu/drm/amd/powerplay/smumgr/Makefile | 2 +-
+ drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c | 346 -------
+ drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h | 50 -
+ .../gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c | 346 +++++++
+ .../gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h | 50 +
+ 14 files changed, 1809 insertions(+), 1808 deletions(-)
+ delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c
+ delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h
+ delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/rv_inc.h
+ create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+ create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h
+ create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h
+ delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c
+ delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h
+ create mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
+ create mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h
+
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
+index aa150c9..efbdd3e 100644
+--- a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
+@@ -10,7 +10,7 @@ HARDWARE_MGR = hwmgr.o processpptables.o \
+ smu7_hwmgr.o smu7_powertune.o smu7_thermal.o \
+ smu7_clockpowergating.o \
+ vega10_processpptables.o vega10_hwmgr.o vega10_powertune.o \
+- vega10_thermal.o rv_hwmgr.o pp_psm.o\
++ vega10_thermal.o smu10_hwmgr.o pp_psm.o\
+ pp_overdriver.o
+
+ AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
+index af1b22d..3432dc0 100644
+--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
+@@ -43,7 +43,7 @@ extern const struct pp_smumgr_func tonga_smu_funcs;
+ extern const struct pp_smumgr_func fiji_smu_funcs;
+ extern const struct pp_smumgr_func polaris10_smu_funcs;
+ extern const struct pp_smumgr_func vega10_smu_funcs;
+-extern const struct pp_smumgr_func rv_smu_funcs;
++extern const struct pp_smumgr_func smu10_smu_funcs;
+
+ extern int cz_init_function_pointers(struct pp_hwmgr *hwmgr);
+ static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr);
+@@ -230,8 +230,8 @@ int hwmgr_early_init(struct pp_instance *handle)
+ switch (hwmgr->chip_id) {
+ case CHIP_RAVEN:
+ hwmgr->od_enabled = false;
+- hwmgr->smumgr_funcs = &rv_smu_funcs;
+- rv_init_function_pointers(hwmgr);
++ hwmgr->smumgr_funcs = &smu10_smu_funcs;
++ smu10_init_function_pointers(hwmgr);
+ break;
+ default:
+ return -EINVAL;
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c
+deleted file mode 100644
+index f314591..0000000
+--- a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c
++++ /dev/null
+@@ -1,1043 +0,0 @@
+-/*
+- * 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 "pp_debug.h"
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/slab.h>
+-#include "atom-types.h"
+-#include "atombios.h"
+-#include "processpptables.h"
+-#include "cgs_common.h"
+-#include "smumgr.h"
+-#include "hwmgr.h"
+-#include "hardwaremanager.h"
+-#include "rv_ppsmc.h"
+-#include "rv_hwmgr.h"
+-#include "power_state.h"
+-#include "pp_soc15.h"
+-
+-#define RAVEN_MAX_DEEPSLEEP_DIVIDER_ID 5
+-#define RAVEN_MINIMUM_ENGINE_CLOCK 800 /* 8Mhz, the low boundary of engine clock allowed on this chip */
+-#define SCLK_MIN_DIV_INTV_SHIFT 12
+-#define RAVEN_DISPCLK_BYPASS_THRESHOLD 10000 /* 100Mhz */
+-#define SMC_RAM_END 0x40000
+-
+-static const unsigned long PhwRaven_Magic = (unsigned long) PHM_Rv_Magic;
+-
+-
+-int rv_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
+- struct pp_display_clock_request *clock_req);
+-
+-
+-static struct rv_power_state *cast_rv_ps(struct pp_hw_power_state *hw_ps)
+-{
+- if (PhwRaven_Magic != hw_ps->magic)
+- return NULL;
+-
+- return (struct rv_power_state *)hw_ps;
+-}
+-
+-static const struct rv_power_state *cast_const_rv_ps(
+- const struct pp_hw_power_state *hw_ps)
+-{
+- if (PhwRaven_Magic != hw_ps->magic)
+- return NULL;
+-
+- return (struct rv_power_state *)hw_ps;
+-}
+-
+-static int rv_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_hwmgr *rv_hwmgr = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- rv_hwmgr->dce_slow_sclk_threshold = 30000;
+- rv_hwmgr->thermal_auto_throttling_treshold = 0;
+- rv_hwmgr->is_nb_dpm_enabled = 1;
+- rv_hwmgr->dpm_flags = 1;
+- rv_hwmgr->gfx_off_controled_by_driver = false;
+- rv_hwmgr->need_min_deep_sleep_dcefclk = true;
+- rv_hwmgr->num_active_display = 0;
+- rv_hwmgr->deep_sleep_dcefclk = 0;
+-
+- phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+- PHM_PlatformCaps_SclkDeepSleep);
+-
+- phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+- PHM_PlatformCaps_SclkThrottleLowNotification);
+-
+- phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+- PHM_PlatformCaps_PowerPlaySupport);
+- return 0;
+-}
+-
+-static int rv_construct_max_power_limits_table(struct pp_hwmgr *hwmgr,
+- struct phm_clock_and_voltage_limits *table)
+-{
+- return 0;
+-}
+-
+-static int rv_init_dynamic_state_adjustment_rule_settings(
+- struct pp_hwmgr *hwmgr)
+-{
+- uint32_t table_size =
+- sizeof(struct phm_clock_voltage_dependency_table) +
+- (7 * sizeof(struct phm_clock_voltage_dependency_record));
+-
+- struct phm_clock_voltage_dependency_table *table_clk_vlt =
+- kzalloc(table_size, GFP_KERNEL);
+-
+- if (NULL == table_clk_vlt) {
+- pr_err("Can not allocate memory!\n");
+- return -ENOMEM;
+- }
+-
+- table_clk_vlt->count = 8;
+- table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0;
+- table_clk_vlt->entries[0].v = 0;
+- table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1;
+- table_clk_vlt->entries[1].v = 1;
+- table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2;
+- table_clk_vlt->entries[2].v = 2;
+- table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3;
+- table_clk_vlt->entries[3].v = 3;
+- table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4;
+- table_clk_vlt->entries[4].v = 4;
+- table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5;
+- table_clk_vlt->entries[5].v = 5;
+- table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6;
+- table_clk_vlt->entries[6].v = 6;
+- table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7;
+- table_clk_vlt->entries[7].v = 7;
+- hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
+-
+- return 0;
+-}
+-
+-static int rv_get_system_info_data(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)hwmgr->backend;
+-
+- rv_data->sys_info.htc_hyst_lmt = 5;
+- rv_data->sys_info.htc_tmp_lmt = 203;
+-
+- if (rv_data->thermal_auto_throttling_treshold == 0)
+- rv_data->thermal_auto_throttling_treshold = 203;
+-
+- rv_construct_max_power_limits_table (hwmgr,
+- &hwmgr->dyn_state.max_clock_voltage_on_ac);
+-
+- rv_init_dynamic_state_adjustment_rule_settings(hwmgr);
+-
+- return 0;
+-}
+-
+-static int rv_construct_boot_state(struct pp_hwmgr *hwmgr)
+-{
+- return 0;
+-}
+-
+-static int rv_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input)
+-{
+- struct PP_Clocks clocks = {0};
+- struct pp_display_clock_request clock_req;
+-
+- clocks.dcefClock = hwmgr->display_config.min_dcef_set_clk;
+- clock_req.clock_type = amd_pp_dcf_clock;
+- clock_req.clock_freq_in_khz = clocks.dcefClock * 10;
+-
+- PP_ASSERT_WITH_CODE(!rv_display_clock_voltage_request(hwmgr, &clock_req),
+- "Attempt to set DCF Clock Failed!", return -EINVAL);
+-
+- return 0;
+-}
+-
+-static int rv_set_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- if (rv_data->need_min_deep_sleep_dcefclk && rv_data->deep_sleep_dcefclk != clock/100) {
+- rv_data->deep_sleep_dcefclk = clock/100;
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetMinDeepSleepDcefclk,
+- rv_data->deep_sleep_dcefclk);
+- }
+-
+- return 0;
+-}
+-
+-static int rv_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- if (rv_data->num_active_display != count) {
+- rv_data->num_active_display = count;
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetDisplayCount,
+- rv_data->num_active_display);
+- }
+-
+- return 0;
+-}
+-
+-static int rv_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
+-{
+- return rv_set_clock_limit(hwmgr, input);
+-}
+-
+-static int rv_init_power_gate_state(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- rv_data->vcn_power_gated = true;
+- rv_data->isp_tileA_power_gated = true;
+- rv_data->isp_tileB_power_gated = true;
+-
+- return 0;
+-}
+-
+-
+-static int rv_setup_asic_task(struct pp_hwmgr *hwmgr)
+-{
+- return rv_init_power_gate_state(hwmgr);
+-}
+-
+-static int rv_reset_cc6_data(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- rv_data->separation_time = 0;
+- rv_data->cc6_disable = false;
+- rv_data->pstate_disable = false;
+- rv_data->cc6_setting_changed = false;
+-
+- return 0;
+-}
+-
+-static int rv_power_off_asic(struct pp_hwmgr *hwmgr)
+-{
+- return rv_reset_cc6_data(hwmgr);
+-}
+-
+-static int rv_disable_gfx_off(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- if (rv_data->gfx_off_controled_by_driver)
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff);
+-
+- return 0;
+-}
+-
+-static int rv_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
+-{
+- return rv_disable_gfx_off(hwmgr);
+-}
+-
+-static int rv_enable_gfx_off(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- if (rv_data->gfx_off_controled_by_driver)
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff);
+-
+- return 0;
+-}
+-
+-static int rv_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+-{
+- return rv_enable_gfx_off(hwmgr);
+-}
+-
+-static int rv_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
+- struct pp_power_state *prequest_ps,
+- const struct pp_power_state *pcurrent_ps)
+-{
+- return 0;
+-}
+-
+-/* temporary hardcoded clock voltage breakdown tables */
+-static const DpmClock_t VddDcfClk[]= {
+- { 300, 2600},
+- { 600, 3200},
+- { 600, 3600},
+-};
+-
+-static const DpmClock_t VddSocClk[]= {
+- { 478, 2600},
+- { 722, 3200},
+- { 722, 3600},
+-};
+-
+-static const DpmClock_t VddFClk[]= {
+- { 400, 2600},
+- {1200, 3200},
+- {1200, 3600},
+-};
+-
+-static const DpmClock_t VddDispClk[]= {
+- { 435, 2600},
+- { 661, 3200},
+- {1086, 3600},
+-};
+-
+-static const DpmClock_t VddDppClk[]= {
+- { 435, 2600},
+- { 661, 3200},
+- { 661, 3600},
+-};
+-
+-static const DpmClock_t VddPhyClk[]= {
+- { 540, 2600},
+- { 810, 3200},
+- { 810, 3600},
+-};
+-
+-static int rv_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
+- struct rv_voltage_dependency_table **pptable,
+- uint32_t num_entry, const DpmClock_t *pclk_dependency_table)
+-{
+- uint32_t table_size, i;
+- struct rv_voltage_dependency_table *ptable;
+-
+- table_size = sizeof(uint32_t) + sizeof(struct rv_voltage_dependency_table) * num_entry;
+- ptable = kzalloc(table_size, GFP_KERNEL);
+-
+- if (NULL == ptable)
+- return -ENOMEM;
+-
+- ptable->count = num_entry;
+-
+- for (i = 0; i < ptable->count; i++) {
+- ptable->entries[i].clk = pclk_dependency_table->Freq * 100;
+- ptable->entries[i].vol = pclk_dependency_table->Vol;
+- pclk_dependency_table++;
+- }
+-
+- *pptable = ptable;
+-
+- return 0;
+-}
+-
+-static int rv_populate_clock_table(struct pp_hwmgr *hwmgr)
+-{
+- int result;
+-
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+- DpmClocks_t *table = &(rv_data->clock_table);
+- struct rv_clock_voltage_information *pinfo = &(rv_data->clock_vol_info);
+-
+- result = smum_smc_table_manager(hwmgr, (uint8_t *)table, SMU10_CLOCKTABLE, true);
+-
+- PP_ASSERT_WITH_CODE((0 == result),
+- "Attempt to copy clock table from smc failed",
+- return result);
+-
+- if (0 == result && table->DcefClocks[0].Freq != 0) {
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
+- NUM_DCEFCLK_DPM_LEVELS,
+- &rv_data->clock_table.DcefClocks[0]);
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
+- NUM_SOCCLK_DPM_LEVELS,
+- &rv_data->clock_table.SocClocks[0]);
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
+- NUM_FCLK_DPM_LEVELS,
+- &rv_data->clock_table.FClocks[0]);
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_mclk,
+- NUM_MEMCLK_DPM_LEVELS,
+- &rv_data->clock_table.MemClocks[0]);
+- } else {
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
+- ARRAY_SIZE(VddDcfClk),
+- &VddDcfClk[0]);
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
+- ARRAY_SIZE(VddSocClk),
+- &VddSocClk[0]);
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
+- ARRAY_SIZE(VddFClk),
+- &VddFClk[0]);
+- }
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dispclk,
+- ARRAY_SIZE(VddDispClk),
+- &VddDispClk[0]);
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dppclk,
+- ARRAY_SIZE(VddDppClk), &VddDppClk[0]);
+- rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk,
+- ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]);
+-
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency);
+- result = smum_get_argument(hwmgr);
+- rv_data->gfx_min_freq_limit = result * 100;
+-
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency);
+- result = smum_get_argument(hwmgr);
+- rv_data->gfx_max_freq_limit = result * 100;
+-
+- return 0;
+-}
+-
+-static int rv_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+-{
+- int result = 0;
+- struct rv_hwmgr *data;
+-
+- data = kzalloc(sizeof(struct rv_hwmgr), GFP_KERNEL);
+- if (data == NULL)
+- return -ENOMEM;
+-
+- hwmgr->backend = data;
+-
+- result = rv_initialize_dpm_defaults(hwmgr);
+- if (result != 0) {
+- pr_err("rv_initialize_dpm_defaults failed\n");
+- return result;
+- }
+-
+- rv_populate_clock_table(hwmgr);
+-
+- result = rv_get_system_info_data(hwmgr);
+- if (result != 0) {
+- pr_err("rv_get_system_info_data failed\n");
+- return result;
+- }
+-
+- rv_construct_boot_state(hwmgr);
+-
+- hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
+- RAVEN_MAX_HARDWARE_POWERLEVELS;
+-
+- hwmgr->platform_descriptor.hardwarePerformanceLevels =
+- RAVEN_MAX_HARDWARE_POWERLEVELS;
+-
+- hwmgr->platform_descriptor.vbiosInterruptId = 0;
+-
+- hwmgr->platform_descriptor.clockStep.engineClock = 500;
+-
+- hwmgr->platform_descriptor.clockStep.memoryClock = 500;
+-
+- hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
+-
+- hwmgr->pstate_sclk = RAVEN_UMD_PSTATE_GFXCLK * 100;
+- hwmgr->pstate_mclk = RAVEN_UMD_PSTATE_FCLK * 100;
+-
+- return result;
+-}
+-
+-static int rv_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+- struct rv_clock_voltage_information *pinfo = &(rv_data->clock_vol_info);
+-
+- kfree(pinfo->vdd_dep_on_dcefclk);
+- pinfo->vdd_dep_on_dcefclk = NULL;
+- kfree(pinfo->vdd_dep_on_socclk);
+- pinfo->vdd_dep_on_socclk = NULL;
+- kfree(pinfo->vdd_dep_on_fclk);
+- pinfo->vdd_dep_on_fclk = NULL;
+- kfree(pinfo->vdd_dep_on_dispclk);
+- pinfo->vdd_dep_on_dispclk = NULL;
+- kfree(pinfo->vdd_dep_on_dppclk);
+- pinfo->vdd_dep_on_dppclk = NULL;
+- kfree(pinfo->vdd_dep_on_phyclk);
+- pinfo->vdd_dep_on_phyclk = NULL;
+-
+- kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
+- hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
+-
+- kfree(hwmgr->backend);
+- hwmgr->backend = NULL;
+-
+- return 0;
+-}
+-
+-static int rv_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
+- enum amd_dpm_forced_level level)
+-{
+- struct rv_hwmgr *data = hwmgr->backend;
+- if (hwmgr->smu_version < 0x1E3700) {
+- pr_info("smu firmware version too old, can not set dpm level\n");
+- return 0;
+- }
+-
+- switch (level) {
+- case AMD_DPM_FORCED_LEVEL_HIGH:
+- case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinGfxClk,
+- data->gfx_max_freq_limit/100);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinFclkByFreq,
+- RAVEN_UMD_PSTATE_PEAK_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinSocclkByFreq,
+- RAVEN_UMD_PSTATE_PEAK_SOCCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinVcn,
+- RAVEN_UMD_PSTATE_VCE);
+-
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxGfxClk,
+- data->gfx_max_freq_limit/100);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxFclkByFreq,
+- RAVEN_UMD_PSTATE_PEAK_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxSocclkByFreq,
+- RAVEN_UMD_PSTATE_PEAK_SOCCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxVcn,
+- RAVEN_UMD_PSTATE_VCE);
+- break;
+- case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinGfxClk,
+- data->gfx_min_freq_limit/100);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxGfxClk,
+- data->gfx_min_freq_limit/100);
+- break;
+- case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinFclkByFreq,
+- RAVEN_UMD_PSTATE_MIN_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxFclkByFreq,
+- RAVEN_UMD_PSTATE_MIN_FCLK);
+- break;
+- case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinGfxClk,
+- RAVEN_UMD_PSTATE_GFXCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinFclkByFreq,
+- RAVEN_UMD_PSTATE_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinSocclkByFreq,
+- RAVEN_UMD_PSTATE_SOCCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinVcn,
+- RAVEN_UMD_PSTATE_VCE);
+-
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxGfxClk,
+- RAVEN_UMD_PSTATE_GFXCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxFclkByFreq,
+- RAVEN_UMD_PSTATE_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxSocclkByFreq,
+- RAVEN_UMD_PSTATE_SOCCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxVcn,
+- RAVEN_UMD_PSTATE_VCE);
+- break;
+- case AMD_DPM_FORCED_LEVEL_AUTO:
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinGfxClk,
+- data->gfx_min_freq_limit/100);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinFclkByFreq,
+- RAVEN_UMD_PSTATE_MIN_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinSocclkByFreq,
+- RAVEN_UMD_PSTATE_MIN_SOCCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinVcn,
+- RAVEN_UMD_PSTATE_MIN_VCE);
+-
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxGfxClk,
+- data->gfx_max_freq_limit/100);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxFclkByFreq,
+- RAVEN_UMD_PSTATE_PEAK_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxSocclkByFreq,
+- RAVEN_UMD_PSTATE_PEAK_SOCCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxVcn,
+- RAVEN_UMD_PSTATE_VCE);
+- break;
+- case AMD_DPM_FORCED_LEVEL_LOW:
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinGfxClk,
+- data->gfx_min_freq_limit/100);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxGfxClk,
+- data->gfx_min_freq_limit/100);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetHardMinFclkByFreq,
+- RAVEN_UMD_PSTATE_MIN_FCLK);
+- smum_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetSoftMaxFclkByFreq,
+- RAVEN_UMD_PSTATE_MIN_FCLK);
+- break;
+- case AMD_DPM_FORCED_LEVEL_MANUAL:
+- case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
+- default:
+- break;
+- }
+- return 0;
+-}
+-
+-static uint32_t rv_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
+-{
+- struct rv_hwmgr *data;
+-
+- if (hwmgr == NULL)
+- return -EINVAL;
+-
+- data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- if (low)
+- return data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
+- else
+- return data->clock_vol_info.vdd_dep_on_fclk->entries[
+- data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
+-}
+-
+-static uint32_t rv_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
+-{
+- struct rv_hwmgr *data;
+-
+- if (hwmgr == NULL)
+- return -EINVAL;
+-
+- data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- if (low)
+- return data->gfx_min_freq_limit;
+- else
+- return data->gfx_max_freq_limit;
+-}
+-
+-static int rv_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
+- struct pp_hw_power_state *hw_ps)
+-{
+- return 0;
+-}
+-
+-static int rv_dpm_get_pp_table_entry_callback(
+- struct pp_hwmgr *hwmgr,
+- struct pp_hw_power_state *hw_ps,
+- unsigned int index,
+- const void *clock_info)
+-{
+- struct rv_power_state *rv_ps = cast_rv_ps(hw_ps);
+-
+- rv_ps->levels[index].engine_clock = 0;
+-
+- rv_ps->levels[index].vddc_index = 0;
+- rv_ps->level = index + 1;
+-
+- if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
+- rv_ps->levels[index].ds_divider_index = 5;
+- rv_ps->levels[index].ss_divider_index = 5;
+- }
+-
+- return 0;
+-}
+-
+-static int rv_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr)
+-{
+- int result;
+- unsigned long ret = 0;
+-
+- result = pp_tables_get_num_of_entries(hwmgr, &ret);
+-
+- return result ? 0 : ret;
+-}
+-
+-static int rv_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr,
+- unsigned long entry, struct pp_power_state *ps)
+-{
+- int result;
+- struct rv_power_state *rv_ps;
+-
+- ps->hardware.magic = PhwRaven_Magic;
+-
+- rv_ps = cast_rv_ps(&(ps->hardware));
+-
+- result = pp_tables_get_entry(hwmgr, entry, ps,
+- rv_dpm_get_pp_table_entry_callback);
+-
+- rv_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK;
+- rv_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK;
+-
+- return result;
+-}
+-
+-static int rv_get_power_state_size(struct pp_hwmgr *hwmgr)
+-{
+- return sizeof(struct rv_power_state);
+-}
+-
+-static int rv_set_cpu_power_state(struct pp_hwmgr *hwmgr)
+-{
+- return 0;
+-}
+-
+-
+-static int rv_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time,
+- bool cc6_disable, bool pstate_disable, bool pstate_switch_disable)
+-{
+- return 0;
+-}
+-
+-static int rv_get_dal_power_level(struct pp_hwmgr *hwmgr,
+- struct amd_pp_simple_clock_info *info)
+-{
+- return -EINVAL;
+-}
+-
+-static int rv_force_clock_level(struct pp_hwmgr *hwmgr,
+- enum pp_clock_type type, uint32_t mask)
+-{
+- return 0;
+-}
+-
+-static int rv_print_clock_levels(struct pp_hwmgr *hwmgr,
+- enum pp_clock_type type, char *buf)
+-{
+- struct rv_hwmgr *data = (struct rv_hwmgr *)(hwmgr->backend);
+- struct rv_voltage_dependency_table *mclk_table =
+- data->clock_vol_info.vdd_dep_on_fclk;
+- uint32_t i, now, size = 0;
+-
+- switch (type) {
+- case PP_SCLK:
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency);
+- now = smum_get_argument(hwmgr);
+-
+- size += sprintf(buf + size, "0: %uMhz %s\n",
+- data->gfx_min_freq_limit / 100,
+- ((data->gfx_min_freq_limit / 100)
+- == now) ? "*" : "");
+- size += sprintf(buf + size, "1: %uMhz %s\n",
+- data->gfx_max_freq_limit / 100,
+- ((data->gfx_max_freq_limit / 100)
+- == now) ? "*" : "");
+- break;
+- case PP_MCLK:
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency);
+- now = smum_get_argument(hwmgr);
+-
+- for (i = 0; i < mclk_table->count; i++)
+- size += sprintf(buf + size, "%d: %uMhz %s\n",
+- i,
+- mclk_table->entries[i].clk / 100,
+- ((mclk_table->entries[i].clk / 100)
+- == now) ? "*" : "");
+- break;
+- default:
+- break;
+- }
+-
+- return size;
+-}
+-
+-static int rv_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
+- PHM_PerformanceLevelDesignation designation, uint32_t index,
+- PHM_PerformanceLevel *level)
+-{
+- struct rv_hwmgr *data;
+-
+- if (level == NULL || hwmgr == NULL || state == NULL)
+- return -EINVAL;
+-
+- data = (struct rv_hwmgr *)(hwmgr->backend);
+-
+- if (index == 0) {
+- level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
+- level->coreClock = data->gfx_min_freq_limit;
+- } else {
+- level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[
+- data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
+- level->coreClock = data->gfx_max_freq_limit;
+- }
+-
+- level->nonLocalMemoryFreq = 0;
+- level->nonLocalMemoryWidth = 0;
+-
+- return 0;
+-}
+-
+-static int rv_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr,
+- const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
+-{
+- const struct rv_power_state *ps = cast_const_rv_ps(state);
+-
+- clock_info->min_eng_clk = ps->levels[0].engine_clock / (1 << (ps->levels[0].ss_divider_index));
+- clock_info->max_eng_clk = ps->levels[ps->level - 1].engine_clock / (1 << (ps->levels[ps->level - 1].ss_divider_index));
+-
+- return 0;
+-}
+-
+-#define MEM_FREQ_LOW_LATENCY 25000
+-#define MEM_FREQ_HIGH_LATENCY 80000
+-#define MEM_LATENCY_HIGH 245
+-#define MEM_LATENCY_LOW 35
+-#define MEM_LATENCY_ERR 0xFFFF
+-
+-
+-static uint32_t rv_get_mem_latency(struct pp_hwmgr *hwmgr,
+- uint32_t clock)
+-{
+- if (clock >= MEM_FREQ_LOW_LATENCY &&
+- clock < MEM_FREQ_HIGH_LATENCY)
+- return MEM_LATENCY_HIGH;
+- else if (clock >= MEM_FREQ_HIGH_LATENCY)
+- return MEM_LATENCY_LOW;
+- else
+- return MEM_LATENCY_ERR;
+-}
+-
+-static int rv_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
+- enum amd_pp_clock_type type,
+- struct pp_clock_levels_with_latency *clocks)
+-{
+- uint32_t i;
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+- struct rv_clock_voltage_information *pinfo = &(rv_data->clock_vol_info);
+- struct rv_voltage_dependency_table *pclk_vol_table;
+- bool latency_required = false;
+-
+- if (pinfo == NULL)
+- return -EINVAL;
+-
+- switch (type) {
+- case amd_pp_mem_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_mclk;
+- latency_required = true;
+- break;
+- case amd_pp_f_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_fclk;
+- latency_required = true;
+- break;
+- case amd_pp_dcf_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
+- break;
+- case amd_pp_disp_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_dispclk;
+- break;
+- case amd_pp_phy_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_phyclk;
+- break;
+- case amd_pp_dpp_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_dppclk;
+- default:
+- return -EINVAL;
+- }
+-
+- if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
+- return -EINVAL;
+-
+- clocks->num_levels = 0;
+- for (i = 0; i < pclk_vol_table->count; i++) {
+- clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk;
+- clocks->data[i].latency_in_us = latency_required ?
+- rv_get_mem_latency(hwmgr,
+- pclk_vol_table->entries[i].clk) :
+- 0;
+- clocks->num_levels++;
+- }
+-
+- return 0;
+-}
+-
+-static int rv_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
+- enum amd_pp_clock_type type,
+- struct pp_clock_levels_with_voltage *clocks)
+-{
+- uint32_t i;
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+- struct rv_clock_voltage_information *pinfo = &(rv_data->clock_vol_info);
+- struct rv_voltage_dependency_table *pclk_vol_table = NULL;
+-
+- if (pinfo == NULL)
+- return -EINVAL;
+-
+- switch (type) {
+- case amd_pp_mem_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_mclk;
+- break;
+- case amd_pp_f_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_fclk;
+- break;
+- case amd_pp_dcf_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
+- break;
+- case amd_pp_soc_clock:
+- pclk_vol_table = pinfo->vdd_dep_on_socclk;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
+- return -EINVAL;
+-
+- clocks->num_levels = 0;
+- for (i = 0; i < pclk_vol_table->count; i++) {
+- clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk;
+- clocks->data[i].voltage_in_mv = pclk_vol_table->entries[i].vol;
+- clocks->num_levels++;
+- }
+-
+- return 0;
+-}
+-
+-int rv_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
+- struct pp_display_clock_request *clock_req)
+-{
+- struct rv_hwmgr *rv_data = (struct rv_hwmgr *)(hwmgr->backend);
+- enum amd_pp_clock_type clk_type = clock_req->clock_type;
+- uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+- PPSMC_Msg msg;
+-
+- switch (clk_type) {
+- case amd_pp_dcf_clock:
+- if (clk_freq == rv_data->dcf_actual_hard_min_freq)
+- return 0;
+- msg = PPSMC_MSG_SetHardMinDcefclkByFreq;
+- rv_data->dcf_actual_hard_min_freq = clk_freq;
+- break;
+- case amd_pp_soc_clock:
+- msg = PPSMC_MSG_SetHardMinSocclkByFreq;
+- break;
+- case amd_pp_f_clock:
+- if (clk_freq == rv_data->f_actual_hard_min_freq)
+- return 0;
+- rv_data->f_actual_hard_min_freq = clk_freq;
+- msg = PPSMC_MSG_SetHardMinFclkByFreq;
+- break;
+- default:
+- pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
+- return -EINVAL;
+- }
+-
+- smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq);
+-
+- return 0;
+-}
+-
+-static int rv_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
+-{
+- clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */
+- return 0;
+-}
+-
+-static int rv_thermal_get_temperature(struct pp_hwmgr *hwmgr)
+-{
+- uint32_t reg_offset = soc15_get_register_offset(THM_HWID, 0,
+- mmTHM_TCON_CUR_TMP_BASE_IDX, mmTHM_TCON_CUR_TMP);
+- uint32_t reg_value = cgs_read_register(hwmgr->device, reg_offset);
+- int cur_temp =
+- (reg_value & THM_TCON_CUR_TMP__CUR_TEMP_MASK) >> THM_TCON_CUR_TMP__CUR_TEMP__SHIFT;
+-
+- if (cur_temp & THM_TCON_CUR_TMP__CUR_TEMP_RANGE_SEL_MASK)
+- cur_temp = ((cur_temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+- else
+- cur_temp = (cur_temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+-
+- return cur_temp;
+-}
+-
+-static int rv_read_sensor(struct pp_hwmgr *hwmgr, int idx,
+- void *value, int *size)
+-{
+- uint32_t sclk, mclk;
+- int ret = 0;
+-
+- switch (idx) {
+- case AMDGPU_PP_SENSOR_GFX_SCLK:
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency);
+- sclk = smum_get_argument(hwmgr);
+- /* in units of 10KHZ */
+- *((uint32_t *)value) = sclk * 100;
+- *size = 4;
+- break;
+- case AMDGPU_PP_SENSOR_GFX_MCLK:
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency);
+- mclk = smum_get_argument(hwmgr);
+- /* in units of 10KHZ */
+- *((uint32_t *)value) = mclk * 100;
+- *size = 4;
+- break;
+- case AMDGPU_PP_SENSOR_GPU_TEMP:
+- *((uint32_t *)value) = rv_thermal_get_temperature(hwmgr);
+- break;
+- default:
+- ret = -EINVAL;
+- break;
+- }
+-
+- return ret;
+-}
+-
+-static int rv_set_mmhub_powergating_by_smu(struct pp_hwmgr *hwmgr)
+-{
+- return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub);
+-}
+-
+-static const struct pp_hwmgr_func rv_hwmgr_funcs = {
+- .backend_init = rv_hwmgr_backend_init,
+- .backend_fini = rv_hwmgr_backend_fini,
+- .asic_setup = NULL,
+- .apply_state_adjust_rules = rv_apply_state_adjust_rules,
+- .force_dpm_level = rv_dpm_force_dpm_level,
+- .get_power_state_size = rv_get_power_state_size,
+- .powerdown_uvd = NULL,
+- .powergate_uvd = NULL,
+- .powergate_vce = NULL,
+- .get_mclk = rv_dpm_get_mclk,
+- .get_sclk = rv_dpm_get_sclk,
+- .patch_boot_state = rv_dpm_patch_boot_state,
+- .get_pp_table_entry = rv_dpm_get_pp_table_entry,
+- .get_num_of_pp_table_entries = rv_dpm_get_num_of_pp_table_entries,
+- .set_cpu_power_state = rv_set_cpu_power_state,
+- .store_cc6_data = rv_store_cc6_data,
+- .force_clock_level = rv_force_clock_level,
+- .print_clock_levels = rv_print_clock_levels,
+- .get_dal_power_level = rv_get_dal_power_level,
+- .get_performance_level = rv_get_performance_level,
+- .get_current_shallow_sleep_clocks = rv_get_current_shallow_sleep_clocks,
+- .get_clock_by_type_with_latency = rv_get_clock_by_type_with_latency,
+- .get_clock_by_type_with_voltage = rv_get_clock_by_type_with_voltage,
+- .get_max_high_clocks = rv_get_max_high_clocks,
+- .read_sensor = rv_read_sensor,
+- .set_active_display_count = rv_set_active_display_count,
+- .set_deep_sleep_dcefclk = rv_set_deep_sleep_dcefclk,
+- .dynamic_state_management_enable = rv_enable_dpm_tasks,
+- .power_off_asic = rv_power_off_asic,
+- .asic_setup = rv_setup_asic_task,
+- .power_state_set = rv_set_power_state_tasks,
+- .dynamic_state_management_disable = rv_disable_dpm_tasks,
+- .set_mmhub_powergating_by_smu = rv_set_mmhub_powergating_by_smu,
+-};
+-
+-int rv_init_function_pointers(struct pp_hwmgr *hwmgr)
+-{
+- hwmgr->hwmgr_func = &rv_hwmgr_funcs;
+- hwmgr->pptable_func = &pptable_funcs;
+- return 0;
+-}
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h
+deleted file mode 100644
+index 29afa5c..0000000
+--- a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h
++++ /dev/null
+@@ -1,320 +0,0 @@
+-/*
+- * Copyright 2017 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 RAVEN_HWMGR_H
+-#define RAVEN_HWMGR_H
+-
+-#include "hwmgr.h"
+-#include "rv_inc.h"
+-#include "smu10_driver_if.h"
+-#include "rv_ppsmc.h"
+-
+-
+-#define RAVEN_MAX_HARDWARE_POWERLEVELS 8
+-#define PHMRAVEN_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15
+-
+-#define DPMFlags_SCLK_Enabled 0x00000001
+-#define DPMFlags_UVD_Enabled 0x00000002
+-#define DPMFlags_VCE_Enabled 0x00000004
+-#define DPMFlags_ACP_Enabled 0x00000008
+-#define DPMFlags_ForceHighestValid 0x40000000
+-
+-/* Do not change the following, it is also defined in SMU8.h */
+-#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001
+-#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000
+-#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x01000000
+-#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x02000000
+-
+-#define SMU_PHYID_SHIFT 8
+-
+-#define RAVEN_PCIE_POWERGATING_TARGET_GFX 0
+-#define RAVEN_PCIE_POWERGATING_TARGET_DDI 1
+-#define RAVEN_PCIE_POWERGATING_TARGET_PLLCASCADE 2
+-#define RAVEN_PCIE_POWERGATING_TARGET_PHY 3
+-
+-enum VQ_TYPE {
+- CLOCK_TYPE_DCLK = 0L,
+- CLOCK_TYPE_ECLK,
+- CLOCK_TYPE_SCLK,
+- CLOCK_TYPE_CCLK,
+- VQ_GFX_CU
+-};
+-
+-#define SUSTAINABLE_SCLK_MASK 0x00ffffff
+-#define SUSTAINABLE_SCLK_SHIFT 0
+-#define SUSTAINABLE_CU_MASK 0xff000000
+-#define SUSTAINABLE_CU_SHIFT 24
+-
+-struct rv_dpm_entry {
+- uint32_t soft_min_clk;
+- uint32_t hard_min_clk;
+- uint32_t soft_max_clk;
+- uint32_t hard_max_clk;
+-};
+-
+-struct rv_power_level {
+- uint32_t engine_clock;
+- uint8_t vddc_index;
+- uint8_t ds_divider_index;
+- uint8_t ss_divider_index;
+- uint8_t allow_gnb_slow;
+- uint8_t force_nbp_state;
+- uint8_t display_wm;
+- uint8_t vce_wm;
+- uint8_t num_simd_to_powerdown;
+- uint8_t hysteresis_up;
+- uint8_t rsv[3];
+-};
+-
+-/*used for the nbpsFlags field in rv_power state*/
+-#define RAVEN_POWERSTATE_FLAGS_NBPS_FORCEHIGH (1<<0)
+-#define RAVEN_POWERSTATE_FLAGS_NBPS_LOCKTOHIGH (1<<1)
+-#define RAVEN_POWERSTATE_FLAGS_NBPS_LOCKTOLOW (1<<2)
+-
+-#define RAVEN_POWERSTATE_FLAGS_BAPM_DISABLE (1<<0)
+-
+-struct rv_uvd_clocks {
+- uint32_t vclk;
+- uint32_t dclk;
+- uint32_t vclk_low_divider;
+- uint32_t vclk_high_divider;
+- uint32_t dclk_low_divider;
+- uint32_t dclk_high_divider;
+-};
+-
+-struct pp_disable_nbpslo_flags {
+- union {
+- struct {
+- uint32_t entry : 1;
+- uint32_t display : 1;
+- uint32_t driver: 1;
+- uint32_t vce : 1;
+- uint32_t uvd : 1;
+- uint32_t acp : 1;
+- uint32_t reserved: 26;
+- } bits;
+- uint32_t u32All;
+- };
+-};
+-
+-
+-enum rv_pstate_previous_action {
+- DO_NOTHING = 1,
+- FORCE_HIGH,
+- CANCEL_FORCE_HIGH
+-};
+-
+-struct rv_power_state {
+- unsigned int magic;
+- uint32_t level;
+- struct rv_uvd_clocks uvd_clocks;
+- uint32_t evclk;
+- uint32_t ecclk;
+- uint32_t samclk;
+- uint32_t acpclk;
+- bool need_dfs_bypass;
+-
+- uint32_t nbps_flags;
+- uint32_t bapm_flags;
+- uint8_t dpm0_pg_nbps_low;
+- uint8_t dpm0_pg_nbps_high;
+- uint8_t dpm_x_nbps_low;
+- uint8_t dpm_x_nbps_high;
+-
+- enum rv_pstate_previous_action action;
+-
+- struct rv_power_level levels[RAVEN_MAX_HARDWARE_POWERLEVELS];
+- struct pp_disable_nbpslo_flags nbpslo_flags;
+-};
+-
+-#define RAVEN_NUM_NBPSTATES 4
+-#define RAVEN_NUM_NBPMEMORYCLOCK 2
+-
+-
+-struct rv_display_phy_info_entry {
+- uint8_t phy_present;
+- uint8_t active_lane_mapping;
+- uint8_t display_config_type;
+- uint8_t active_num_of_lanes;
+-};
+-
+-#define RAVEN_MAX_DISPLAYPHY_IDS 10
+-
+-struct rv_display_phy_info {
+- bool display_phy_access_initialized;
+- struct rv_display_phy_info_entry entries[RAVEN_MAX_DISPLAYPHY_IDS];
+-};
+-
+-#define MAX_DISPLAY_CLOCK_LEVEL 8
+-
+-struct rv_system_info{
+- uint8_t htc_tmp_lmt;
+- uint8_t htc_hyst_lmt;
+-};
+-
+-#define MAX_REGULAR_DPM_NUMBER 8
+-
+-struct rv_mclk_latency_entries {
+- uint32_t frequency;
+- uint32_t latency;
+-};
+-
+-struct rv_mclk_latency_table {
+- uint32_t count;
+- struct rv_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER];
+-};
+-
+-struct rv_clock_voltage_dependency_record {
+- uint32_t clk;
+- uint32_t vol;
+-};
+-
+-
+-struct rv_voltage_dependency_table {
+- uint32_t count;
+- struct rv_clock_voltage_dependency_record entries[1];
+-};
+-
+-struct rv_clock_voltage_information {
+- struct rv_voltage_dependency_table *vdd_dep_on_dcefclk;
+- struct rv_voltage_dependency_table *vdd_dep_on_socclk;
+- struct rv_voltage_dependency_table *vdd_dep_on_fclk;
+- struct rv_voltage_dependency_table *vdd_dep_on_mclk;
+- struct rv_voltage_dependency_table *vdd_dep_on_dispclk;
+- struct rv_voltage_dependency_table *vdd_dep_on_dppclk;
+- struct rv_voltage_dependency_table *vdd_dep_on_phyclk;
+-};
+-
+-struct rv_hwmgr {
+- uint32_t disable_driver_thermal_policy;
+- uint32_t thermal_auto_throttling_treshold;
+- struct rv_system_info sys_info;
+- struct rv_mclk_latency_table mclk_latency_table;
+-
+- uint32_t ddi_power_gating_disabled;
+-
+- struct rv_display_phy_info_entry display_phy_info;
+- uint32_t dce_slow_sclk_threshold;
+-
+- bool disp_clk_bypass;
+- bool disp_clk_bypass_pending;
+- uint32_t bapm_enabled;
+-
+- bool video_start;
+- bool battery_state;
+-
+- uint32_t is_nb_dpm_enabled;
+- uint32_t is_voltage_island_enabled;
+- uint32_t disable_smu_acp_s3_handshake;
+- uint32_t disable_notify_smu_vpu_recovery;
+- bool in_vpu_recovery;
+- bool pg_acp_init;
+- uint8_t disp_config;
+-
+- /* PowerTune */
+- uint32_t power_containment_features;
+- bool cac_enabled;
+- bool disable_uvd_power_tune_feature;
+- bool enable_bapm_feature;
+- bool enable_tdc_limit_feature;
+-
+-
+- /* SMC SRAM Address of firmware header tables */
+- uint32_t sram_end;
+- uint32_t dpm_table_start;
+- uint32_t soft_regs_start;
+-
+- /* start of SMU7_Fusion_DpmTable */
+-
+- uint8_t uvd_level_count;
+- uint8_t vce_level_count;
+- uint8_t acp_level_count;
+- uint8_t samu_level_count;
+-
+- uint32_t fps_high_threshold;
+- uint32_t fps_low_threshold;
+-
+- uint32_t dpm_flags;
+- struct rv_dpm_entry sclk_dpm;
+- struct rv_dpm_entry uvd_dpm;
+- struct rv_dpm_entry vce_dpm;
+- struct rv_dpm_entry acp_dpm;
+- bool acp_power_up_no_dsp;
+-
+- uint32_t max_sclk_level;
+- uint32_t num_of_clk_entries;
+-
+- /* CPU Power State */
+- uint32_t separation_time;
+- bool cc6_disable;
+- bool pstate_disable;
+- bool cc6_setting_changed;
+-
+- uint32_t ulTotalActiveCUs;
+-
+- bool isp_tileA_power_gated;
+- bool isp_tileB_power_gated;
+- uint32_t isp_actual_hard_min_freq;
+- uint32_t soc_actual_hard_min_freq;
+- uint32_t dcf_actual_hard_min_freq;
+-
+- uint32_t f_actual_hard_min_freq;
+- uint32_t fabric_actual_soft_min_freq;
+- uint32_t vclk_soft_min;
+- uint32_t dclk_soft_min;
+- uint32_t gfx_actual_soft_min_freq;
+- uint32_t gfx_min_freq_limit;
+- uint32_t gfx_max_freq_limit;
+-
+- bool vcn_power_gated;
+- bool vcn_dpg_mode;
+-
+- bool gfx_off_controled_by_driver;
+- Watermarks_t water_marks_table;
+- struct rv_clock_voltage_information clock_vol_info;
+- DpmClocks_t clock_table;
+-
+- uint32_t active_process_mask;
+- bool need_min_deep_sleep_dcefclk;
+- uint32_t deep_sleep_dcefclk;
+- uint32_t num_active_display;
+-};
+-
+-struct pp_hwmgr;
+-
+-int rv_init_function_pointers(struct pp_hwmgr *hwmgr);
+-
+-/* UMD PState Raven Msg Parameters in MHz */
+-#define RAVEN_UMD_PSTATE_GFXCLK 700
+-#define RAVEN_UMD_PSTATE_SOCCLK 626
+-#define RAVEN_UMD_PSTATE_FCLK 933
+-#define RAVEN_UMD_PSTATE_VCE 0x03C00320
+-
+-#define RAVEN_UMD_PSTATE_PEAK_SOCCLK 757
+-#define RAVEN_UMD_PSTATE_PEAK_FCLK 1200
+-
+-#define RAVEN_UMD_PSTATE_MIN_FCLK 400
+-#define RAVEN_UMD_PSTATE_MIN_SOCCLK 200
+-#define RAVEN_UMD_PSTATE_MIN_VCE 0x0190012C
+-
+-#endif
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_inc.h b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_inc.h
+deleted file mode 100644
+index ae59a3f..0000000
+--- a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_inc.h
++++ /dev/null
+@@ -1,43 +0,0 @@
+-/*
+- * Copyright 2016 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 RAVEN_INC_H
+-#define RAVEN_INC_H
+-
+-
+-#include "asic_reg/mp/mp_10_0_default.h"
+-#include "asic_reg/mp/mp_10_0_offset.h"
+-#include "asic_reg/mp/mp_10_0_sh_mask.h"
+-
+-#include "asic_reg/nbio/nbio_7_0_default.h"
+-#include "asic_reg/nbio/nbio_7_0_offset.h"
+-#include "asic_reg/nbio/nbio_7_0_sh_mask.h"
+-
+-#include "asic_reg/thm/thm_10_0_default.h"
+-#include "asic_reg/thm/thm_10_0_offset.h"
+-#include "asic_reg/thm/thm_10_0_sh_mask.h"
+-
+-
+-#define ixDDI_PHY_GEN_STATUS 0x3FCE8
+-
+-#endif
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+new file mode 100644
+index 0000000..10253b8
+--- /dev/null
++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+@@ -0,0 +1,1042 @@
++/*
++ * 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 "pp_debug.h"
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include "atom-types.h"
++#include "atombios.h"
++#include "processpptables.h"
++#include "cgs_common.h"
++#include "smumgr.h"
++#include "hwmgr.h"
++#include "hardwaremanager.h"
++#include "rv_ppsmc.h"
++#include "smu10_hwmgr.h"
++#include "power_state.h"
++#include "pp_soc15.h"
++
++#define SMU10_MAX_DEEPSLEEP_DIVIDER_ID 5
++#define SMU10_MINIMUM_ENGINE_CLOCK 800 /* 8Mhz, the low boundary of engine clock allowed on this chip */
++#define SCLK_MIN_DIV_INTV_SHIFT 12
++#define SMU10_DISPCLK_BYPASS_THRESHOLD 10000 /* 100Mhz */
++#define SMC_RAM_END 0x40000
++
++static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic;
++
++
++static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
++ struct pp_display_clock_request *clock_req);
++
++
++static struct smu10_power_state *cast_smu10_ps(struct pp_hw_power_state *hw_ps)
++{
++ if (SMU10_Magic != hw_ps->magic)
++ return NULL;
++
++ return (struct smu10_power_state *)hw_ps;
++}
++
++static const struct smu10_power_state *cast_const_smu10_ps(
++ const struct pp_hw_power_state *hw_ps)
++{
++ if (SMU10_Magic != hw_ps->magic)
++ return NULL;
++
++ return (struct smu10_power_state *)hw_ps;
++}
++
++static int smu10_initialize_dpm_defaults(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ smu10_data->dce_slow_sclk_threshold = 30000;
++ smu10_data->thermal_auto_throttling_treshold = 0;
++ smu10_data->is_nb_dpm_enabled = 1;
++ smu10_data->dpm_flags = 1;
++ smu10_data->gfx_off_controled_by_driver = false;
++ smu10_data->need_min_deep_sleep_dcefclk = true;
++ smu10_data->num_active_display = 0;
++ smu10_data->deep_sleep_dcefclk = 0;
++
++ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
++ PHM_PlatformCaps_SclkDeepSleep);
++
++ phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
++ PHM_PlatformCaps_SclkThrottleLowNotification);
++
++ phm_cap_set(hwmgr->platform_descriptor.platformCaps,
++ PHM_PlatformCaps_PowerPlaySupport);
++ return 0;
++}
++
++static int smu10_construct_max_power_limits_table(struct pp_hwmgr *hwmgr,
++ struct phm_clock_and_voltage_limits *table)
++{
++ return 0;
++}
++
++static int smu10_init_dynamic_state_adjustment_rule_settings(
++ struct pp_hwmgr *hwmgr)
++{
++ uint32_t table_size =
++ sizeof(struct phm_clock_voltage_dependency_table) +
++ (7 * sizeof(struct phm_clock_voltage_dependency_record));
++
++ struct phm_clock_voltage_dependency_table *table_clk_vlt =
++ kzalloc(table_size, GFP_KERNEL);
++
++ if (NULL == table_clk_vlt) {
++ pr_err("Can not allocate memory!\n");
++ return -ENOMEM;
++ }
++
++ table_clk_vlt->count = 8;
++ table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0;
++ table_clk_vlt->entries[0].v = 0;
++ table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1;
++ table_clk_vlt->entries[1].v = 1;
++ table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2;
++ table_clk_vlt->entries[2].v = 2;
++ table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3;
++ table_clk_vlt->entries[3].v = 3;
++ table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4;
++ table_clk_vlt->entries[4].v = 4;
++ table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5;
++ table_clk_vlt->entries[5].v = 5;
++ table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6;
++ table_clk_vlt->entries[6].v = 6;
++ table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7;
++ table_clk_vlt->entries[7].v = 7;
++ hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt;
++
++ return 0;
++}
++
++static int smu10_get_system_info_data(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)hwmgr->backend;
++
++ smu10_data->sys_info.htc_hyst_lmt = 5;
++ smu10_data->sys_info.htc_tmp_lmt = 203;
++
++ if (smu10_data->thermal_auto_throttling_treshold == 0)
++ smu10_data->thermal_auto_throttling_treshold = 203;
++
++ smu10_construct_max_power_limits_table (hwmgr,
++ &hwmgr->dyn_state.max_clock_voltage_on_ac);
++
++ smu10_init_dynamic_state_adjustment_rule_settings(hwmgr);
++
++ return 0;
++}
++
++static int smu10_construct_boot_state(struct pp_hwmgr *hwmgr)
++{
++ return 0;
++}
++
++static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input)
++{
++ struct PP_Clocks clocks = {0};
++ struct pp_display_clock_request clock_req;
++
++ clocks.dcefClock = hwmgr->display_config.min_dcef_set_clk;
++ clock_req.clock_type = amd_pp_dcf_clock;
++ clock_req.clock_freq_in_khz = clocks.dcefClock * 10;
++
++ PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, &clock_req),
++ "Attempt to set DCF Clock Failed!", return -EINVAL);
++
++ return 0;
++}
++
++static int smu10_set_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ if (smu10_data->need_min_deep_sleep_dcefclk && smu10_data->deep_sleep_dcefclk != clock/100) {
++ smu10_data->deep_sleep_dcefclk = clock/100;
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetMinDeepSleepDcefclk,
++ smu10_data->deep_sleep_dcefclk);
++ }
++ return 0;
++}
++
++static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ if (smu10_data->num_active_display != count) {
++ smu10_data->num_active_display = count;
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetDisplayCount,
++ smu10_data->num_active_display);
++ }
++
++ return 0;
++}
++
++static int smu10_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input)
++{
++ return smu10_set_clock_limit(hwmgr, input);
++}
++
++static int smu10_init_power_gate_state(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ smu10_data->vcn_power_gated = true;
++ smu10_data->isp_tileA_power_gated = true;
++ smu10_data->isp_tileB_power_gated = true;
++
++ return 0;
++}
++
++
++static int smu10_setup_asic_task(struct pp_hwmgr *hwmgr)
++{
++ return smu10_init_power_gate_state(hwmgr);
++}
++
++static int smu10_reset_cc6_data(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ smu10_data->separation_time = 0;
++ smu10_data->cc6_disable = false;
++ smu10_data->pstate_disable = false;
++ smu10_data->cc6_setting_changed = false;
++
++ return 0;
++}
++
++static int smu10_power_off_asic(struct pp_hwmgr *hwmgr)
++{
++ return smu10_reset_cc6_data(hwmgr);
++}
++
++static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ if (smu10_data->gfx_off_controled_by_driver)
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff);
++
++ return 0;
++}
++
++static int smu10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
++{
++ return smu10_disable_gfx_off(hwmgr);
++}
++
++static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ if (smu10_data->gfx_off_controled_by_driver)
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff);
++
++ return 0;
++}
++
++static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
++{
++ return smu10_enable_gfx_off(hwmgr);
++}
++
++static int smu10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
++ struct pp_power_state *prequest_ps,
++ const struct pp_power_state *pcurrent_ps)
++{
++ return 0;
++}
++
++/* temporary hardcoded clock voltage breakdown tables */
++static const DpmClock_t VddDcfClk[]= {
++ { 300, 2600},
++ { 600, 3200},
++ { 600, 3600},
++};
++
++static const DpmClock_t VddSocClk[]= {
++ { 478, 2600},
++ { 722, 3200},
++ { 722, 3600},
++};
++
++static const DpmClock_t VddFClk[]= {
++ { 400, 2600},
++ {1200, 3200},
++ {1200, 3600},
++};
++
++static const DpmClock_t VddDispClk[]= {
++ { 435, 2600},
++ { 661, 3200},
++ {1086, 3600},
++};
++
++static const DpmClock_t VddDppClk[]= {
++ { 435, 2600},
++ { 661, 3200},
++ { 661, 3600},
++};
++
++static const DpmClock_t VddPhyClk[]= {
++ { 540, 2600},
++ { 810, 3200},
++ { 810, 3600},
++};
++
++static int smu10_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,
++ struct smu10_voltage_dependency_table **pptable,
++ uint32_t num_entry, const DpmClock_t *pclk_dependency_table)
++{
++ uint32_t table_size, i;
++ struct smu10_voltage_dependency_table *ptable;
++
++ table_size = sizeof(uint32_t) + sizeof(struct smu10_voltage_dependency_table) * num_entry;
++ ptable = kzalloc(table_size, GFP_KERNEL);
++
++ if (NULL == ptable)
++ return -ENOMEM;
++
++ ptable->count = num_entry;
++
++ for (i = 0; i < ptable->count; i++) {
++ ptable->entries[i].clk = pclk_dependency_table->Freq * 100;
++ ptable->entries[i].vol = pclk_dependency_table->Vol;
++ pclk_dependency_table++;
++ }
++
++ *pptable = ptable;
++
++ return 0;
++}
++
++
++static int smu10_populate_clock_table(struct pp_hwmgr *hwmgr)
++{
++ int result;
++
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++ DpmClocks_t *table = &(smu10_data->clock_table);
++ struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
++
++ result = smum_smc_table_manager(hwmgr, (uint8_t *)table, SMU10_CLOCKTABLE, true);
++
++ PP_ASSERT_WITH_CODE((0 == result),
++ "Attempt to copy clock table from smc failed",
++ return result);
++
++ if (0 == result && table->DcefClocks[0].Freq != 0) {
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
++ NUM_DCEFCLK_DPM_LEVELS,
++ &smu10_data->clock_table.DcefClocks[0]);
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
++ NUM_SOCCLK_DPM_LEVELS,
++ &smu10_data->clock_table.SocClocks[0]);
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
++ NUM_FCLK_DPM_LEVELS,
++ &smu10_data->clock_table.FClocks[0]);
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_mclk,
++ NUM_MEMCLK_DPM_LEVELS,
++ &smu10_data->clock_table.MemClocks[0]);
++ } else {
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk,
++ ARRAY_SIZE(VddDcfClk),
++ &VddDcfClk[0]);
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk,
++ ARRAY_SIZE(VddSocClk),
++ &VddSocClk[0]);
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk,
++ ARRAY_SIZE(VddFClk),
++ &VddFClk[0]);
++ }
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dispclk,
++ ARRAY_SIZE(VddDispClk),
++ &VddDispClk[0]);
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dppclk,
++ ARRAY_SIZE(VddDppClk), &VddDppClk[0]);
++ smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk,
++ ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]);
++
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency);
++ result = smum_get_argument(hwmgr);
++ smu10_data->gfx_min_freq_limit = result * 100;
++
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency);
++ result = smum_get_argument(hwmgr);
++ smu10_data->gfx_max_freq_limit = result * 100;
++
++ return 0;
++}
++
++static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
++{
++ int result = 0;
++ struct smu10_hwmgr *data;
++
++ data = kzalloc(sizeof(struct smu10_hwmgr), GFP_KERNEL);
++ if (data == NULL)
++ return -ENOMEM;
++
++ hwmgr->backend = data;
++
++ result = smu10_initialize_dpm_defaults(hwmgr);
++ if (result != 0) {
++ pr_err("smu10_initialize_dpm_defaults failed\n");
++ return result;
++ }
++
++ smu10_populate_clock_table(hwmgr);
++
++ result = smu10_get_system_info_data(hwmgr);
++ if (result != 0) {
++ pr_err("smu10_get_system_info_data failed\n");
++ return result;
++ }
++
++ smu10_construct_boot_state(hwmgr);
++
++ hwmgr->platform_descriptor.hardwareActivityPerformanceLevels =
++ SMU10_MAX_HARDWARE_POWERLEVELS;
++
++ hwmgr->platform_descriptor.hardwarePerformanceLevels =
++ SMU10_MAX_HARDWARE_POWERLEVELS;
++
++ hwmgr->platform_descriptor.vbiosInterruptId = 0;
++
++ hwmgr->platform_descriptor.clockStep.engineClock = 500;
++
++ hwmgr->platform_descriptor.clockStep.memoryClock = 500;
++
++ hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50;
++
++ hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK;
++ hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK;
++
++ return result;
++}
++
++static int smu10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++ struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
++
++ kfree(pinfo->vdd_dep_on_dcefclk);
++ pinfo->vdd_dep_on_dcefclk = NULL;
++ kfree(pinfo->vdd_dep_on_socclk);
++ pinfo->vdd_dep_on_socclk = NULL;
++ kfree(pinfo->vdd_dep_on_fclk);
++ pinfo->vdd_dep_on_fclk = NULL;
++ kfree(pinfo->vdd_dep_on_dispclk);
++ pinfo->vdd_dep_on_dispclk = NULL;
++ kfree(pinfo->vdd_dep_on_dppclk);
++ pinfo->vdd_dep_on_dppclk = NULL;
++ kfree(pinfo->vdd_dep_on_phyclk);
++ pinfo->vdd_dep_on_phyclk = NULL;
++
++ kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl);
++ hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;
++
++ kfree(hwmgr->backend);
++ hwmgr->backend = NULL;
++
++ return 0;
++}
++
++static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
++ enum amd_dpm_forced_level level)
++{
++ if (hwmgr->smu_version < 0x1E3700) {
++ pr_info("smu firmware version too old, can not set dpm level\n");
++ return 0;
++ }
++
++ switch (level) {
++ case AMD_DPM_FORCED_LEVEL_HIGH:
++ case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinGfxClk,
++ SMU10_UMD_PSTATE_PEAK_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinFclkByFreq,
++ SMU10_UMD_PSTATE_PEAK_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinSocclkByFreq,
++ SMU10_UMD_PSTATE_PEAK_SOCCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinVcn,
++ SMU10_UMD_PSTATE_VCE);
++
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxGfxClk,
++ SMU10_UMD_PSTATE_PEAK_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxFclkByFreq,
++ SMU10_UMD_PSTATE_PEAK_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxSocclkByFreq,
++ SMU10_UMD_PSTATE_PEAK_SOCCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxVcn,
++ SMU10_UMD_PSTATE_VCE);
++ break;
++ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinGfxClk,
++ SMU10_UMD_PSTATE_MIN_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxGfxClk,
++ SMU10_UMD_PSTATE_MIN_GFXCLK);
++ break;
++ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinFclkByFreq,
++ SMU10_UMD_PSTATE_MIN_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxFclkByFreq,
++ SMU10_UMD_PSTATE_MIN_FCLK);
++ break;
++ case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinGfxClk,
++ SMU10_UMD_PSTATE_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinFclkByFreq,
++ SMU10_UMD_PSTATE_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinSocclkByFreq,
++ SMU10_UMD_PSTATE_SOCCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinVcn,
++ SMU10_UMD_PSTATE_VCE);
++
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxGfxClk,
++ SMU10_UMD_PSTATE_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxFclkByFreq,
++ SMU10_UMD_PSTATE_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxSocclkByFreq,
++ SMU10_UMD_PSTATE_SOCCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxVcn,
++ SMU10_UMD_PSTATE_VCE);
++ break;
++ case AMD_DPM_FORCED_LEVEL_AUTO:
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinGfxClk,
++ SMU10_UMD_PSTATE_MIN_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinFclkByFreq,
++ SMU10_UMD_PSTATE_MIN_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinSocclkByFreq,
++ SMU10_UMD_PSTATE_MIN_SOCCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinVcn,
++ SMU10_UMD_PSTATE_MIN_VCE);
++
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxGfxClk,
++ SMU10_UMD_PSTATE_PEAK_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxFclkByFreq,
++ SMU10_UMD_PSTATE_PEAK_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxSocclkByFreq,
++ SMU10_UMD_PSTATE_PEAK_SOCCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxVcn,
++ SMU10_UMD_PSTATE_VCE);
++ break;
++ case AMD_DPM_FORCED_LEVEL_LOW:
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinGfxClk,
++ SMU10_UMD_PSTATE_MIN_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxGfxClk,
++ SMU10_UMD_PSTATE_MIN_GFXCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetHardMinFclkByFreq,
++ SMU10_UMD_PSTATE_MIN_FCLK);
++ smum_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetSoftMaxFclkByFreq,
++ SMU10_UMD_PSTATE_MIN_FCLK);
++ break;
++ case AMD_DPM_FORCED_LEVEL_MANUAL:
++ case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
++ default:
++ break;
++ }
++ return 0;
++}
++
++static uint32_t smu10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low)
++{
++ struct smu10_hwmgr *data;
++
++ if (hwmgr == NULL)
++ return -EINVAL;
++
++ data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ if (low)
++ return data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
++ else
++ return data->clock_vol_info.vdd_dep_on_fclk->entries[
++ data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
++}
++
++static uint32_t smu10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low)
++{
++ struct smu10_hwmgr *data;
++
++ if (hwmgr == NULL)
++ return -EINVAL;
++
++ data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ if (low)
++ return data->gfx_min_freq_limit;
++ else
++ return data->gfx_max_freq_limit;
++}
++
++static int smu10_dpm_patch_boot_state(struct pp_hwmgr *hwmgr,
++ struct pp_hw_power_state *hw_ps)
++{
++ return 0;
++}
++
++static int smu10_dpm_get_pp_table_entry_callback(
++ struct pp_hwmgr *hwmgr,
++ struct pp_hw_power_state *hw_ps,
++ unsigned int index,
++ const void *clock_info)
++{
++ struct smu10_power_state *smu10_ps = cast_smu10_ps(hw_ps);
++
++ smu10_ps->levels[index].engine_clock = 0;
++
++ smu10_ps->levels[index].vddc_index = 0;
++ smu10_ps->level = index + 1;
++
++ if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) {
++ smu10_ps->levels[index].ds_divider_index = 5;
++ smu10_ps->levels[index].ss_divider_index = 5;
++ }
++
++ return 0;
++}
++
++static int smu10_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr)
++{
++ int result;
++ unsigned long ret = 0;
++
++ result = pp_tables_get_num_of_entries(hwmgr, &ret);
++
++ return result ? 0 : ret;
++}
++
++static int smu10_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr,
++ unsigned long entry, struct pp_power_state *ps)
++{
++ int result;
++ struct smu10_power_state *smu10_ps;
++
++ ps->hardware.magic = SMU10_Magic;
++
++ smu10_ps = cast_smu10_ps(&(ps->hardware));
++
++ result = pp_tables_get_entry(hwmgr, entry, ps,
++ smu10_dpm_get_pp_table_entry_callback);
++
++ smu10_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK;
++ smu10_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK;
++
++ return result;
++}
++
++static int smu10_get_power_state_size(struct pp_hwmgr *hwmgr)
++{
++ return sizeof(struct smu10_power_state);
++}
++
++static int smu10_set_cpu_power_state(struct pp_hwmgr *hwmgr)
++{
++ return 0;
++}
++
++
++static int smu10_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time,
++ bool cc6_disable, bool pstate_disable, bool pstate_switch_disable)
++{
++ return 0;
++}
++
++static int smu10_get_dal_power_level(struct pp_hwmgr *hwmgr,
++ struct amd_pp_simple_clock_info *info)
++{
++ return -EINVAL;
++}
++
++static int smu10_force_clock_level(struct pp_hwmgr *hwmgr,
++ enum pp_clock_type type, uint32_t mask)
++{
++ return 0;
++}
++
++static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr,
++ enum pp_clock_type type, char *buf)
++{
++ struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend);
++ struct smu10_voltage_dependency_table *mclk_table =
++ data->clock_vol_info.vdd_dep_on_fclk;
++ int i, now, size = 0;
++
++ switch (type) {
++ case PP_SCLK:
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency);
++ now = smum_get_argument(hwmgr);
++
++ size += sprintf(buf + size, "0: %uMhz %s\n",
++ data->gfx_min_freq_limit / 100,
++ ((data->gfx_min_freq_limit / 100)
++ == now) ? "*" : "");
++ size += sprintf(buf + size, "1: %uMhz %s\n",
++ data->gfx_max_freq_limit / 100,
++ ((data->gfx_max_freq_limit / 100)
++ == now) ? "*" : "");
++ break;
++ case PP_MCLK:
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency);
++ now = smum_get_argument(hwmgr);
++
++ for (i = 0; i < mclk_table->count; i++)
++ size += sprintf(buf + size, "%d: %uMhz %s\n",
++ i,
++ mclk_table->entries[i].clk / 100,
++ ((mclk_table->entries[i].clk / 100)
++ == now) ? "*" : "");
++ break;
++ default:
++ break;
++ }
++
++ return size;
++}
++
++static int smu10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
++ PHM_PerformanceLevelDesignation designation, uint32_t index,
++ PHM_PerformanceLevel *level)
++{
++ struct smu10_hwmgr *data;
++
++ if (level == NULL || hwmgr == NULL || state == NULL)
++ return -EINVAL;
++
++ data = (struct smu10_hwmgr *)(hwmgr->backend);
++
++ if (index == 0) {
++ level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk;
++ level->coreClock = data->gfx_min_freq_limit;
++ } else {
++ level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[
++ data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk;
++ level->coreClock = data->gfx_max_freq_limit;
++ }
++
++ level->nonLocalMemoryFreq = 0;
++ level->nonLocalMemoryWidth = 0;
++
++ return 0;
++}
++
++static int smu10_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr,
++ const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
++{
++ const struct smu10_power_state *ps = cast_const_smu10_ps(state);
++
++ clock_info->min_eng_clk = ps->levels[0].engine_clock / (1 << (ps->levels[0].ss_divider_index));
++ clock_info->max_eng_clk = ps->levels[ps->level - 1].engine_clock / (1 << (ps->levels[ps->level - 1].ss_divider_index));
++
++ return 0;
++}
++
++#define MEM_FREQ_LOW_LATENCY 25000
++#define MEM_FREQ_HIGH_LATENCY 80000
++#define MEM_LATENCY_HIGH 245
++#define MEM_LATENCY_LOW 35
++#define MEM_LATENCY_ERR 0xFFFF
++
++
++static uint32_t smu10_get_mem_latency(struct pp_hwmgr *hwmgr,
++ uint32_t clock)
++{
++ if (clock >= MEM_FREQ_LOW_LATENCY &&
++ clock < MEM_FREQ_HIGH_LATENCY)
++ return MEM_LATENCY_HIGH;
++ else if (clock >= MEM_FREQ_HIGH_LATENCY)
++ return MEM_LATENCY_LOW;
++ else
++ return MEM_LATENCY_ERR;
++}
++
++static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
++ enum amd_pp_clock_type type,
++ struct pp_clock_levels_with_latency *clocks)
++{
++ uint32_t i;
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++ struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
++ struct smu10_voltage_dependency_table *pclk_vol_table;
++ bool latency_required = false;
++
++ if (pinfo == NULL)
++ return -EINVAL;
++
++ switch (type) {
++ case amd_pp_mem_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_mclk;
++ latency_required = true;
++ break;
++ case amd_pp_f_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_fclk;
++ latency_required = true;
++ break;
++ case amd_pp_dcf_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
++ break;
++ case amd_pp_disp_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_dispclk;
++ break;
++ case amd_pp_phy_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_phyclk;
++ break;
++ case amd_pp_dpp_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_dppclk;
++ default:
++ return -EINVAL;
++ }
++
++ if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
++ return -EINVAL;
++
++ clocks->num_levels = 0;
++ for (i = 0; i < pclk_vol_table->count; i++) {
++ clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk;
++ clocks->data[i].latency_in_us = latency_required ?
++ smu10_get_mem_latency(hwmgr,
++ pclk_vol_table->entries[i].clk) :
++ 0;
++ clocks->num_levels++;
++ }
++
++ return 0;
++}
++
++static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
++ enum amd_pp_clock_type type,
++ struct pp_clock_levels_with_voltage *clocks)
++{
++ uint32_t i;
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++ struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info);
++ struct smu10_voltage_dependency_table *pclk_vol_table = NULL;
++
++ if (pinfo == NULL)
++ return -EINVAL;
++
++ switch (type) {
++ case amd_pp_mem_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_mclk;
++ break;
++ case amd_pp_f_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_fclk;
++ break;
++ case amd_pp_dcf_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_dcefclk;
++ break;
++ case amd_pp_soc_clock:
++ pclk_vol_table = pinfo->vdd_dep_on_socclk;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ if (pclk_vol_table == NULL || pclk_vol_table->count == 0)
++ return -EINVAL;
++
++ clocks->num_levels = 0;
++ for (i = 0; i < pclk_vol_table->count; i++) {
++ clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk;
++ clocks->data[i].voltage_in_mv = pclk_vol_table->entries[i].vol;
++ clocks->num_levels++;
++ }
++
++ return 0;
++}
++
++static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
++ struct pp_display_clock_request *clock_req)
++{
++ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
++ enum amd_pp_clock_type clk_type = clock_req->clock_type;
++ uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
++ PPSMC_Msg msg;
++
++ switch (clk_type) {
++ case amd_pp_dcf_clock:
++ if (clk_freq == smu10_data->dcf_actual_hard_min_freq)
++ return 0;
++ msg = PPSMC_MSG_SetHardMinDcefclkByFreq;
++ smu10_data->dcf_actual_hard_min_freq = clk_freq;
++ break;
++ case amd_pp_soc_clock:
++ msg = PPSMC_MSG_SetHardMinSocclkByFreq;
++ break;
++ case amd_pp_f_clock:
++ if (clk_freq == smu10_data->f_actual_hard_min_freq)
++ return 0;
++ smu10_data->f_actual_hard_min_freq = clk_freq;
++ msg = PPSMC_MSG_SetHardMinFclkByFreq;
++ break;
++ default:
++ pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
++ return -EINVAL;
++ }
++
++ smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq);
++
++ return 0;
++}
++
++static int smu10_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
++{
++ clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */
++ return 0;
++}
++
++static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
++{
++ uint32_t reg_offset = soc15_get_register_offset(THM_HWID, 0,
++ mmTHM_TCON_CUR_TMP_BASE_IDX, mmTHM_TCON_CUR_TMP);
++ uint32_t reg_value = cgs_read_register(hwmgr->device, reg_offset);
++ int cur_temp =
++ (reg_value & THM_TCON_CUR_TMP__CUR_TEMP_MASK) >> THM_TCON_CUR_TMP__CUR_TEMP__SHIFT;
++
++ if (cur_temp & THM_TCON_CUR_TMP__CUR_TEMP_RANGE_SEL_MASK)
++ cur_temp = ((cur_temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
++ else
++ cur_temp = (cur_temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
++
++ return cur_temp;
++}
++
++static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
++ void *value, int *size)
++{
++ uint32_t sclk, mclk;
++ int ret = 0;
++
++ switch (idx) {
++ case AMDGPU_PP_SENSOR_GFX_SCLK:
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency);
++ sclk = smum_get_argument(hwmgr);
++ /* in units of 10KHZ */
++ *((uint32_t *)value) = sclk * 100;
++ *size = 4;
++ break;
++ case AMDGPU_PP_SENSOR_GFX_MCLK:
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency);
++ mclk = smum_get_argument(hwmgr);
++ /* in units of 10KHZ */
++ *((uint32_t *)value) = mclk * 100;
++ *size = 4;
++ break;
++ case AMDGPU_PP_SENSOR_GPU_TEMP:
++ *((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr);
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++static int smu10_set_mmhub_powergating_by_smu(struct pp_hwmgr *hwmgr)
++{
++ return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub);
++}
++
++static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
++ .backend_init = smu10_hwmgr_backend_init,
++ .backend_fini = smu10_hwmgr_backend_fini,
++ .asic_setup = NULL,
++ .apply_state_adjust_rules = smu10_apply_state_adjust_rules,
++ .force_dpm_level = smu10_dpm_force_dpm_level,
++ .get_power_state_size = smu10_get_power_state_size,
++ .powerdown_uvd = NULL,
++ .powergate_uvd = NULL,
++ .powergate_vce = NULL,
++ .get_mclk = smu10_dpm_get_mclk,
++ .get_sclk = smu10_dpm_get_sclk,
++ .patch_boot_state = smu10_dpm_patch_boot_state,
++ .get_pp_table_entry = smu10_dpm_get_pp_table_entry,
++ .get_num_of_pp_table_entries = smu10_dpm_get_num_of_pp_table_entries,
++ .set_cpu_power_state = smu10_set_cpu_power_state,
++ .store_cc6_data = smu10_store_cc6_data,
++ .force_clock_level = smu10_force_clock_level,
++ .print_clock_levels = smu10_print_clock_levels,
++ .get_dal_power_level = smu10_get_dal_power_level,
++ .get_performance_level = smu10_get_performance_level,
++ .get_current_shallow_sleep_clocks = smu10_get_current_shallow_sleep_clocks,
++ .get_clock_by_type_with_latency = smu10_get_clock_by_type_with_latency,
++ .get_clock_by_type_with_voltage = smu10_get_clock_by_type_with_voltage,
++ .get_max_high_clocks = smu10_get_max_high_clocks,
++ .read_sensor = smu10_read_sensor,
++ .set_active_display_count = smu10_set_active_display_count,
++ .set_deep_sleep_dcefclk = smu10_set_deep_sleep_dcefclk,
++ .dynamic_state_management_enable = smu10_enable_dpm_tasks,
++ .power_off_asic = smu10_power_off_asic,
++ .asic_setup = smu10_setup_asic_task,
++ .power_state_set = smu10_set_power_state_tasks,
++ .dynamic_state_management_disable = smu10_disable_dpm_tasks,
++ .set_mmhub_powergating_by_smu = smu10_set_mmhub_powergating_by_smu,
++};
++
++int smu10_init_function_pointers(struct pp_hwmgr *hwmgr)
++{
++ hwmgr->hwmgr_func = &smu10_hwmgr_funcs;
++ hwmgr->pptable_func = &pptable_funcs;
++ return 0;
++}
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h
+new file mode 100644
+index 0000000..175c3a5
+--- /dev/null
++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h
+@@ -0,0 +1,322 @@
++/*
++ * Copyright 2017 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 SMU10_HWMGR_H
++#define SMU10_HWMGR_H
++
++#include "hwmgr.h"
++#include "smu10_inc.h"
++#include "smu10_driver_if.h"
++#include "rv_ppsmc.h"
++
++
++#define SMU10_MAX_HARDWARE_POWERLEVELS 8
++#define SMU10_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15
++
++#define DPMFlags_SCLK_Enabled 0x00000001
++#define DPMFlags_UVD_Enabled 0x00000002
++#define DPMFlags_VCE_Enabled 0x00000004
++#define DPMFlags_ACP_Enabled 0x00000008
++#define DPMFlags_ForceHighestValid 0x40000000
++
++/* Do not change the following, it is also defined in SMU8.h */
++#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001
++#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000
++#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x01000000
++#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x02000000
++
++#define SMU_PHYID_SHIFT 8
++
++#define SMU10_PCIE_POWERGATING_TARGET_GFX 0
++#define SMU10_PCIE_POWERGATING_TARGET_DDI 1
++#define SMU10_PCIE_POWERGATING_TARGET_PLLCASCADE 2
++#define SMU10_PCIE_POWERGATING_TARGET_PHY 3
++
++enum VQ_TYPE {
++ CLOCK_TYPE_DCLK = 0L,
++ CLOCK_TYPE_ECLK,
++ CLOCK_TYPE_SCLK,
++ CLOCK_TYPE_CCLK,
++ VQ_GFX_CU
++};
++
++#define SUSTAINABLE_SCLK_MASK 0x00ffffff
++#define SUSTAINABLE_SCLK_SHIFT 0
++#define SUSTAINABLE_CU_MASK 0xff000000
++#define SUSTAINABLE_CU_SHIFT 24
++
++struct smu10_dpm_entry {
++ uint32_t soft_min_clk;
++ uint32_t hard_min_clk;
++ uint32_t soft_max_clk;
++ uint32_t hard_max_clk;
++};
++
++struct smu10_power_level {
++ uint32_t engine_clock;
++ uint8_t vddc_index;
++ uint8_t ds_divider_index;
++ uint8_t ss_divider_index;
++ uint8_t allow_gnb_slow;
++ uint8_t force_nbp_state;
++ uint8_t display_wm;
++ uint8_t vce_wm;
++ uint8_t num_simd_to_powerdown;
++ uint8_t hysteresis_up;
++ uint8_t rsv[3];
++};
++
++/*used for the nbpsFlags field in smu10_power state*/
++#define SMU10_POWERSTATE_FLAGS_NBPS_FORCEHIGH (1<<0)
++#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOHIGH (1<<1)
++#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOLOW (1<<2)
++
++#define SMU10_POWERSTATE_FLAGS_BAPM_DISABLE (1<<0)
++
++struct smu10_uvd_clocks {
++ uint32_t vclk;
++ uint32_t dclk;
++ uint32_t vclk_low_divider;
++ uint32_t vclk_high_divider;
++ uint32_t dclk_low_divider;
++ uint32_t dclk_high_divider;
++};
++
++struct pp_disable_nbpslo_flags {
++ union {
++ struct {
++ uint32_t entry : 1;
++ uint32_t display : 1;
++ uint32_t driver: 1;
++ uint32_t vce : 1;
++ uint32_t uvd : 1;
++ uint32_t acp : 1;
++ uint32_t reserved: 26;
++ } bits;
++ uint32_t u32All;
++ };
++};
++
++
++enum smu10_pstate_previous_action {
++ DO_NOTHING = 1,
++ FORCE_HIGH,
++ CANCEL_FORCE_HIGH
++};
++
++struct smu10_power_state {
++ unsigned int magic;
++ uint32_t level;
++ struct smu10_uvd_clocks uvd_clocks;
++ uint32_t evclk;
++ uint32_t ecclk;
++ uint32_t samclk;
++ uint32_t acpclk;
++ bool need_dfs_bypass;
++
++ uint32_t nbps_flags;
++ uint32_t bapm_flags;
++ uint8_t dpm0_pg_nbps_low;
++ uint8_t dpm0_pg_nbps_high;
++ uint8_t dpm_x_nbps_low;
++ uint8_t dpm_x_nbps_high;
++
++ enum smu10_pstate_previous_action action;
++
++ struct smu10_power_level levels[SMU10_MAX_HARDWARE_POWERLEVELS];
++ struct pp_disable_nbpslo_flags nbpslo_flags;
++};
++
++#define SMU10_NUM_NBPSTATES 4
++#define SMU10_NUM_NBPMEMORYCLOCK 2
++
++
++struct smu10_display_phy_info_entry {
++ uint8_t phy_present;
++ uint8_t active_lane_mapping;
++ uint8_t display_config_type;
++ uint8_t active_num_of_lanes;
++};
++
++#define SMU10_MAX_DISPLAYPHY_IDS 10
++
++struct smu10_display_phy_info {
++ bool display_phy_access_initialized;
++ struct smu10_display_phy_info_entry entries[SMU10_MAX_DISPLAYPHY_IDS];
++};
++
++#define MAX_DISPLAY_CLOCK_LEVEL 8
++
++struct smu10_system_info{
++ uint8_t htc_tmp_lmt;
++ uint8_t htc_hyst_lmt;
++};
++
++#define MAX_REGULAR_DPM_NUMBER 8
++
++struct smu10_mclk_latency_entries {
++ uint32_t frequency;
++ uint32_t latency;
++};
++
++struct smu10_mclk_latency_table {
++ uint32_t count;
++ struct smu10_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER];
++};
++
++struct smu10_clock_voltage_dependency_record {
++ uint32_t clk;
++ uint32_t vol;
++};
++
++
++struct smu10_voltage_dependency_table {
++ uint32_t count;
++ struct smu10_clock_voltage_dependency_record entries[1];
++};
++
++struct smu10_clock_voltage_information {
++ struct smu10_voltage_dependency_table *vdd_dep_on_dcefclk;
++ struct smu10_voltage_dependency_table *vdd_dep_on_socclk;
++ struct smu10_voltage_dependency_table *vdd_dep_on_fclk;
++ struct smu10_voltage_dependency_table *vdd_dep_on_mclk;
++ struct smu10_voltage_dependency_table *vdd_dep_on_dispclk;
++ struct smu10_voltage_dependency_table *vdd_dep_on_dppclk;
++ struct smu10_voltage_dependency_table *vdd_dep_on_phyclk;
++};
++
++struct smu10_hwmgr {
++ uint32_t disable_driver_thermal_policy;
++ uint32_t thermal_auto_throttling_treshold;
++ struct smu10_system_info sys_info;
++ struct smu10_mclk_latency_table mclk_latency_table;
++
++ uint32_t ddi_power_gating_disabled;
++
++ struct smu10_display_phy_info_entry display_phy_info;
++ uint32_t dce_slow_sclk_threshold;
++
++ bool disp_clk_bypass;
++ bool disp_clk_bypass_pending;
++ uint32_t bapm_enabled;
++
++ bool video_start;
++ bool battery_state;
++
++ uint32_t is_nb_dpm_enabled;
++ uint32_t is_voltage_island_enabled;
++ uint32_t disable_smu_acp_s3_handshake;
++ uint32_t disable_notify_smu_vpu_recovery;
++ bool in_vpu_recovery;
++ bool pg_acp_init;
++ uint8_t disp_config;
++
++ /* PowerTune */
++ uint32_t power_containment_features;
++ bool cac_enabled;
++ bool disable_uvd_power_tune_feature;
++ bool enable_bapm_feature;
++ bool enable_tdc_limit_feature;
++
++
++ /* SMC SRAM Address of firmware header tables */
++ uint32_t sram_end;
++ uint32_t dpm_table_start;
++ uint32_t soft_regs_start;
++
++ /* start of SMU7_Fusion_DpmTable */
++
++ uint8_t uvd_level_count;
++ uint8_t vce_level_count;
++ uint8_t acp_level_count;
++ uint8_t samu_level_count;
++
++ uint32_t fps_high_threshold;
++ uint32_t fps_low_threshold;
++
++ uint32_t dpm_flags;
++ struct smu10_dpm_entry sclk_dpm;
++ struct smu10_dpm_entry uvd_dpm;
++ struct smu10_dpm_entry vce_dpm;
++ struct smu10_dpm_entry acp_dpm;
++ bool acp_power_up_no_dsp;
++
++ uint32_t max_sclk_level;
++ uint32_t num_of_clk_entries;
++
++ /* CPU Power State */
++ uint32_t separation_time;
++ bool cc6_disable;
++ bool pstate_disable;
++ bool cc6_setting_changed;
++
++ uint32_t ulTotalActiveCUs;
++
++ bool isp_tileA_power_gated;
++ bool isp_tileB_power_gated;
++ uint32_t isp_actual_hard_min_freq;
++ uint32_t soc_actual_hard_min_freq;
++ uint32_t dcf_actual_hard_min_freq;
++
++ uint32_t f_actual_hard_min_freq;
++ uint32_t fabric_actual_soft_min_freq;
++ uint32_t vclk_soft_min;
++ uint32_t dclk_soft_min;
++ uint32_t gfx_actual_soft_min_freq;
++ uint32_t gfx_min_freq_limit;
++ uint32_t gfx_max_freq_limit;
++
++ bool vcn_power_gated;
++ bool vcn_dpg_mode;
++
++ bool gfx_off_controled_by_driver;
++ Watermarks_t water_marks_table;
++ struct smu10_clock_voltage_information clock_vol_info;
++ DpmClocks_t clock_table;
++
++ uint32_t active_process_mask;
++ bool need_min_deep_sleep_dcefclk;
++ uint32_t deep_sleep_dcefclk;
++ uint32_t num_active_display;
++};
++
++struct pp_hwmgr;
++
++int smu10_init_function_pointers(struct pp_hwmgr *hwmgr);
++
++/* UMD PState SMU10 Msg Parameters in MHz */
++#define SMU10_UMD_PSTATE_GFXCLK 700
++#define SMU10_UMD_PSTATE_SOCCLK 626
++#define SMU10_UMD_PSTATE_FCLK 933
++#define SMU10_UMD_PSTATE_VCE 0x03C00320
++
++#define SMU10_UMD_PSTATE_PEAK_GFXCLK 1100
++#define SMU10_UMD_PSTATE_PEAK_SOCCLK 757
++#define SMU10_UMD_PSTATE_PEAK_FCLK 1200
++
++#define SMU10_UMD_PSTATE_MIN_GFXCLK 200
++#define SMU10_UMD_PSTATE_MIN_FCLK 400
++#define SMU10_UMD_PSTATE_MIN_SOCCLK 200
++#define SMU10_UMD_PSTATE_MIN_VCE 0x0190012C
++
++#endif
+diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h
+new file mode 100644
+index 0000000..edb68e3
+--- /dev/null
++++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright 2016 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 SMU10_INC_H
++#define SMU10_INC_H
++
++
++#include "asic_reg/mp/mp_10_0_default.h"
++#include "asic_reg/mp/mp_10_0_offset.h"
++#include "asic_reg/mp/mp_10_0_sh_mask.h"
++
++#include "asic_reg/nbio/nbio_7_0_default.h"
++#include "asic_reg/nbio/nbio_7_0_offset.h"
++#include "asic_reg/nbio/nbio_7_0_sh_mask.h"
++
++#include "asic_reg/thm/thm_10_0_default.h"
++#include "asic_reg/thm/thm_10_0_offset.h"
++#include "asic_reg/thm/thm_10_0_sh_mask.h"
++
++
++#define ixDDI_PHY_GEN_STATUS 0x3FCE8
++
++#endif
+diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+index 494f891..9bdad48 100644
+--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
++++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+@@ -820,7 +820,7 @@ extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr);
+
+ extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr);
+ extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr);
+-extern int rv_init_function_pointers(struct pp_hwmgr *hwmgr);
++extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr);
+
+ extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,
+ uint32_t sclk, uint16_t id, uint16_t *voltage);
+diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
+index 30d3089..c44d792 100644
+--- a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
++++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile
+@@ -5,7 +5,7 @@
+
+ SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o \
+ polaris10_smumgr.o iceland_smumgr.o \
+- smu7_smumgr.o vega10_smumgr.o rv_smumgr.o ci_smumgr.o
++ smu7_smumgr.o vega10_smumgr.o smu10_smumgr.o ci_smumgr.o
+
+ AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR))
+
+diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c
+deleted file mode 100644
+index 3dec481..0000000
+--- a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.c
++++ /dev/null
+@@ -1,346 +0,0 @@
+-/*
+- * Copyright 2016 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 "smumgr.h"
+-#include "rv_inc.h"
+-#include "pp_soc15.h"
+-#include "rv_smumgr.h"
+-#include "ppatomctrl.h"
+-#include "rv_ppsmc.h"
+-#include "smu10_driver_if.h"
+-#include "smu10.h"
+-#include "ppatomctrl.h"
+-#include "pp_debug.h"
+-
+-
+-#define VOLTAGE_SCALE 4
+-
+-#define BUFFER_SIZE 80000
+-#define MAX_STRING_SIZE 15
+-#define BUFFER_SIZETWO 131072
+-
+-#define MP0_Public 0x03800000
+-#define MP0_SRAM 0x03900000
+-#define MP1_Public 0x03b00000
+-#define MP1_SRAM 0x03c00004
+-
+-#define smnMP1_FIRMWARE_FLAGS 0x3010028
+-
+-
+-static uint32_t rv_wait_for_response(struct pp_hwmgr *hwmgr)
+-{
+- uint32_t reg;
+-
+- reg = soc15_get_register_offset(MP1_HWID, 0,
+- mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+-
+- phm_wait_for_register_unequal(hwmgr, reg,
+- 0, MP1_C2PMSG_90__CONTENT_MASK);
+-
+- return cgs_read_register(hwmgr->device, reg);
+-}
+-
+-static int rv_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
+- uint16_t msg)
+-{
+- uint32_t reg;
+-
+- reg = soc15_get_register_offset(MP1_HWID, 0,
+- mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
+- cgs_write_register(hwmgr->device, reg, msg);
+-
+- return 0;
+-}
+-
+-static int rv_read_arg_from_smc(struct pp_hwmgr *hwmgr)
+-{
+- uint32_t reg;
+-
+- reg = soc15_get_register_offset(MP1_HWID, 0,
+- mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
+-
+- return cgs_read_register(hwmgr->device, reg);
+-}
+-
+-static int rv_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
+-{
+- uint32_t reg;
+-
+- rv_wait_for_response(hwmgr);
+-
+- reg = soc15_get_register_offset(MP1_HWID, 0,
+- mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+- cgs_write_register(hwmgr->device, reg, 0);
+-
+- rv_send_msg_to_smc_without_waiting(hwmgr, msg);
+-
+- if (rv_wait_for_response(hwmgr) == 0)
+- printk("Failed to send Message %x.\n", msg);
+-
+- return 0;
+-}
+-
+-
+-static int rv_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
+- uint16_t msg, uint32_t parameter)
+-{
+- uint32_t reg;
+-
+- rv_wait_for_response(hwmgr);
+-
+- reg = soc15_get_register_offset(MP1_HWID, 0,
+- mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
+- cgs_write_register(hwmgr->device, reg, 0);
+-
+- reg = soc15_get_register_offset(MP1_HWID, 0,
+- mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
+- cgs_write_register(hwmgr->device, reg, parameter);
+-
+- rv_send_msg_to_smc_without_waiting(hwmgr, msg);
+-
+-
+- if (rv_wait_for_response(hwmgr) == 0)
+- printk("Failed to send Message %x.\n", msg);
+-
+- return 0;
+-}
+-
+-static int rv_copy_table_from_smc(struct pp_hwmgr *hwmgr,
+- uint8_t *table, int16_t table_id)
+-{
+- struct rv_smumgr *priv =
+- (struct rv_smumgr *)(hwmgr->smu_backend);
+-
+- PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
+- "Invalid SMU Table ID!", return -EINVAL;);
+- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
+- "Invalid SMU Table version!", return -EINVAL;);
+- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
+- "Invalid SMU Table Length!", return -EINVAL;);
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetDriverDramAddrHigh,
+- upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetDriverDramAddrLow,
+- lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_TransferTableSmu2Dram,
+- priv->smu_tables.entry[table_id].table_id);
+-
+- memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table,
+- priv->smu_tables.entry[table_id].size);
+-
+- return 0;
+-}
+-
+-static int rv_copy_table_to_smc(struct pp_hwmgr *hwmgr,
+- uint8_t *table, int16_t table_id)
+-{
+- struct rv_smumgr *priv =
+- (struct rv_smumgr *)(hwmgr->smu_backend);
+-
+- PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
+- "Invalid SMU Table ID!", return -EINVAL;);
+- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
+- "Invalid SMU Table version!", return -EINVAL;);
+- PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
+- "Invalid SMU Table Length!", return -EINVAL;);
+-
+- memcpy(priv->smu_tables.entry[table_id].table, table,
+- priv->smu_tables.entry[table_id].size);
+-
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetDriverDramAddrHigh,
+- upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_SetDriverDramAddrLow,
+- lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_TransferTableDram2Smu,
+- priv->smu_tables.entry[table_id].table_id);
+-
+- return 0;
+-}
+-
+-static int rv_verify_smc_interface(struct pp_hwmgr *hwmgr)
+-{
+- uint32_t smc_driver_if_version;
+-
+- rv_send_msg_to_smc(hwmgr,
+- PPSMC_MSG_GetDriverIfVersion);
+- smc_driver_if_version = rv_read_arg_from_smc(hwmgr);
+-
+- if (smc_driver_if_version != SMU10_DRIVER_IF_VERSION) {
+- pr_err("Attempt to read SMC IF Version Number Failed!\n");
+- return -EINVAL;
+- }
+-
+- return 0;
+-}
+-
+-/* sdma is disabled by default in vbios, need to re-enable in driver */
+-static void rv_smc_enable_sdma(struct pp_hwmgr *hwmgr)
+-{
+- rv_send_msg_to_smc(hwmgr,
+- PPSMC_MSG_PowerUpSdma);
+-}
+-
+-static void rv_smc_disable_sdma(struct pp_hwmgr *hwmgr)
+-{
+- rv_send_msg_to_smc(hwmgr,
+- PPSMC_MSG_PowerDownSdma);
+-}
+-
+-/* vcn is disabled by default in vbios, need to re-enable in driver */
+-static void rv_smc_enable_vcn(struct pp_hwmgr *hwmgr)
+-{
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_PowerUpVcn, 0);
+-}
+-
+-static void rv_smc_disable_vcn(struct pp_hwmgr *hwmgr)
+-{
+- rv_send_msg_to_smc_with_parameter(hwmgr,
+- PPSMC_MSG_PowerDownVcn, 0);
+-}
+-
+-static int rv_smu_fini(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_smumgr *priv =
+- (struct rv_smumgr *)(hwmgr->smu_backend);
+-
+- if (priv) {
+- rv_smc_disable_sdma(hwmgr);
+- rv_smc_disable_vcn(hwmgr);
+- amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
+- &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
+- &priv->smu_tables.entry[SMU10_WMTABLE].table);
+- amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
+- &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
+- &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
+- kfree(hwmgr->smu_backend);
+- hwmgr->smu_backend = NULL;
+- }
+-
+- return 0;
+-}
+-
+-static int rv_start_smu(struct pp_hwmgr *hwmgr)
+-{
+- struct cgs_firmware_info info = {0};
+-
+- smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
+- hwmgr->smu_version = rv_read_arg_from_smc(hwmgr);
+- info.version = hwmgr->smu_version >> 8;
+-
+- cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info);
+-
+- if (rv_verify_smc_interface(hwmgr))
+- return -EINVAL;
+- rv_smc_enable_sdma(hwmgr);
+- rv_smc_enable_vcn(hwmgr);
+- return 0;
+-}
+-
+-static int rv_smu_init(struct pp_hwmgr *hwmgr)
+-{
+- struct rv_smumgr *priv;
+- int r;
+-
+- priv = kzalloc(sizeof(struct rv_smumgr), GFP_KERNEL);
+-
+- if (!priv)
+- return -ENOMEM;
+-
+- hwmgr->smu_backend = priv;
+-
+- /* allocate space for watermarks table */
+- r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+- sizeof(Watermarks_t),
+- PAGE_SIZE,
+- AMDGPU_GEM_DOMAIN_VRAM,
+- &priv->smu_tables.entry[SMU10_WMTABLE].handle,
+- &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
+- &priv->smu_tables.entry[SMU10_WMTABLE].table);
+-
+- if (r)
+- goto err0;
+-
+- priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01;
+- priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t);
+- priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS;
+-
+- /* allocate space for watermarks table */
+- r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+- sizeof(DpmClocks_t),
+- PAGE_SIZE,
+- AMDGPU_GEM_DOMAIN_VRAM,
+- &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
+- &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
+- &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
+-
+- if (r)
+- goto err1;
+-
+- priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01;
+- priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t);
+- priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
+-
+- return 0;
+-
+-err1:
+- amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
+- &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
+- &priv->smu_tables.entry[SMU10_WMTABLE].table);
+-err0:
+- kfree(priv);
+- return -EINVAL;
+-}
+-
+-static int rv_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
+-{
+- int ret;
+-
+- if (rw)
+- ret = rv_copy_table_from_smc(hwmgr, table, table_id);
+- else
+- ret = rv_copy_table_to_smc(hwmgr, table, table_id);
+-
+- return ret;
+-}
+-
+-
+-const struct pp_smumgr_func rv_smu_funcs = {
+- .smu_init = &rv_smu_init,
+- .smu_fini = &rv_smu_fini,
+- .start_smu = &rv_start_smu,
+- .request_smu_load_specific_fw = NULL,
+- .send_msg_to_smc = &rv_send_msg_to_smc,
+- .send_msg_to_smc_with_parameter = &rv_send_msg_to_smc_with_parameter,
+- .download_pptable_settings = NULL,
+- .upload_pptable_settings = NULL,
+- .get_argument = rv_read_arg_from_smc,
+- .smc_table_manager = rv_smc_table_manager,
+-};
+-
+-
+diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h
+deleted file mode 100644
+index 7b53798..0000000
+--- a/drivers/gpu/drm/amd/powerplay/smumgr/rv_smumgr.h
++++ /dev/null
+@@ -1,50 +0,0 @@
+-/*
+- * Copyright 2017 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_RAVEN_SMUMANAGER_H
+-#define PP_RAVEN_SMUMANAGER_H
+-
+-#include "rv_ppsmc.h"
+-#include "smu10_driver_if.h"
+-
+-#define MAX_SMU_TABLE 2
+-
+-struct smu_table_entry {
+- uint32_t version;
+- uint32_t size;
+- uint32_t table_id;
+- uint64_t mc_addr;
+- void *table;
+- struct amdgpu_bo *handle;
+-};
+-
+-struct smu_table_array {
+- struct smu_table_entry entry[MAX_SMU_TABLE];
+-};
+-
+-struct rv_smumgr {
+- struct smu_table_array smu_tables;
+-};
+-
+-
+-#endif
+diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
+new file mode 100644
+index 0000000..bef0b2d
+--- /dev/null
++++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
+@@ -0,0 +1,346 @@
++/*
++ * Copyright 2016 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 "smumgr.h"
++#include "smu10_inc.h"
++#include "pp_soc15.h"
++#include "smu10_smumgr.h"
++#include "ppatomctrl.h"
++#include "rv_ppsmc.h"
++#include "smu10_driver_if.h"
++#include "smu10.h"
++#include "ppatomctrl.h"
++#include "pp_debug.h"
++
++
++#define VOLTAGE_SCALE 4
++
++#define BUFFER_SIZE 80000
++#define MAX_STRING_SIZE 15
++#define BUFFER_SIZETWO 131072
++
++#define MP0_Public 0x03800000
++#define MP0_SRAM 0x03900000
++#define MP1_Public 0x03b00000
++#define MP1_SRAM 0x03c00004
++
++#define smnMP1_FIRMWARE_FLAGS 0x3010028
++
++
++static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr)
++{
++ uint32_t reg;
++
++ reg = soc15_get_register_offset(MP1_HWID, 0,
++ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
++
++ phm_wait_for_register_unequal(hwmgr, reg,
++ 0, MP1_C2PMSG_90__CONTENT_MASK);
++
++ return cgs_read_register(hwmgr->device, reg);
++}
++
++static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr,
++ uint16_t msg)
++{
++ uint32_t reg;
++
++ reg = soc15_get_register_offset(MP1_HWID, 0,
++ mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
++ cgs_write_register(hwmgr->device, reg, msg);
++
++ return 0;
++}
++
++static int smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr)
++{
++ uint32_t reg;
++
++ reg = soc15_get_register_offset(MP1_HWID, 0,
++ mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
++
++ return cgs_read_register(hwmgr->device, reg);
++}
++
++static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
++{
++ uint32_t reg;
++
++ smu10_wait_for_response(hwmgr);
++
++ reg = soc15_get_register_offset(MP1_HWID, 0,
++ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
++ cgs_write_register(hwmgr->device, reg, 0);
++
++ smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
++
++ if (smu10_wait_for_response(hwmgr) == 0)
++ printk("Failed to send Message %x.\n", msg);
++
++ return 0;
++}
++
++
++static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
++ uint16_t msg, uint32_t parameter)
++{
++ uint32_t reg;
++
++ smu10_wait_for_response(hwmgr);
++
++ reg = soc15_get_register_offset(MP1_HWID, 0,
++ mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
++ cgs_write_register(hwmgr->device, reg, 0);
++
++ reg = soc15_get_register_offset(MP1_HWID, 0,
++ mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
++ cgs_write_register(hwmgr->device, reg, parameter);
++
++ smu10_send_msg_to_smc_without_waiting(hwmgr, msg);
++
++
++ if (smu10_wait_for_response(hwmgr) == 0)
++ printk("Failed to send Message %x.\n", msg);
++
++ return 0;
++}
++
++static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
++ uint8_t *table, int16_t table_id)
++{
++ struct smu10_smumgr *priv =
++ (struct smu10_smumgr *)(hwmgr->smu_backend);
++
++ PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
++ "Invalid SMU Table ID!", return -EINVAL;);
++ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
++ "Invalid SMU Table version!", return -EINVAL;);
++ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
++ "Invalid SMU Table Length!", return -EINVAL;);
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetDriverDramAddrHigh,
++ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetDriverDramAddrLow,
++ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_TransferTableSmu2Dram,
++ priv->smu_tables.entry[table_id].table_id);
++
++ memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table,
++ priv->smu_tables.entry[table_id].size);
++
++ return 0;
++}
++
++static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
++ uint8_t *table, int16_t table_id)
++{
++ struct smu10_smumgr *priv =
++ (struct smu10_smumgr *)(hwmgr->smu_backend);
++
++ PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
++ "Invalid SMU Table ID!", return -EINVAL;);
++ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
++ "Invalid SMU Table version!", return -EINVAL;);
++ PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
++ "Invalid SMU Table Length!", return -EINVAL;);
++
++ memcpy(priv->smu_tables.entry[table_id].table, table,
++ priv->smu_tables.entry[table_id].size);
++
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetDriverDramAddrHigh,
++ upper_32_bits(priv->smu_tables.entry[table_id].mc_addr));
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_SetDriverDramAddrLow,
++ lower_32_bits(priv->smu_tables.entry[table_id].mc_addr));
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_TransferTableDram2Smu,
++ priv->smu_tables.entry[table_id].table_id);
++
++ return 0;
++}
++
++static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr)
++{
++ uint32_t smc_driver_if_version;
++
++ smu10_send_msg_to_smc(hwmgr,
++ PPSMC_MSG_GetDriverIfVersion);
++ smc_driver_if_version = smu10_read_arg_from_smc(hwmgr);
++
++ if (smc_driver_if_version != SMU10_DRIVER_IF_VERSION) {
++ pr_err("Attempt to read SMC IF Version Number Failed!\n");
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++/* sdma is disabled by default in vbios, need to re-enable in driver */
++static void smu10_smc_enable_sdma(struct pp_hwmgr *hwmgr)
++{
++ smu10_send_msg_to_smc(hwmgr,
++ PPSMC_MSG_PowerUpSdma);
++}
++
++static void smu10_smc_disable_sdma(struct pp_hwmgr *hwmgr)
++{
++ smu10_send_msg_to_smc(hwmgr,
++ PPSMC_MSG_PowerDownSdma);
++}
++
++/* vcn is disabled by default in vbios, need to re-enable in driver */
++static void smu10_smc_enable_vcn(struct pp_hwmgr *hwmgr)
++{
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_PowerUpVcn, 0);
++}
++
++static void smu10_smc_disable_vcn(struct pp_hwmgr *hwmgr)
++{
++ smu10_send_msg_to_smc_with_parameter(hwmgr,
++ PPSMC_MSG_PowerDownVcn, 0);
++}
++
++static int smu10_smu_fini(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_smumgr *priv =
++ (struct smu10_smumgr *)(hwmgr->smu_backend);
++
++ if (priv) {
++ smu10_smc_disable_sdma(hwmgr);
++ smu10_smc_disable_vcn(hwmgr);
++ amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
++ &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
++ &priv->smu_tables.entry[SMU10_WMTABLE].table);
++ amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
++ &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
++ &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
++ kfree(hwmgr->smu_backend);
++ hwmgr->smu_backend = NULL;
++ }
++
++ return 0;
++}
++
++static int smu10_start_smu(struct pp_hwmgr *hwmgr)
++{
++ struct cgs_firmware_info info = {0};
++
++ smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion);
++ hwmgr->smu_version = smu10_read_arg_from_smc(hwmgr);
++ info.version = hwmgr->smu_version >> 8;
++
++ cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info);
++
++ if (smu10_verify_smc_interface(hwmgr))
++ return -EINVAL;
++ smu10_smc_enable_sdma(hwmgr);
++ smu10_smc_enable_vcn(hwmgr);
++ return 0;
++}
++
++static int smu10_smu_init(struct pp_hwmgr *hwmgr)
++{
++ struct smu10_smumgr *priv;
++ int r;
++
++ priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL);
++
++ if (!priv)
++ return -ENOMEM;
++
++ hwmgr->smu_backend = priv;
++
++ /* allocate space for watermarks table */
++ r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
++ sizeof(Watermarks_t),
++ PAGE_SIZE,
++ AMDGPU_GEM_DOMAIN_VRAM,
++ &priv->smu_tables.entry[SMU10_WMTABLE].handle,
++ &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
++ &priv->smu_tables.entry[SMU10_WMTABLE].table);
++
++ if (r)
++ goto err0;
++
++ priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01;
++ priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t);
++ priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS;
++
++ /* allocate space for watermarks table */
++ r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
++ sizeof(DpmClocks_t),
++ PAGE_SIZE,
++ AMDGPU_GEM_DOMAIN_VRAM,
++ &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle,
++ &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr,
++ &priv->smu_tables.entry[SMU10_CLOCKTABLE].table);
++
++ if (r)
++ goto err1;
++
++ priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01;
++ priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t);
++ priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS;
++
++ return 0;
++
++err1:
++ amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
++ &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
++ &priv->smu_tables.entry[SMU10_WMTABLE].table);
++err0:
++ kfree(priv);
++ return -EINVAL;
++}
++
++static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw)
++{
++ int ret;
++
++ if (rw)
++ ret = smu10_copy_table_from_smc(hwmgr, table, table_id);
++ else
++ ret = smu10_copy_table_to_smc(hwmgr, table, table_id);
++
++ return ret;
++}
++
++
++const struct pp_smumgr_func smu10_smu_funcs = {
++ .smu_init = &smu10_smu_init,
++ .smu_fini = &smu10_smu_fini,
++ .start_smu = &smu10_start_smu,
++ .request_smu_load_specific_fw = NULL,
++ .send_msg_to_smc = &smu10_send_msg_to_smc,
++ .send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter,
++ .download_pptable_settings = NULL,
++ .upload_pptable_settings = NULL,
++ .get_argument = smu10_read_arg_from_smc,
++ .smc_table_manager = smu10_smc_table_manager,
++};
++
++
+diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h
+new file mode 100644
+index 0000000..9c2be74
+--- /dev/null
++++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h
+@@ -0,0 +1,50 @@
++/*
++ * Copyright 2017 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_SMU10_SMUMANAGER_H
++#define PP_SMU10_SMUMANAGER_H
++
++#include "rv_ppsmc.h"
++#include "smu10_driver_if.h"
++
++#define MAX_SMU_TABLE 2
++
++struct smu_table_entry {
++ uint32_t version;
++ uint32_t size;
++ uint32_t table_id;
++ uint64_t mc_addr;
++ void *table;
++ struct amdgpu_bo *handle;
++};
++
++struct smu_table_array {
++ struct smu_table_entry entry[MAX_SMU_TABLE];
++};
++
++struct smu10_smumgr {
++ struct smu_table_array smu_tables;
++};
++
++
++#endif
+--
+2.7.4
+