diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/ci_dpm.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/ci_dpm.c | 6844 |
1 files changed, 0 insertions, 6844 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c deleted file mode 100644 index 86e14c754dd4..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ /dev/null @@ -1,6844 +0,0 @@ -/* - * Copyright 2013 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 <linux/firmware.h> -#include <drm/drmP.h> -#include "amdgpu.h" -#include "amdgpu_pm.h" -#include "amdgpu_ucode.h" -#include "cikd.h" -#include "amdgpu_dpm.h" -#include "ci_dpm.h" -#include "gfx_v7_0.h" -#include "atom.h" -#include "amd_pcie.h" -#include <linux/seq_file.h> - -#include "smu/smu_7_0_1_d.h" -#include "smu/smu_7_0_1_sh_mask.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "bif/bif_4_1_d.h" -#include "bif/bif_4_1_sh_mask.h" - -#include "gca/gfx_7_2_d.h" -#include "gca/gfx_7_2_sh_mask.h" - -#include "gmc/gmc_7_1_d.h" -#include "gmc/gmc_7_1_sh_mask.h" - -MODULE_FIRMWARE("amdgpu/bonaire_smc.bin"); -MODULE_FIRMWARE("amdgpu/bonaire_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/hawaii_smc.bin"); -MODULE_FIRMWARE("amdgpu/hawaii_k_smc.bin"); - -#define MC_CG_ARB_FREQ_F0 0x0a -#define MC_CG_ARB_FREQ_F1 0x0b -#define MC_CG_ARB_FREQ_F2 0x0c -#define MC_CG_ARB_FREQ_F3 0x0d - -#define SMC_RAM_END 0x40000 - -#define VOLTAGE_SCALE 4 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 - -static const struct amd_pm_funcs ci_dpm_funcs; - -static const struct ci_pt_defaults defaults_hawaii_xt = -{ - 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000, - { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, - { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } -}; - -static const struct ci_pt_defaults defaults_hawaii_pro = -{ - 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062, - { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, - { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } -}; - -static const struct ci_pt_defaults defaults_bonaire_xt = -{ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } -}; - -#if 0 -static const struct ci_pt_defaults defaults_bonaire_pro = -{ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x65062, - { 0x8C, 0x23F, 0x244, 0xA6, 0x83, 0x85, 0x86, 0x86, 0x83, 0xDB, 0xDB, 0xDA, 0x67, 0x60, 0x5F }, - { 0x187, 0x193, 0x193, 0x1C7, 0x1D1, 0x1D1, 0x210, 0x219, 0x219, 0x266, 0x26C, 0x26C, 0x2C9, 0x2CB, 0x2CB } -}; -#endif - -static const struct ci_pt_defaults defaults_saturn_xt = -{ - 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000, - { 0x8C, 0x247, 0x249, 0xA6, 0x80, 0x81, 0x8B, 0x89, 0x86, 0xC9, 0xCA, 0xC9, 0x4D, 0x4D, 0x4D }, - { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 } -}; - -#if 0 -static const struct ci_pt_defaults defaults_saturn_pro = -{ - 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x30000, - { 0x96, 0x21D, 0x23B, 0xA1, 0x85, 0x87, 0x83, 0x84, 0x81, 0xE6, 0xE6, 0xE6, 0x71, 0x6A, 0x6A }, - { 0x193, 0x19E, 0x19E, 0x1D2, 0x1DC, 0x1DC, 0x21A, 0x223, 0x223, 0x26E, 0x27E, 0x274, 0x2CF, 0x2D2, 0x2D2 } -}; -#endif - -static const struct ci_pt_config_reg didt_config_ci[] = -{ - { 0x10, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x10, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x10, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x10, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x11, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x11, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x11, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x11, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x12, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x12, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x12, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x12, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x2, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x2, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x2, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x1, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x1, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x0, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x30, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x30, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x30, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x30, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x31, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x31, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x31, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x31, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x32, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x32, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x32, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x32, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x22, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x22, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x22, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x21, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x21, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x20, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x50, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x50, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x50, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x50, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x51, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x51, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x51, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x51, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x52, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x52, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x52, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x52, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x42, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x42, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x42, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x41, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x41, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x40, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x70, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x70, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x70, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x70, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x71, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x71, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x71, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x71, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x72, 0x000000ff, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x72, 0x0000ff00, 8, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x72, 0x00ff0000, 16, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x72, 0xff000000, 24, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x62, 0x00003fff, 0, 0x4, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x62, 0x03ff0000, 16, 0x80, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x62, 0x78000000, 27, 0x3, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x61, 0x0000ffff, 0, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x61, 0xffff0000, 16, 0x3FFF, CISLANDS_CONFIGREG_DIDT_IND }, - { 0x60, 0x00000001, 0, 0x0, CISLANDS_CONFIGREG_DIDT_IND }, - { 0xFFFFFFFF } -}; - -static u8 ci_get_memory_module_index(struct amdgpu_device *adev) -{ - return (u8) ((RREG32(mmBIOS_SCRATCH_4) >> 16) & 0xff); -} - -#define MC_CG_ARB_FREQ_F0 0x0a -#define MC_CG_ARB_FREQ_F1 0x0b -#define MC_CG_ARB_FREQ_F2 0x0c -#define MC_CG_ARB_FREQ_F3 0x0d - -static int ci_copy_and_switch_arb_sets(struct amdgpu_device *adev, - u32 arb_freq_src, u32 arb_freq_dest) -{ - u32 mc_arb_dram_timing; - u32 mc_arb_dram_timing2; - u32 burst_time; - u32 mc_cg_config; - - switch (arb_freq_src) { - case MC_CG_ARB_FREQ_F0: - mc_arb_dram_timing = RREG32(mmMC_ARB_DRAM_TIMING); - mc_arb_dram_timing2 = RREG32(mmMC_ARB_DRAM_TIMING2); - burst_time = (RREG32(mmMC_ARB_BURST_TIME) & MC_ARB_BURST_TIME__STATE0_MASK) >> - MC_ARB_BURST_TIME__STATE0__SHIFT; - break; - case MC_CG_ARB_FREQ_F1: - mc_arb_dram_timing = RREG32(mmMC_ARB_DRAM_TIMING_1); - mc_arb_dram_timing2 = RREG32(mmMC_ARB_DRAM_TIMING2_1); - burst_time = (RREG32(mmMC_ARB_BURST_TIME) & MC_ARB_BURST_TIME__STATE1_MASK) >> - MC_ARB_BURST_TIME__STATE1__SHIFT; - break; - default: - return -EINVAL; - } - - switch (arb_freq_dest) { - case MC_CG_ARB_FREQ_F0: - WREG32(mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing); - WREG32(mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); - WREG32_P(mmMC_ARB_BURST_TIME, (burst_time << MC_ARB_BURST_TIME__STATE0__SHIFT), - ~MC_ARB_BURST_TIME__STATE0_MASK); - break; - case MC_CG_ARB_FREQ_F1: - WREG32(mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); - WREG32(mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); - WREG32_P(mmMC_ARB_BURST_TIME, (burst_time << MC_ARB_BURST_TIME__STATE1__SHIFT), - ~MC_ARB_BURST_TIME__STATE1_MASK); - break; - default: - return -EINVAL; - } - - mc_cg_config = RREG32(mmMC_CG_CONFIG) | 0x0000000F; - WREG32(mmMC_CG_CONFIG, mc_cg_config); - WREG32_P(mmMC_ARB_CG, (arb_freq_dest) << MC_ARB_CG__CG_ARB_REQ__SHIFT, - ~MC_ARB_CG__CG_ARB_REQ_MASK); - - return 0; -} - -static u8 ci_get_ddr3_mclk_frequency_ratio(u32 memory_clock) -{ - u8 mc_para_index; - - if (memory_clock < 10000) - mc_para_index = 0; - else if (memory_clock >= 80000) - mc_para_index = 0x0f; - else - mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1); - return mc_para_index; -} - -static u8 ci_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode) -{ - u8 mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) - mc_para_index = 0x00; - else if (memory_clock > 47500) - mc_para_index = 0x0f; - else - mc_para_index = (u8)((memory_clock - 10000) / 2500); - } else { - if (memory_clock < 65000) - mc_para_index = 0x00; - else if (memory_clock > 135000) - mc_para_index = 0x0f; - else - mc_para_index = (u8)((memory_clock - 60000) / 5000); - } - return mc_para_index; -} - -static void ci_trim_voltage_table_to_fit_state_table(struct amdgpu_device *adev, - u32 max_voltage_steps, - struct atom_voltage_table *voltage_table) -{ - unsigned int i, diff; - - if (voltage_table->count <= max_voltage_steps) - return; - - diff = voltage_table->count - max_voltage_steps; - - for (i = 0; i < max_voltage_steps; i++) - voltage_table->entries[i] = voltage_table->entries[i + diff]; - - voltage_table->count = max_voltage_steps; -} - -static int ci_get_std_voltage_value_sidd(struct amdgpu_device *adev, - struct atom_voltage_table_entry *voltage_table, - u16 *std_voltage_hi_sidd, u16 *std_voltage_lo_sidd); -static int ci_set_power_limit(struct amdgpu_device *adev, u32 n); -static int ci_set_overdrive_target_tdp(struct amdgpu_device *adev, - u32 target_tdp); -static int ci_update_uvd_dpm(struct amdgpu_device *adev, bool gate); -static void ci_dpm_set_irq_funcs(struct amdgpu_device *adev); - -static PPSMC_Result amdgpu_ci_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, - PPSMC_Msg msg, u32 parameter); -static void ci_thermal_start_smc_fan_control(struct amdgpu_device *adev); -static void ci_fan_ctrl_set_default_mode(struct amdgpu_device *adev); - -static struct ci_power_info *ci_get_pi(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = adev->pm.dpm.priv; - - return pi; -} - -static struct ci_ps *ci_get_ps(struct amdgpu_ps *rps) -{ - struct ci_ps *ps = rps->ps_priv; - - return ps; -} - -static void ci_initialize_powertune_defaults(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - - switch (adev->pdev->device) { - case 0x6649: - case 0x6650: - case 0x6651: - case 0x6658: - case 0x665C: - case 0x665D: - default: - pi->powertune_defaults = &defaults_bonaire_xt; - break; - case 0x6640: - case 0x6641: - case 0x6646: - case 0x6647: - pi->powertune_defaults = &defaults_saturn_xt; - break; - case 0x67B8: - case 0x67B0: - pi->powertune_defaults = &defaults_hawaii_xt; - break; - case 0x67BA: - case 0x67B1: - pi->powertune_defaults = &defaults_hawaii_pro; - break; - case 0x67A0: - case 0x67A1: - case 0x67A2: - case 0x67A8: - case 0x67A9: - case 0x67AA: - case 0x67B9: - case 0x67BE: - pi->powertune_defaults = &defaults_bonaire_xt; - break; - } - - pi->dte_tj_offset = 0; - - pi->caps_power_containment = true; - pi->caps_cac = false; - pi->caps_sq_ramping = false; - pi->caps_db_ramping = false; - pi->caps_td_ramping = false; - pi->caps_tcp_ramping = false; - - if (pi->caps_power_containment) { - pi->caps_cac = true; - if (adev->asic_type == CHIP_HAWAII) - pi->enable_bapm_feature = false; - else - pi->enable_bapm_feature = true; - pi->enable_tdc_limit_feature = true; - pi->enable_pkg_pwr_tracking_feature = true; - } -} - -static u8 ci_convert_to_vid(u16 vddc) -{ - return (6200 - (vddc * VOLTAGE_SCALE)) / 25; -} - -static int ci_populate_bapm_vddc_vid_sidd(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - u8 *hi_vid = pi->smc_powertune_table.BapmVddCVidHiSidd; - u8 *lo_vid = pi->smc_powertune_table.BapmVddCVidLoSidd; - u8 *hi2_vid = pi->smc_powertune_table.BapmVddCVidHiSidd2; - u32 i; - - if (adev->pm.dpm.dyn_state.cac_leakage_table.entries == NULL) - return -EINVAL; - if (adev->pm.dpm.dyn_state.cac_leakage_table.count > 8) - return -EINVAL; - if (adev->pm.dpm.dyn_state.cac_leakage_table.count != - adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count) - return -EINVAL; - - for (i = 0; i < adev->pm.dpm.dyn_state.cac_leakage_table.count; i++) { - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { - lo_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1); - hi_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2); - hi2_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3); - } else { - lo_vid[i] = ci_convert_to_vid(adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc); - hi_vid[i] = ci_convert_to_vid((u16)adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage); - } - } - return 0; -} - -static int ci_populate_vddc_vid(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - u8 *vid = pi->smc_powertune_table.VddCVid; - u32 i; - - if (pi->vddc_voltage_table.count > 8) - return -EINVAL; - - for (i = 0; i < pi->vddc_voltage_table.count; i++) - vid[i] = ci_convert_to_vid(pi->vddc_voltage_table.entries[i].value); - - return 0; -} - -static int ci_populate_svi_load_line(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults; - - pi->smc_powertune_table.SviLoadLineEn = pt_defaults->svi_load_line_en; - pi->smc_powertune_table.SviLoadLineVddC = pt_defaults->svi_load_line_vddc; - pi->smc_powertune_table.SviLoadLineTrimVddC = 3; - pi->smc_powertune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int ci_populate_tdc_limit(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults; - u16 tdc_limit; - - tdc_limit = adev->pm.dpm.dyn_state.cac_tdp_table->tdc * 256; - pi->smc_powertune_table.TDC_VDDC_PkgLimit = cpu_to_be16(tdc_limit); - pi->smc_powertune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - pt_defaults->tdc_vddc_throttle_release_limit_perc; - pi->smc_powertune_table.TDC_MAWt = pt_defaults->tdc_mawt; - - return 0; -} - -static int ci_populate_dw8(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults; - int ret; - - ret = amdgpu_ci_read_smc_sram_dword(adev, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, PmFuseTable) + - offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl), - (u32 *)&pi->smc_powertune_table.TdcWaterfallCtl, - pi->sram_end); - if (ret) - return -EINVAL; - else - pi->smc_powertune_table.TdcWaterfallCtl = pt_defaults->tdc_waterfall_ctl; - - return 0; -} - -static int ci_populate_fuzzy_fan(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - - if ((adev->pm.dpm.fan.fan_output_sensitivity & (1 << 15)) || - (adev->pm.dpm.fan.fan_output_sensitivity == 0)) - adev->pm.dpm.fan.fan_output_sensitivity = - adev->pm.dpm.fan.default_fan_output_sensitivity; - - pi->smc_powertune_table.FuzzyFan_PwmSetDelta = - cpu_to_be16(adev->pm.dpm.fan.fan_output_sensitivity); - - return 0; -} - -static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - u8 *hi_vid = pi->smc_powertune_table.BapmVddCVidHiSidd; - u8 *lo_vid = pi->smc_powertune_table.BapmVddCVidLoSidd; - int i, min, max; - - min = max = hi_vid[0]; - for (i = 0; i < 8; i++) { - if (0 != hi_vid[i]) { - if (min > hi_vid[i]) - min = hi_vid[i]; - if (max < hi_vid[i]) - max = hi_vid[i]; - } - - if (0 != lo_vid[i]) { - if (min > lo_vid[i]) - min = lo_vid[i]; - if (max < lo_vid[i]) - max = lo_vid[i]; - } - } - - if ((min == 0) || (max == 0)) - return -EINVAL; - pi->smc_powertune_table.GnbLPMLMaxVid = (u8)max; - pi->smc_powertune_table.GnbLPMLMinVid = (u8)min; - - return 0; -} - -static int ci_populate_bapm_vddc_base_leakage_sidd(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - u16 hi_sidd = pi->smc_powertune_table.BapmVddCBaseLeakageHiSidd; - u16 lo_sidd = pi->smc_powertune_table.BapmVddCBaseLeakageLoSidd; - struct amdgpu_cac_tdp_table *cac_tdp_table = - adev->pm.dpm.dyn_state.cac_tdp_table; - - hi_sidd = cac_tdp_table->high_cac_leakage / 100 * 256; - lo_sidd = cac_tdp_table->low_cac_leakage / 100 * 256; - - pi->smc_powertune_table.BapmVddCBaseLeakageHiSidd = cpu_to_be16(hi_sidd); - pi->smc_powertune_table.BapmVddCBaseLeakageLoSidd = cpu_to_be16(lo_sidd); - - return 0; -} - -static int ci_populate_bapm_parameters_in_dpm_table(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - const struct ci_pt_defaults *pt_defaults = pi->powertune_defaults; - SMU7_Discrete_DpmTable *dpm_table = &pi->smc_state_table; - struct amdgpu_cac_tdp_table *cac_tdp_table = - adev->pm.dpm.dyn_state.cac_tdp_table; - struct amdgpu_ppm_table *ppm = adev->pm.dpm.dyn_state.ppm_table; - int i, j, k; - const u16 *def1; - const u16 *def2; - - dpm_table->DefaultTdp = cac_tdp_table->tdp * 256; - dpm_table->TargetTdp = cac_tdp_table->configurable_tdp * 256; - - dpm_table->DTETjOffset = (u8)pi->dte_tj_offset; - dpm_table->GpuTjMax = - (u8)(pi->thermal_temp_setting.temperature_high / 1000); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = pt_defaults->dte_ambient_temp_base; - - if (ppm) { - dpm_table->PPM_PkgPwrLimit = cpu_to_be16((u16)ppm->dgpu_tdp * 256 / 1000); - dpm_table->PPM_TemperatureLimit = cpu_to_be16((u16)ppm->tj_max * 256); - } else { - dpm_table->PPM_PkgPwrLimit = cpu_to_be16(0); - dpm_table->PPM_TemperatureLimit = cpu_to_be16(0); - } - - dpm_table->BAPM_TEMP_GRADIENT = cpu_to_be32(pt_defaults->bapm_temp_gradient); - def1 = pt_defaults->bapmti_r; - def2 = pt_defaults->bapmti_rc; - - for (i = 0; i < SMU7_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU7_DTE_SOURCES; j++) { - for (k = 0; k < SMU7_DTE_SINKS; k++) { - dpm_table->BAPMTI_R[i][j][k] = cpu_to_be16(*def1); - dpm_table->BAPMTI_RC[i][j][k] = cpu_to_be16(*def2); - def1++; - def2++; - } - } - } - - return 0; -} - -static int ci_populate_pm_base(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - u32 pm_fuse_table_offset; - int ret; - - if (pi->caps_power_containment) { - ret = amdgpu_ci_read_smc_sram_dword(adev, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, pi->sram_end); - if (ret) - return ret; - ret = ci_populate_bapm_vddc_vid_sidd(adev); - if (ret) - return ret; - ret = ci_populate_vddc_vid(adev); - if (ret) - return ret; - ret = ci_populate_svi_load_line(adev); - if (ret) - return ret; - ret = ci_populate_tdc_limit(adev); - if (ret) - return ret; - ret = ci_populate_dw8(adev); - if (ret) - return ret; - ret = ci_populate_fuzzy_fan(adev); - if (ret) - return ret; - ret = ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(adev); - if (ret) - return ret; - ret = ci_populate_bapm_vddc_base_leakage_sidd(adev); - if (ret) - return ret; - ret = amdgpu_ci_copy_bytes_to_smc(adev, pm_fuse_table_offset, - (u8 *)&pi->smc_powertune_table, - sizeof(SMU7_Discrete_PmFuses), pi->sram_end); - if (ret) - return ret; - } - - return 0; -} - -static void ci_do_enable_didt(struct amdgpu_device *adev, const bool enable) -{ - struct ci_power_info *pi = ci_get_pi(adev); - u32 data; - - if (pi->caps_sq_ramping) { - data = RREG32_DIDT(ixDIDT_SQ_CTRL0); - if (enable) - data |= DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_SQ_CTRL0, data); - } - - if (pi->caps_db_ramping) { - data = RREG32_DIDT(ixDIDT_DB_CTRL0); - if (enable) - data |= DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_DB_CTRL0, data); - } - - if (pi->caps_td_ramping) { - data = RREG32_DIDT(ixDIDT_TD_CTRL0); - if (enable) - data |= DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_TD_CTRL0, data); - } - - if (pi->caps_tcp_ramping) { - data = RREG32_DIDT(ixDIDT_TCP_CTRL0); - if (enable) - data |= DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_TCP_CTRL0, data); - } -} - -static int ci_program_pt_config_registers(struct amdgpu_device *adev, - const struct ci_pt_config_reg *cac_config_regs) -{ - const struct ci_pt_config_reg *config_regs = cac_config_regs; - u32 data; - u32 cache = 0; - - if (config_regs == NULL) - return -EINVAL; - - while (config_regs->offset != 0xFFFFFFFF) { - if (config_regs->type == CISLANDS_CONFIGREG_CACHE) { - cache |= ((config_regs->value << config_regs->shift) & config_regs->mask); - } else { - switch (config_regs->type) { - case CISLANDS_CONFIGREG_SMC_IND: - data = RREG32_SMC(config_regs->offset); - break; - case CISLANDS_CONFIGREG_DIDT_IND: - data = RREG32_DIDT(config_regs->offset); - break; - default: - data = RREG32(config_regs->offset); - break; - } - - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - data |= cache; - - switch (config_regs->type) { - case CISLANDS_CONFIGREG_SMC_IND: - WREG32_SMC(config_regs->offset, data); - break; - case CISLANDS_CONFIGREG_DIDT_IND: - WREG32_DIDT(config_regs->offset, data); - break; - default: - WREG32(config_regs->offset, data); - break; - } - cache = 0; - } - config_regs++; - } - return 0; -} - -static int ci_enable_didt(struct amdgpu_device *adev, bool enable) -{ - struct ci_power_info *pi = ci_get_pi(adev); - int ret; - - if (pi->caps_sq_ramping || pi->caps_db_ramping || - pi->caps_td_ramping || pi->caps_tcp_ramping) { - amdgpu_gfx_rlc_enter_safe_mode(adev); - - if (enable) { - ret = ci_program_pt_config_registers(adev, didt_config_ci); - if (ret) { - amdgpu_gfx_rlc_exit_safe_mode(adev); - return ret; - } - } - - ci_do_enable_didt(adev, enable); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - } - - return 0; -} - -static int ci_enable_power_containment(struct amdgpu_device *adev, bool enable) -{ - struct ci_power_info *pi = ci_get_pi(adev); - PPSMC_Result smc_result; - int ret = 0; - - if (enable) { - pi->power_containment_features = 0; - if (pi->caps_power_containment) { - if (pi->enable_bapm_feature) { - smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE); - if (smc_result != PPSMC_Result_OK) - ret = -EINVAL; - else - pi->power_containment_features |= POWERCONTAINMENT_FEATURE_BAPM; - } - - if (pi->enable_tdc_limit_feature) { - smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_TDCLimitEnable); - if (smc_result != PPSMC_Result_OK) - ret = -EINVAL; - else - pi->power_containment_features |= POWERCONTAINMENT_FEATURE_TDCLimit; - } - - if (pi->enable_pkg_pwr_tracking_feature) { - smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_PkgPwrLimitEnable); - if (smc_result != PPSMC_Result_OK) { - ret = -EINVAL; - } else { - struct amdgpu_cac_tdp_table *cac_tdp_table = - adev->pm.dpm.dyn_state.cac_tdp_table; - u32 default_pwr_limit = - (u32)(cac_tdp_table->maximum_power_delivery_limit * 256); - - pi->power_containment_features |= POWERCONTAINMENT_FEATURE_PkgPwrLimit; - - ci_set_power_limit(adev, default_pwr_limit); - } - } - } - } else { - if (pi->caps_power_containment && pi->power_containment_features) { - if (pi->power_containment_features & POWERCONTAINMENT_FEATURE_TDCLimit) - amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_TDCLimitDisable); - - if (pi->power_containment_features & POWERCONTAINMENT_FEATURE_BAPM) - amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE); - - if (pi->power_containment_features & POWERCONTAINMENT_FEATURE_PkgPwrLimit) - amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_PkgPwrLimitDisable); - pi->power_containment_features = 0; - } - } - - return ret; -} - -static int ci_enable_smc_cac(struct amdgpu_device *adev, bool enable) -{ - struct ci_power_info *pi = ci_get_pi(adev); - PPSMC_Result smc_result; - int ret = 0; - - if (pi->caps_cac) { - if (enable) { - smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_EnableCac); - if (smc_result != PPSMC_Result_OK) { - ret = -EINVAL; - pi->cac_enabled = false; - } else { - pi->cac_enabled = true; - } - } else if (pi->cac_enabled) { - amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DisableCac); - pi->cac_enabled = false; - } - } - - return ret; -} - -static int ci_enable_thermal_based_sclk_dpm(struct amdgpu_device *adev, - bool enable) -{ - struct ci_power_info *pi = ci_get_pi(adev); - PPSMC_Result smc_result = PPSMC_Result_OK; - - if (pi->thermal_sclk_dpm_enabled) { - if (enable) - smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_ENABLE_THERMAL_DPM); - else - smc_result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_DISABLE_THERMAL_DPM); - } - - if (smc_result == PPSMC_Result_OK) - return 0; - else - return -EINVAL; -} - -static int ci_power_control_set_level(struct amdgpu_device *adev) -{ - struct ci_power_info *pi = ci_get_pi(adev); - struct amdgpu_cac_tdp_table *cac_tdp_table = - adev->pm.dpm.dyn_state.cac_tdp_table; - s32 adjust_percent; - s32 target_tdp; - int ret = 0; - bool adjust_polarity = false; /* ??? */ - - if (pi->caps_power_containment) { - adjust_percent = adjust_polarity ? - adev->pm.dpm.tdp_adjustment : (-1 * adev->pm.dpm.tdp_adjustment); - target_tdp = ((100 + adjust_percent) * - (s32)cac_tdp_table->configurable_tdp) / 100; - - ret = ci_set_overdrive_target_tdp(adev, (u32)target_tdp); - } - - return ret; -} - -static void ci_dpm_powergate_uvd(void *handle, bool gate) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct ci_power_info *pi = ci_get_pi(adev); - - pi->uvd_power_gated = gate; - - if (gate) { - /* stop the UVD block */ - amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_GATE); - ci_update_uvd_dpm(adev, gate); - } else { - amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_UNGATE); - ci_update_uvd_dpm(adev, gate); - } -} - -static bool ci_dpm_vblank_too_short(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); - u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 300; - - /* disable mclk switching if the refresh is >120Hz, even if the - * blanking period would allow it - */ - if (amdgpu_dpm_get_vrefresh(adev) > 120) - return true; - - if (vblank_time < switch_limit) - return true; - else - return false; - -} - -static void ci_apply_state_adjust_rules(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - struct ci_ps *ps = ci_get_ps(rps); - struct ci_power_info *pi = ci_get_pi(adev); - struct amdgpu_clock_and_voltage_limits *max_limits; - bool disable_mclk_switching; - u32 sclk, mclk; - int i; - - if (rps->vce_active) { - rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; - rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk; - } else { - rps->evclk = 0; - rps->ecclk = 0; - } - - if ((adev->pm.dpm.new_active_crtc_count > 1) || - ci_dpm_vblank_too_short(adev)) - disable_mclk_switching = true; - else - disable_mclk_switching = false; - - if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) - pi->battery_state = true; - else - pi->battery_state = false; - - if (adev->pm.ac_power) - max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; - else - max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc; - - if (adev->pm.ac_power == false) { - for (i = 0; i < ps->performance_level_count; i++) { - if (ps->performance_levels[i].mclk > max_limits->mclk) - ps->performance_levels[i].mclk = max_limits->mclk; - if (ps->performance_levels[i].sclk > max_limits->sclk) - ps->performance_levels[i].sclk = max_limits->sclk; - } - } - - /* XXX validate the min clocks required for display */ - - if (disable_mclk_switching) { - mclk = ps->performance_levels[ps->performance_level_count - 1].mclk; - sclk = ps->performance_levels[0].sclk; - } else { - mclk = ps->performance_levels[0].mclk; - sclk = ps->performance_levels[0].sclk; - } - - if (adev->pm.pm_display_cfg.min_core_set_clock > sclk) - sclk = adev->pm.pm_display_cfg.min_core_set_clock; - - if (adev->pm.pm_display_cfg.min_mem_set_clock > mclk) - mclk = adev->pm.pm_display_cfg.min_mem_set_clock; - - if (rps->vce_active) { - if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk) - sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk; - if (mclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk) - mclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk; - } - - ps->performance_levels[0].sclk = sclk; - ps->performance_levels[0].mclk = mclk; - - if (ps->performance_levels[1].sclk < ps->performance_levels[0].sclk) - ps->performance_levels[1].sclk = ps->performance_levels[0].sclk; - - if (disable_mclk_switching) { - if (ps->performance_levels[0].mclk < ps->performance_levels[1].mclk) - ps->performance_levels[0].mclk = ps->performance_levels[1].mclk; - } else { - if (ps->performance_levels[1].mclk < ps->performance_levels[0].mclk) - ps->performance_levels[1].mclk = ps->performance_levels[0].mclk; - } -} - -static int ci_thermal_set_temperature_range(struct amdgpu_device *adev, - int min_temp, int max_temp) -{ - int low_temp = 0 * 1000; - int high_temp = 255 * 1000; - u32 tmp; - - if (low_temp < min_temp) - low_temp = min_temp; - if (high_temp > max_temp) - high_temp = max_temp; - if (high_temp < low_temp) { - DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); - return -EINVAL; - } - - tmp = RREG32_SMC(ixCG_THERMAL_INT); - tmp &= ~(CG_THERMAL_INT__DIG_THERM_INTH_MASK | CG_THERMAL_INT__DIG_THERM_INTL_MASK); - tmp |= ((high_temp / 1000) << CG_THERMAL_INT__DIG_THERM_INTH__SHIFT) | - ((low_temp / 1000)) << CG_THERMAL_INT__DIG_THERM_INTL__SHIFT; - WREG32_SMC(ixCG_THERMAL_INT, tmp); - -#if 0 - /* XXX: need to figure out how to handle this properly */ - tmp = RREG32_SMC(ixCG_THERMAL_CTRL); - tmp &= DIG_THERM_DPM_MASK; - tmp |= DIG_THERM_DPM(high_temp / 1000); - WREG32_SMC(ixCG_THERMAL_CTRL, tmp); -#endif - - adev->pm.dpm.thermal.min_temp = low_temp; - adev->pm.dpm.thermal.max_temp = high_temp; - return 0; -} - -static int ci_thermal_enable_alert(struct amdgpu_device *adev, - bool enable) -{ - u32 thermal_int = RREG32_SMC(ixCG_THERMAL_INT); - PPSMC_Result result; - - if (enable) { - thermal_int &= ~(CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK | - CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK); - WREG32_SMC(ixCG_THERMAL_INT, thermal_int); - result = amdgpu_ci_send_msg_to_smc(adev, PPSMC_MSG_Thermal_Cntl_Enable); - if (result != PPSMC_Result_OK) { - DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); |
