/* * 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("radeon/bonaire_smc.bin");MODULE_FIRMWARE("radeon/bonaire_k_smc.bin");MODULE_FIRMWARE("radeon/hawaii_smc.bin");MODULE_FIRMWARE("radeon/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 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 0static 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 0static 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_dpm_funcs(struct amdgpu_device *adev);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); Lines 1–500 of 7053. Load more
/* * 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("radeon/bonaire_smc.bin"); MODULE_FIRMWARE("radeon/bonaire_k_smc.bin"); MODULE_FIRMWARE("radeon/hawaii_smc.bin"); MODULE_FIRMWARE("radeon/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 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_dpm_funcs(struct amdgpu_device *adev); 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);