Commit dd35f548 authored by Rex Zhu's avatar Rex Zhu Committed by Tim Gardner

drm/amd/powerplay: Add CG and PG support for tonga

BugLink: http://bugs.launchpad.net/bugs/1546572

Implement clock and power gating support for tonga.  On Tonga
this is handles by the SMU rather than direct register settings
in the driver.
Signed-off-by: default avatarRex Zhu <Rex.Zhu@amd.com>
Reviewed-by: default avatarJammy Zhou <Jammy.Zhou@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 0859ed3d)
Signed-off-by: default avatarAlberto Milone <alberto.milone@canonical.com>
Signed-off-by: default avatarTim Gardner <tim.gardner@canonical.com>
parent b34fb753
......@@ -7,7 +7,7 @@ HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \
cz_clockpowergating.o \
tonga_processpptables.o ppatomctrl.o \
tonga_hwmgr.o pppcielanes.o \
fiji_powertune.o fiji_hwmgr.o
fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o
AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR))
......
/*
* Copyright 2015 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "hwmgr.h"
#include "tonga_clockpowergating.h"
#include "tonga_ppsmc.h"
#include "tonga_hwmgr.h"
int tonga_phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_uvd_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr->smumgr,
PPSMC_MSG_UVDPowerOFF);
return 0;
}
int tonga_phm_powerup_uvd(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_uvd_power_gating(hwmgr)) {
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
PHM_PlatformCaps_UVDDynamicPowerGating)) {
return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_UVDPowerON, 1);
} else {
return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_UVDPowerON, 0);
}
}
return 0;
}
int tonga_phm_powerdown_vce(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_vce_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr->smumgr,
PPSMC_MSG_VCEPowerOFF);
return 0;
}
int tonga_phm_powerup_vce(struct pp_hwmgr *hwmgr)
{
if (phm_cf_want_vce_power_gating(hwmgr))
return smum_send_msg_to_smc(hwmgr->smumgr,
PPSMC_MSG_VCEPowerON);
return 0;
}
int tonga_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating)
{
int ret = 0;
switch (block) {
case PHM_AsicBlock_UVD_MVC:
case PHM_AsicBlock_UVD:
case PHM_AsicBlock_UVD_HD:
case PHM_AsicBlock_UVD_SD:
if (gating == PHM_ClockGateSetting_StaticOff)
ret = tonga_phm_powerdown_uvd(hwmgr);
else
ret = tonga_phm_powerup_uvd(hwmgr);
break;
case PHM_AsicBlock_GFX:
default:
break;
}
return ret;
}
int tonga_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr)
{
struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
data->uvd_power_gated = false;
data->vce_power_gated = false;
tonga_phm_powerup_uvd(hwmgr);
tonga_phm_powerup_vce(hwmgr);
return 0;
}
int tonga_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
{
struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
if (data->uvd_power_gated == bgate)
return 0;
data->uvd_power_gated = bgate;
if (bgate) {
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE);
tonga_update_uvd_dpm(hwmgr, true);
tonga_phm_powerdown_uvd(hwmgr);
} else {
tonga_phm_powerup_uvd(hwmgr);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE);
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE);
tonga_update_uvd_dpm(hwmgr, false);
}
return 0;
}
int tonga_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
{
struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
struct phm_set_power_state_input states;
const struct pp_power_state *pcurrent;
struct pp_power_state *requested;
pcurrent = hwmgr->current_ps;
requested = hwmgr->request_ps;
states.pcurrent_state = &(pcurrent->hardware);
states.pnew_state = &(requested->hardware);
if (phm_cf_want_vce_power_gating(hwmgr)) {
if (data->vce_power_gated != bgate) {
if (bgate) {
cgs_set_clockgating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
cgs_set_powergating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_GATE);
tonga_enable_disable_vce_dpm(hwmgr, false);
data->vce_power_gated = true;
} else {
tonga_phm_powerup_vce(hwmgr);
data->vce_power_gated = false;
cgs_set_powergating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
cgs_set_clockgating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_GATE);
tonga_update_vce_dpm(hwmgr, &states);
tonga_enable_disable_vce_dpm(hwmgr, true);
return 0;
}
}
} else {
tonga_update_vce_dpm(hwmgr, &states);
tonga_enable_disable_vce_dpm(hwmgr, true);
return 0;
}
if (!data->vce_power_gated)
tonga_update_vce_dpm(hwmgr, &states);
return 0;
}
int tonga_phm_update_clock_gatings(struct pp_hwmgr *hwmgr,
const uint32_t *msg_id)
{
PPSMC_Msg msg;
uint32_t value;
switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) {
case PP_GROUP_GFX:
switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
case PP_BLOCK_GFX_CG:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_CGCG_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_GFX_CGLS_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
break;
case PP_BLOCK_GFX_MG:
/* For GFX MGCG, there are three different ones;
* CPF, RLC, and all others. CPF MGCG will not be used for Tonga.
* For GFX MGLS, Tonga will not support it.
* */
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = (CG_RLC_MGCG_MASK | CG_GFX_OTHERS_MGCG_MASK);
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
break;
default:
return -1;
}
break;
case PP_GROUP_SYS:
switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) {
case PP_BLOCK_SYS_BIF:
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_BIF_MGLS_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
break;
case PP_BLOCK_SYS_MC:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_MC_MGCG_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_MC_MGLS_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
break;
case PP_BLOCK_SYS_HDP:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_HDP_MGCG_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_HDP_MGLS_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
break;
case PP_BLOCK_SYS_SDMA:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_SDMA_MGCG_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
if (PP_STATE_SUPPORT_LS & *msg_id) {
msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_SDMA_MGLS_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
break;
case PP_BLOCK_SYS_ROM:
if (PP_STATE_SUPPORT_CG & *msg_id) {
msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG)
? PPSMC_MSG_EnableClockGatingFeature
: PPSMC_MSG_DisableClockGatingFeature;
value = CG_SYS_ROM_MASK;
if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value))
return -1;
}
break;
default:
return -1;
}
break;
default:
return -1;
}
return 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.
*
*/
#ifndef _TONGA_CLOCK_POWER_GATING_H_
#define _TONGA_CLOCK_POWER_GATING_H_
#include "tonga_hwmgr.h"
#include "pp_asicblocks.h"
extern int tonga_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating);
extern int tonga_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate);
extern int tonga_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate);
extern int tonga_phm_powerdown_uvd(struct pp_hwmgr *hwmgr);
extern int tonga_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr);
extern int tonga_phm_update_clock_gatings(struct pp_hwmgr *hwmgr, const uint32_t *msg_id);
#endif /* _TONGA_CLOCK_POWER_GATING_H_ */
......@@ -39,6 +39,7 @@
#include "tonga_dyn_defaults.h"
#include "smumgr.h"
#include "tonga_smumgr.h"
#include "tonga_clockpowergating.h"
#include "smu/smu_7_1_2_d.h"
#include "smu/smu_7_1_2_sh_mask.h"
......@@ -5488,14 +5489,47 @@ static int tonga_generate_dpm_level_enable_mask(struct pp_hwmgr *hwmgr, const vo
return 0;
}
static int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
{
return smum_send_msg_to_smc(hwmgr->smumgr, enable?
return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
(PPSMC_Msg)PPSMC_MSG_VCEDPM_Enable :
(PPSMC_Msg)PPSMC_MSG_VCEDPM_Disable);
}
static int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
int tonga_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
{
return smum_send_msg_to_smc(hwmgr->smumgr, enable ?
(PPSMC_Msg)PPSMC_MSG_UVDDPM_Enable :
(PPSMC_Msg)PPSMC_MSG_UVDDPM_Disable);
}
int tonga_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate)
{
struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
uint32_t mm_boot_level_offset, mm_boot_level_value;
struct phm_ppt_v1_information *ptable_information = (struct phm_ppt_v1_information *)(hwmgr->pptable);
if (!bgate) {
data->smc_state_table.UvdBootLevel = (uint8_t) (ptable_information->mm_dep_table->count - 1);
mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, UvdBootLevel);
mm_boot_level_offset /= 4;
mm_boot_level_offset *= 4;
mm_boot_level_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset);
mm_boot_level_value &= 0x00FFFFFF;
mm_boot_level_value |= data->smc_state_table.UvdBootLevel << 24;
cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM) ||
phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_UVDDPM_SetEnabledMask,
(uint32_t)(1 << data->smc_state_table.UvdBootLevel));
}
return tonga_enable_disable_uvd_dpm(hwmgr, !bgate);
}
int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
{
const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input;
struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend);
......@@ -5505,8 +5539,7 @@ static int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
uint32_t mm_boot_level_offset, mm_boot_level_value;
struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable);
if(tonga_nps->vce_clocks.EVCLK >0 &&
(tonga_cps == NULL || tonga_cps->vce_clocks.EVCLK == 0)) {
if (tonga_nps->vce_clocks.EVCLK > 0 && (tonga_cps == NULL || tonga_cps->vce_clocks.EVCLK == 0)) {
data->smc_state_table.VceBootLevel = (uint8_t) (pptable_info->mm_dep_table->count - 1);
mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, VceBootLevel);
......@@ -5517,16 +5550,14 @@ static int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input)
mm_boot_level_value |= data->smc_state_table.VceBootLevel << 16;
cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value);
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) {
smum_send_msg_to_smc_with_parameter(
hwmgr->smumgr,
(PPSMC_Msg)(PPSMC_MSG_VCEDPM_SetEnabledMask),
(uint32_t)1 << data->smc_state_table.VceBootLevel);
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState))
smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
PPSMC_MSG_VCEDPM_SetEnabledMask,
(uint32_t)(1 << data->smc_state_table.VceBootLevel));
tonga_enable_disable_vce_dpm(hwmgr, true);
} else if (tonga_nps->vce_clocks.EVCLK == 0 && tonga_cps != NULL && tonga_cps->vce_clocks.EVCLK > 0)
tonga_enable_disable_vce_dpm(hwmgr, false);
}
tonga_enable_disable_vce_dpm(hwmgr, true);
} else if (tonga_nps->vce_clocks.EVCLK == 0 && tonga_cps != NULL && tonga_cps->vce_clocks.EVCLK > 0)
tonga_enable_disable_vce_dpm(hwmgr, false);
return 0;
}
......@@ -5783,6 +5814,10 @@ static const struct pp_hwmgr_func tonga_hwmgr_funcs = {
.get_pp_table_entry = tonga_get_pp_table_entry,
.get_num_of_pp_table_entries = tonga_get_number_of_powerplay_table_entries,
.print_current_perforce_level = tonga_print_current_perforce_level,
.powerdown_uvd = tonga_phm_powerdown_uvd,
.powergate_uvd = tonga_phm_powergate_uvd,
.powergate_vce = tonga_phm_powergate_vce,
.disable_clock_power_gating = tonga_phm_disable_clock_power_gating,
.notify_smc_display_config_after_ps_adjustment = tonga_notify_smc_display_config_after_ps_adjustment,
.display_config_changed = tonga_display_configuration_changed_task,
};
......
......@@ -422,6 +422,10 @@ typedef struct tonga_hwmgr tonga_hwmgr;
#define CONVERT_FROM_HOST_TO_SMC_US(X) ((X) = PP_HOST_TO_SMC_US(X))
int tonga_hwmgr_init(struct pp_hwmgr *hwmgr);
int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input);
int tonga_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate);
int tonga_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable);
int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment