From 92c6d645ee19819dd5b63a171ac7ef7abeb3d21b Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Fri, 5 Feb 2016 14:47:06 -0500 Subject: [PATCH] drm/amd/powerplay: add UVD&VCE DPM and powergating support for elm/baf Signed-off-by: Eric Huang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/Makefile | 3 +- .../hwmgr/ellesmere_clockpowergating.c | 153 ++++++++++++++++++ .../hwmgr/ellesmere_clockpowergating.h | 37 +++++ .../drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c | 91 ++++++++++- .../drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h | 4 + 5 files changed, 282 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.c create mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.h diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile index f13327d3f24c..5437ec0ac99b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile @@ -9,7 +9,8 @@ HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \ tonga_hwmgr.o pppcielanes.o tonga_thermal.o\ fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o \ fiji_clockpowergating.o fiji_thermal.o \ - ellesmere_hwmgr.o ellesmere_powertune.o ellesmere_thermal.o + ellesmere_hwmgr.o ellesmere_powertune.o ellesmere_thermal.o \ + ellesmere_clockpowergating.o AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR)) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.c new file mode 100644 index 000000000000..0dee0dfa91ec --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.c @@ -0,0 +1,153 @@ +/* + * 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 "ellesmere_clockpowergating.h" + +int ellesmere_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 ellesmere_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 ellesmere_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 ellesmere_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 ellesmere_phm_powerdown_samu(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SamuPowerGating)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SAMPowerOFF); + return 0; +} + +int ellesmere_phm_powerup_samu(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SamuPowerGating)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SAMPowerON); + return 0; +} + +int ellesmere_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr) +{ + struct ellesmere_hwmgr *data = (struct ellesmere_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = false; + data->vce_power_gated = false; + data->samu_power_gated = false; + + ellesmere_phm_powerup_uvd(hwmgr); + ellesmere_phm_powerup_vce(hwmgr); + ellesmere_phm_powerup_samu(hwmgr); + + return 0; +} + +int ellesmere_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct ellesmere_hwmgr *data = (struct ellesmere_hwmgr *)(hwmgr->backend); + + if (data->uvd_power_gated == bgate) + return 0; + + data->uvd_power_gated = bgate; + + if (bgate) { + ellesmere_update_uvd_dpm(hwmgr, true); + ellesmere_phm_powerdown_uvd(hwmgr); + } else { + ellesmere_phm_powerup_uvd(hwmgr); + ellesmere_update_uvd_dpm(hwmgr, false); + } + + return 0; +} + +int ellesmere_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct ellesmere_hwmgr *data = (struct ellesmere_hwmgr *)(hwmgr->backend); + + if (data->vce_power_gated == bgate) + return 0; + + if (bgate) + ellesmere_phm_powerdown_vce(hwmgr); + else + ellesmere_phm_powerup_vce(hwmgr); + + return 0; +} + +int ellesmere_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct ellesmere_hwmgr *data = (struct ellesmere_hwmgr *)(hwmgr->backend); + + if (data->samu_power_gated == bgate) + return 0; + + data->samu_power_gated = bgate; + + if (bgate) { + ellesmere_update_samu_dpm(hwmgr, true); + ellesmere_phm_powerdown_samu(hwmgr); + } else { + ellesmere_phm_powerup_samu(hwmgr); + ellesmere_update_samu_dpm(hwmgr, false); + } + + return 0; +} + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.h new file mode 100644 index 000000000000..56a950e1c94d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_clockpowergating.h @@ -0,0 +1,37 @@ +/* + * 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 _ELLESMERE_CLOCK_POWER_GATING_H_ +#define _ELLESMERE_CLOCK_POWER_GATING_H_ + +#include "ellesmere_hwmgr.h" +#include "pp_asicblocks.h" + +int ellesmere_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); +int ellesmere_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); +int ellesmere_phm_powerdown_uvd(struct pp_hwmgr *hwmgr); +int ellesmere_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate); +int ellesmere_phm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate); +int ellesmere_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr); + +#endif /* _ELLESMERE_CLOCK_POWER_GATING_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c index 3ef8d3c1c1ef..62f0f36cd673 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.c @@ -58,6 +58,7 @@ #include "dce/dce_10_0_sh_mask.h" #include "ellesmere_thermal.h" +#include "ellesmere_clockpowergating.h" #define MC_CG_ARB_FREQ_F0 0x0a #define MC_CG_ARB_FREQ_F1 0x0b @@ -3962,13 +3963,62 @@ static int ellesmere_generate_dpm_level_enable_mask( return 0; } -static int ellesmere_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +int ellesmere_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) { return smum_send_msg_to_smc(hwmgr->smumgr, enable ? + PPSMC_MSG_UVDDPM_Enable : + PPSMC_MSG_UVDDPM_Disable); +} + +int ellesmere_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable? PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable); } +int ellesmere_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable? + PPSMC_MSG_SAMUDPM_Enable : + PPSMC_MSG_SAMUDPM_Disable); +} + +int ellesmere_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct ellesmere_hwmgr *data = (struct ellesmere_hwmgr *)(hwmgr->backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (!bgate) { + data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = data->dpm_table_start + + offsetof(SMU74_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 ellesmere_enable_disable_uvd_dpm(hwmgr, !bgate); +} + static int ellesmere_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input) { const struct phm_set_power_state_input *states = @@ -4015,6 +4065,37 @@ static int ellesmere_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input) return 0; } +int ellesmere_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct ellesmere_hwmgr *data = (struct ellesmere_hwmgr *)(hwmgr->backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (!bgate) { + data->smc_state_table.SamuBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = data->dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, SamuBootLevel); + 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 &= 0xFFFFFF00; + mm_boot_level_value |= data->smc_state_table.SamuBootLevel << 0; + 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_SAMUDPM_SetEnabledMask, + (uint32_t)(1 << data->smc_state_table.SamuBootLevel)); + } + + return ellesmere_enable_disable_samu_dpm(hwmgr, !bgate); +} + static int ellesmere_update_sclk_threshold(struct pp_hwmgr *hwmgr) { struct ellesmere_hwmgr *data = (struct ellesmere_hwmgr *)(hwmgr->backend); @@ -4536,10 +4617,10 @@ static const struct pp_hwmgr_func ellesmere_hwmgr_funcs = { .get_pp_table_entry = ellesmere_get_pp_table_entry, .get_num_of_pp_table_entries = tonga_get_number_of_powerplay_table_entries, .print_current_perforce_level = ellesmere_print_current_perforce_level, - .powerdown_uvd = NULL, - .powergate_uvd = NULL, - .powergate_vce = NULL, - .disable_clock_power_gating = NULL, + .powerdown_uvd = ellesmere_phm_powerdown_uvd, + .powergate_uvd = ellesmere_phm_powergate_uvd, + .powergate_vce = ellesmere_phm_powergate_vce, + .disable_clock_power_gating = ellesmere_phm_disable_clock_power_gating, .notify_smc_display_config_after_ps_adjustment = ellesmere_notify_smc_display_config_after_ps_adjustment, .display_config_changed = ellesmere_display_configuration_changed_task, .set_max_fan_pwm_output = ellesmere_set_max_fan_pwm_output, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h index 4d576984928d..7f9025256d08 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ellesmere_hwmgr.h @@ -345,5 +345,9 @@ enum Ellesmere_I2CLineID { int ellesemere_hwmgr_init(struct pp_hwmgr *hwmgr); +int ellesmere_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int ellesmere_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int ellesmere_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); + #endif -- 2.20.1