diff options
Diffstat (limited to 'drivers/gpu/drm/amd/pm/powerplay')
41 files changed, 1870 insertions, 867 deletions
diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index eab9768029c1..e0d288208220 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -1629,6 +1629,24 @@ static ssize_t pp_get_gpu_metrics(void *handle, void **table) return size; } +static int pp_gfx_state_change_set(void *handle, uint32_t state) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->gfx_state_change == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->gfx_state_change(hwmgr, state); + mutex_unlock(&hwmgr->smu_lock); + return 0; +} + static const struct amd_pm_funcs pp_dpm_funcs = { .load_firmware = pp_dpm_load_fw, .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, @@ -1691,4 +1709,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = { .set_df_cstate = pp_set_df_cstate, .set_xgmi_pstate = pp_set_xgmi_pstate, .get_gpu_metrics = pp_get_gpu_metrics, + .gfx_state_change_set = pp_gfx_state_change_set, }; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c index 3be40114e63d..45f608838f6e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c @@ -142,12 +142,12 @@ static const struct baco_cmd_entry exit_baco_tbl[] = { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, { CMD_DELAY_MS, 0, 0, 0, 20, 0 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x20 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x10 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } }; @@ -155,6 +155,7 @@ static const struct baco_cmd_entry exit_baco_tbl[] = static const struct baco_cmd_entry clean_baco_tbl[] = { { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }, { CMD_WRITE, mmCP_PFP_UCODE_ADDR, 0, 0, 0, 0 } }; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c index 1f9b9facdf1f..25b5831a15cd 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c @@ -223,11 +223,11 @@ int phm_register_irq_handlers(struct pp_hwmgr *hwmgr) } /** -* Initializes the thermal controller subsystem. -* -* @param pHwMgr the address of the powerplay hardware manager. -* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher. -*/ + * phm_start_thermal_controller - Initializes the thermal controller subsystem. + * + * @hwmgr: the address of the powerplay hardware manager. + * Exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher. + */ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr) { int ret = 0; @@ -371,13 +371,14 @@ int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_s /** -* Gets Clock Info. -* -* @param pHwMgr the address of the powerplay hardware manager. -* @param pPowerState the address of the Power State structure. -* @param pClockInfo the address of PP_ClockInfo structure where the result will be returned. -* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end. -*/ + * phm_get_clock_info + * + * @hwmgr: the address of the powerplay hardware manager. + * @state: the address of the Power State structure. + * @pclock_info: the address of PP_ClockInfo structure where the result will be returned. + * @designation: PHM performance level designation + * Exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end. + */ int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *pclock_info, PHM_PerformanceLevelDesignation designation) { @@ -514,34 +515,3 @@ int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) return hwmgr->hwmgr_func->set_active_display_count(hwmgr, count); } - -int phm_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) - return -EINVAL; - - return hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); -} - -int phm_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq) - return -EINVAL; - - return hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); -} - -int phm_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_hard_min_fclk_by_freq) - return -EINVAL; - - return hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); -} - diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c index f48fdc7f0382..6a7de8b898fa 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c @@ -46,11 +46,7 @@ extern const struct pp_smumgr_func vega12_smu_funcs; extern const struct pp_smumgr_func smu10_smu_funcs; extern const struct pp_smumgr_func vega20_smu_funcs; -extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr); -extern int smu8_init_function_pointers(struct pp_hwmgr *hwmgr); extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr); -extern int vega12_hwmgr_init(struct pp_hwmgr *hwmgr); -extern int vega20_hwmgr_init(struct pp_hwmgr *hwmgr); extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr); @@ -479,11 +475,17 @@ int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_RegulatorHot); phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_AutomaticDCTransition); - if (hwmgr->chip_id != CHIP_POLARIS10) + if (((hwmgr->chip_id == CHIP_POLARIS11) && !hwmgr->is_kicker) || + (hwmgr->chip_id == CHIP_POLARIS12)) phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SPLLShutdownSupport); + PHM_PlatformCaps_SPLLShutdownSupport); if (hwmgr->chip_id != CHIP_POLARIS11) { phm_cap_set(hwmgr->platform_descriptor.platformCaps, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h index c0193e09d58a..729615aff126 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h @@ -48,7 +48,7 @@ typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_volta struct phm_ppt_v1_clock_voltage_dependency_table { uint32_t count; /* Number of entries. */ - phm_ppt_v1_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ + phm_ppt_v1_clock_voltage_dependency_record entries[]; /* Dynamically allocate count entries. */ }; typedef struct phm_ppt_v1_clock_voltage_dependency_table phm_ppt_v1_clock_voltage_dependency_table; @@ -71,7 +71,7 @@ typedef struct phm_ppt_v1_mm_clock_voltage_dependency_record phm_ppt_v1_mm_clock struct phm_ppt_v1_mm_clock_voltage_dependency_table { uint32_t count; /* Number of entries. */ - phm_ppt_v1_mm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ + phm_ppt_v1_mm_clock_voltage_dependency_record entries[]; /* Dynamically allocate count entries. */ }; typedef struct phm_ppt_v1_mm_clock_voltage_dependency_table phm_ppt_v1_mm_clock_voltage_dependency_table; @@ -86,7 +86,7 @@ typedef struct phm_ppt_v1_voltage_lookup_record phm_ppt_v1_voltage_lookup_record struct phm_ppt_v1_voltage_lookup_table { uint32_t count; - phm_ppt_v1_voltage_lookup_record entries[1]; /* Dynamically allocate count entries. */ + phm_ppt_v1_voltage_lookup_record entries[]; /* Dynamically allocate count entries. */ }; typedef struct phm_ppt_v1_voltage_lookup_table phm_ppt_v1_voltage_lookup_table; @@ -103,7 +103,7 @@ typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record; struct phm_ppt_v1_pcie_table { uint32_t count; /* Number of entries. */ - phm_ppt_v1_pcie_record entries[1]; /* Dynamically allocate count entries. */ + phm_ppt_v1_pcie_record entries[]; /* Dynamically allocate count entries. */ }; typedef struct phm_ppt_v1_pcie_table phm_ppt_v1_pcie_table; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c index 31a32a79cfc2..67d7da0b6fed 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c @@ -74,6 +74,13 @@ int psm_init_power_state_table(struct pp_hwmgr *hwmgr) for (i = 0; i < table_entries; i++) { result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); + if (result) { + kfree(hwmgr->request_ps); + kfree(hwmgr->ps); + hwmgr->request_ps = NULL; + hwmgr->ps = NULL; + return -EINVAL; + } if (state->classification.flags & PP_StateClassificationFlag_Boot) { hwmgr->boot_ps = state; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c index 01dc46dc9c8a..83a6504e093c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c @@ -92,11 +92,11 @@ static int atomctrl_retrieve_ac_timing( } /** - * Get memory clock AC timing registers index from VBIOS table + * atomctrl_set_mc_reg_address_table - Get memory clock AC timing registers index from VBIOS table * VBIOS set end of memory clock AC timing registers by ucPreRegDataLength bit6 = 1 - * @param reg_block the address ATOM_INIT_REG_BLOCK - * @param table the address of MCRegTable - * @return 0 + * @reg_block: the address ATOM_INIT_REG_BLOCK + * @table: the address of MCRegTable + * Return: 0 */ static int atomctrl_set_mc_reg_address_table( ATOM_INIT_REG_BLOCK *reg_block, @@ -166,7 +166,44 @@ int atomctrl_initialize_mc_reg_table( return result; } -/** +int atomctrl_initialize_mc_reg_table_v2_2( + struct pp_hwmgr *hwmgr, + uint8_t module_index, + pp_atomctrl_mc_reg_table *table) +{ + ATOM_VRAM_INFO_HEADER_V2_2 *vram_info; + ATOM_INIT_REG_BLOCK *reg_block; + int result = 0; + u8 frev, crev; + u16 size; + + vram_info = (ATOM_VRAM_INFO_HEADER_V2_2 *) + smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, VRAM_Info), &size, &frev, &crev); + + if (module_index >= vram_info->ucNumOfVRAMModule) { + pr_err("Invalid VramInfo table."); + result = -1; + } else if (vram_info->sHeader.ucTableFormatRevision < 2) { + pr_err("Invalid VramInfo table."); + result = -1; + } + + if (0 == result) { + reg_block = (ATOM_INIT_REG_BLOCK *) + ((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset)); + result = atomctrl_set_mc_reg_address_table(reg_block, table); + } + + if (0 == result) { + result = atomctrl_retrieve_ac_timing(module_index, + reg_block, table); + } + + return result; +} + +/* * Set DRAM timings based on engine clock and memory clock. */ int atomctrl_set_engine_dram_timings_rv770( @@ -192,7 +229,7 @@ int atomctrl_set_engine_dram_timings_rv770( (uint32_t *)&engine_clock_parameters); } -/** +/* * Private Function to get the PowerPlay Table Address. * WARNING: The tabled returned by this function is in * dynamically allocated memory. @@ -237,12 +274,13 @@ static const ATOM_VOLTAGE_OBJECT_V3 *atomctrl_lookup_voltage_type_v3( return NULL; } -/** atomctrl_get_memory_pll_dividers_si(). +/** + * atomctrl_get_memory_pll_dividers_si(). * - * @param hwmgr input parameter: pointer to HwMgr - * @param clock_value input parameter: memory clock - * @param dividers output parameter: memory PLL dividers - * @param strobe_mode input parameter: 1 for strobe mode, 0 for performance mode + * @hwmgr: input parameter: pointer to HwMgr + * @clock_value: input parameter: memory clock + * @dividers: output parameter: memory PLL dividers + * @strobe_mode: input parameter: 1 for strobe mode, 0 for performance mode */ int atomctrl_get_memory_pll_dividers_si( struct pp_hwmgr *hwmgr, @@ -289,11 +327,12 @@ int atomctrl_get_memory_pll_dividers_si( return result; } -/** atomctrl_get_memory_pll_dividers_vi(). +/** + * atomctrl_get_memory_pll_dividers_vi(). * - * @param hwmgr input parameter: pointer to HwMgr - * @param clock_value input parameter: memory clock - * @param dividers output parameter: memory PLL dividers + * @hwmgr: input parameter: pointer to HwMgr + * @clock_value: input parameter: memory clock + * @dividers: output parameter: memory PLL dividers */ int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param) @@ -475,7 +514,7 @@ int atomctrl_get_dfs_pll_dividers_vi( return result; } -/** +/* * Get the reference clock in 10KHz */ uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr) @@ -498,7 +537,7 @@ uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr) return clock; } -/** +/* * Returns true if the given voltage type is controlled by GPIO pins. * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, * SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. @@ -593,7 +632,7 @@ static bool atomctrl_lookup_gpio_pin( return false; } -/** +/* * Private Function to get the PowerPlay Table Address. * WARNING: The tabled returned by this function is in * dynamically allocated memory. @@ -616,7 +655,7 @@ static ATOM_GPIO_PIN_LUT *get_gpio_lookup_table(void *device) return (ATOM_GPIO_PIN_LUT *)table_address; } -/** +/* * Returns 1 if the given pin id find in lookup table. */ bool atomctrl_get_pp_assign_pin( @@ -662,7 +701,7 @@ int atomctrl_calculate_voltage_evv_on_sclk( fInt fMargin_RO_a, fMargin_RO_b, fMargin_RO_c, fMargin_fixed, fMargin_FMAX_mean, fMargin_Plat_mean, fMargin_FMAX_sigma, fMargin_Plat_sigma, fMargin_DC_sigma; fInt fLkg_FT, repeat; fInt fMicro_FMAX, fMicro_CR, fSigma_FMAX, fSigma_CR, fSigma_DC, fDC_SCLK, fSquared_Sigma_DC, fSquared_Sigma_CR, fSquared_Sigma_FMAX; - fInt fRLL_LoadLine, fPowerDPMx, fDerateTDP, fVDDC_base, fA_Term, fC_Term, fB_Term, fRO_DC_margin; + fInt fRLL_LoadLine, fDerateTDP, fVDDC_base, fA_Term, fC_Term, fB_Term, fRO_DC_margin; fInt fRO_fused, fCACm_fused, fCACb_fused, fKv_m_fused, fKv_b_fused, fKt_Beta_fused, fFT_Lkg_V0NORM; fInt fSclk_margin, fSclk, fEVV_V; fInt fV_min, fV_max, fT_prod, fLKG_Factor, fT_FT, fV_FT, fV_x, fTDP_Power, fTDP_Power_right, fTDP_Power_left, fTDP_Current, fV_NL; @@ -694,36 +733,28 @@ int atomctrl_calculate_voltage_evv_on_sclk( switch (dpm_level) { case 1: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm1)); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM1), 1000); break; case 2: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm2)); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM2), 1000); break; case 3: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm3)); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM3), 1000); break; case 4: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm4)); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM4), 1000); break; case 5: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm5)); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM5), 1000); break; case 6: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm6)); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM6), 1000); break; case 7: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm7)); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM7), 1000); break; default: pr_err("DPM Level not supported\n"); - fPowerDPMx = Convert_ULONG_ToFraction(1); fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM0), 1000); } @@ -1072,14 +1103,15 @@ int atomctrl_calculate_voltage_evv_on_sclk( return result; } -/** atomctrl_get_voltage_evv_on_sclk gets voltage via call to ATOM COMMAND table. - * @param hwmgr input: pointer to hwManager - * @param voltage_type input: type of EVV voltage VDDC or VDDGFX - * @param sclk input: in 10Khz unit. DPM state SCLK frequency - * which is define in PPTable SCLK/VDDC dependence - * table associated with this virtual_voltage_Id - * @param virtual_voltage_Id input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 - * @param voltage output: real voltage level in unit of mv +/** + * atomctrl_get_voltage_evv_on_sclk gets voltage via call to ATOM COMMAND table. + * @hwmgr: input: pointer to hwManager + * @voltage_type: input: type of EVV voltage VDDC or VDDGFX + * @sclk: input: in 10Khz unit. DPM state SCLK frequency + * which is define in PPTable SCLK/VDDC dependence + * table associated with this virtual_voltage_Id + * @virtual_voltage_Id: input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 + * @voltage: output: real voltage level in unit of mv */ int atomctrl_get_voltage_evv_on_sclk( struct pp_hwmgr *hwmgr, @@ -1113,9 +1145,9 @@ int atomctrl_get_voltage_evv_on_sclk( /** * atomctrl_get_voltage_evv gets voltage via call to ATOM COMMAND table. - * @param hwmgr input: pointer to hwManager - * @param virtual_voltage_id input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 - * @param voltage output: real voltage level in unit of mv + * @hwmgr: input: pointer to hwManager + * @virtual_voltage_id: input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 + * @voltage: output: real voltage level in unit of mv */ int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, uint16_t virtual_voltage_id, @@ -1158,7 +1190,7 @@ int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, return result; } -/** +/* * Get the mpll reference clock in 10KHz */ uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr) @@ -1191,7 +1223,7 @@ uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr) return clock; } -/** +/* * Get the asic internal spread spectrum table */ static ATOM_ASIC_INTERNAL_SS_INFO *asic_internal_ss_get_ss_table(void *device) @@ -1208,7 +1240,18 @@ static ATOM_ASIC_INTERNAL_SS_INFO *asic_internal_ss_get_ss_table(void *device) return table; } -/** +bool atomctrl_is_asic_internal_ss_supported(struct pp_hwmgr *hwmgr) +{ + ATOM_ASIC_INTERNAL_SS_INFO *table = + asic_internal_ss_get_ss_table(hwmgr->adev); + + if (table) + return true; + else + return false; +} + +/* * Get the asic internal spread spectrum assignment */ static int asic_internal_ss_get_ss_asignment(struct pp_hwmgr *hwmgr, @@ -1271,7 +1314,7 @@ static int asic_internal_ss_get_ss_asignment(struct pp_hwmgr *hwmgr, return entry_found ? 0 : 1; } -/** +/* * Get the memory clock spread spectrum info */ int atomctrl_get_memory_clock_spread_spectrum( @@ -1282,7 +1325,8 @@ int atomctrl_get_memory_clock_spread_spectrum( return asic_internal_ss_get_ss_asignment(hwmgr, ASIC_INTERNAL_MEMORY_SS, memory_clock, ssInfo); } -/** + +/* * Get the engine clock spread spectrum info */ int atomctrl_get_engine_clock_spread_spectrum( @@ -1295,12 +1339,18 @@ int atomctrl_get_engine_clock_spread_spectrum( } int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index, - uint16_t end_index, uint32_t mask, uint32_t *efuse) + uint16_t end_index, uint32_t *efuse) { struct amdgpu_device *adev = hwmgr->adev; + uint32_t mask; int result; READ_EFUSE_VALUE_PARAMETER efuse_param; + if ((end_index - start_index) == 31) + mask = 0xFFFFFFFF; + else + mask = (1 << ((end_index - start_index) + 1)) - 1; + efuse_param.sEfuse.usEfuseIndex = cpu_to_le16((start_index / 32) * 4); efuse_param.sEfuse.ucBitShift = (uint8_t) (start_index - ((start_index / 32) * 32)); @@ -1384,6 +1434,20 @@ int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctr return 0; } +int atomctrl_get_vddc_shared_railinfo(struct pp_hwmgr *hwmgr, uint8_t *shared_rail) +{ + ATOM_SMU_INFO_V2_1 *psmu_info = + (ATOM_SMU_INFO_V2_1 *)smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, SMU_Info), + NULL, NULL, NULL); + if (!psmu_info) + return -1; + + *shared_rail = psmu_info->ucSharePowerSource; + + return 0; +} + int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param) { @@ -1560,3 +1624,56 @@ void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, *max_vddc = 0; *min_vddc = 0; } + +int atomctrl_get_edc_hilo_leakage_offset_table(struct pp_hwmgr *hwmgr, + AtomCtrl_HiLoLeakageOffsetTable *table) +{ + ATOM_GFX_INFO_V2_3 *gfxinfo = smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, GFX_Info), + NULL, NULL, NULL); + if (!gfxinfo) + return -ENOENT; + + table->usHiLoLeakageThreshold = gfxinfo->usHiLoLeakageThreshold; + table->usEdcDidtLoDpm7TableOffset = gfxinfo->usEdcDidtLoDpm7TableOffset; + table->usEdcDidtHiDpm7TableOffset = gfxinfo->usEdcDidtHiDpm7TableOffset; + + return 0; +} + +static AtomCtrl_EDCLeakgeTable *get_edc_leakage_table(struct pp_hwmgr *hwmgr, + uint16_t offset) +{ + void *table_address; + char *temp; + + table_address = smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, GFX_Info), + NULL, NULL, NULL); + if (!table_address) + return NULL; + + temp = (char *)table_address; + table_address += offset; + + return (AtomCtrl_EDCLeakgeTable *)temp; +} + +int atomctrl_get_edc_leakage_table(struct pp_hwmgr *hwmgr, + AtomCtrl_EDCLeakgeTable *table, + uint16_t offset) +{ + uint32_t length, i; + AtomCtrl_EDCLeakgeTable *leakage_table = + get_edc_leakage_table(hwmgr, offset); + + if (!leakage_table) + return -ENOENT; + + length = sizeof(leakage_table->DIDT_REG) / + sizeof(leakage_table->DIDT_REG[0]); + for (i = 0; i < length; i++) + table->DIDT_REG[i] = leakage_table->DIDT_REG[i]; + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h index 76ed2e413594..b3103bd4be42 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h @@ -278,13 +278,30 @@ struct pp_atom_ctrl__avfs_parameters { uint8_t ucReserved; }; +struct _AtomCtrl_HiLoLeakageOffsetTable +{ + USHORT usHiLoLeakageThreshold; + USHORT usEdcDidtLoDpm7TableOffset; + USHORT usEdcDidtHiDpm7TableOffset; +}; +typedef struct _AtomCtrl_HiLoLeakageOffsetTable AtomCtrl_HiLoLeakageOffsetTable; + +struct _AtomCtrl_EDCLeakgeTable +{ + ULONG DIDT_REG[24]; +}; +typedef struct _AtomCtrl_EDCLeakgeTable AtomCtrl_EDCLeakgeTable; + extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment); extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage); extern int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, uint16_t virtual_voltage_id, uint16_t *voltage); extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr); + +bool atomctrl_is_asic_internal_ss_supported(struct pp_hwmgr *hwmgr); extern int atomctrl_get_memory_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t memory_clock, pp_atomctrl_internal_ss_info *ssInfo); extern int atomctrl_get_engine_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t engine_clock, pp_atomctrl_internal_ss_info *ssInfo); extern int atomctrl_initialize_mc_reg_table(struct pp_hwmgr *hwmgr, uint8_t module_index, pp_atomctrl_mc_reg_table *table); +extern int atomctrl_initialize_mc_reg_table_v2_2(struct pp_hwmgr *hwmgr, uint8_t module_index, pp_atomctrl_mc_reg_table *table); extern int atomctrl_set_engine_dram_timings_rv770(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint32_t memory_clock); extern uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr); extern int atomctrl_get_memory_pll_dividers_si(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param, bool strobe_mode); @@ -300,7 +317,7 @@ extern int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_kong *dividers); extern int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index, - uint16_t end_index, uint32_t mask, uint32_t *efuse); + uint16_t end_index, uint32_t *efuse); extern int atomctrl_calculate_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage, uint16_t dpm_level, bool debug); extern int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_ai *dividers); @@ -324,5 +341,14 @@ extern int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t * extern void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, uint32_t *min_vddc); + +extern int atomctrl_get_edc_hilo_leakage_offset_table(struct pp_hwmgr *hwmgr, + AtomCtrl_HiLoLeakageOffsetTable *table); + +extern int atomctrl_get_edc_leakage_table(struct pp_hwmgr *hwmgr, + AtomCtrl_EDCLeakgeTable *table, + uint16_t offset); + +extern int atomctrl_get_vddc_shared_railinfo(struct pp_hwmgr *hwmgr, uint8_t *shared_rail); #endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c index 615cf2c09e54..a47a47238e2b 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c @@ -68,11 +68,11 @@ static struct atom_voltage_objects_info_v4_1 *pp_atomfwctrl_get_voltage_info_tab return (struct atom_voltage_objects_info_v4_1 *)table_address; } -/** -* Returns TRUE if the given voltage type is controlled by GPIO pins. -* voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. -* voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE -*/ +/* + * Returns TRUE if the given voltage type is controlled by GPIO pins. + * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. + * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE + */ bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode) { @@ -202,9 +202,9 @@ static bool pp_atomfwctrl_lookup_gpio_pin( return false; } -/** -* Returns TRUE if the given pin id find in lookup table. -*/ +/* + * Returns TRUE if the given pin id find in lookup table. + */ bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pin_id, struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) @@ -224,10 +224,10 @@ bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, return ret; } -/** -* Enter to SelfRefresh mode. -* @param hwmgr -*/ +/* + * Enter to SelfRefresh mode. + * @param hwmgr + */ int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr) { /* 0 - no action diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h index 8f50a038396c..dac29fe6cfc6 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h @@ -333,14 +333,14 @@ static fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */ { fInt Product; int64_t tempProduct; + + /*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/ + /* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION bool X_LessThanOne, Y_LessThanOne; X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0); Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0); - /*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/ - /* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION - if (X_LessThanOne && Y_LessThanOne) { Product.full = X.full * Y.full; return Product diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h index 1e870f58dd12..b0ac4d121adc 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h @@ -315,6 +315,36 @@ typedef struct _ATOM_Fiji_Fan_Table { USHORT usReserved; } ATOM_Fiji_Fan_Table; +typedef struct _ATOM_Polaris_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ + USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + USHORT usTMed; /* The middle temperature where we change slopes. */ + USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ + USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ + USHORT usPWMHigh; /* The PWM value at THigh. */ + USHORT usTMax; /* The max temperature */ + UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ + USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ + USHORT usFanRPMMax; /* The default value in RPM */ + ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ + UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + USHORT usFanGainEdge; + USHORT usFanGainHotspot; + USHORT usFanGainLiquid; + USHORT usFanGainVrVddc; + USHORT usFanGainVrMvdd; + USHORT usFanGainPlx; + USHORT usFanGainHbm; + UCHAR ucEnableZeroRPM; + UCHAR ucFanStopTemperature; + UCHAR ucFanStartTemperature; + USHORT usReserved; +} ATOM_Polaris_Fan_Table; + typedef struct _ATOM_Tonga_Thermal_Controller { UCHAR ucRevId; UCHAR ucType; /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */ @@ -389,6 +419,42 @@ typedef struct _ATOM_Fiji_PowerTune_Table { USHORT usReserved; } ATOM_Fiji_PowerTune_Table; +typedef struct _ATOM_Polaris_PowerTune_Table +{ + UCHAR ucRevId; + USHORT usTDP; + USHORT usConfigurableTDP; + USHORT usTDC; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usLowCACLeakage; + USHORT usHighCACLeakage; + USHORT usMaximumPowerDeliveryLimit; + USHORT usTjMax; // For Fiji, this is also usTemperatureLimitEdge; + USHORT usPowerTuneDataSetID; + USHORT usEDCLimit; + USHORT usSoftwareShutdownTemp; + USHORT usClockStretchAmount; + USHORT usTemperatureLimitHotspot; //The following are added for Fiji + USHORT usTemperatureLimitLiquid1; + USHORT usTemperatureLimitLiquid2; + USHORT usTemperatureLimitVrVddc; + USHORT usTemperatureLimitVrMvdd; + USHORT usTemperatureLimitPlx; + UCHAR ucLiquid1_I2C_address; //Liquid + UCHAR ucLiquid2_I2C_address; + UCHAR ucLiquid_I2C_Line; + UCHAR ucVr_I2C_address; //VR + UCHAR ucVr_I2C_Line; + UCHAR ucPlx_I2C_address; //PLX + UCHAR ucPlx_I2C_Line; + USHORT usBoostPowerLimit; + UCHAR ucCKS_LDO_REFSEL; + UCHAR ucHotSpotOnly; + UCHAR ucReserve; + USHORT usReserve; +} ATOM_Polaris_PowerTune_Table; + #define ATOM_PPM_A_A 1 #define ATOM_PPM_A_I 2 typedef struct _ATOM_Tonga_PPM_Table { diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c index b760f95e7fa7..741e03ad5311 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c @@ -32,10 +32,10 @@ #include "pptable_v1_0.h" /** - * Private Function used during initialization. - * @param hwmgr Pointer to the hardware manager. - * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE). - * @param cap Which capability to set/reset. + * set_hw_cap - Private Function used during initialization. + * @hwmgr: Pointer to the hardware manager. + * @setIt: A flag indication if the capability should be set (TRUE) or reset (FALSE). + * @cap: Which capability to set/reset. */ static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap) { @@ -47,10 +47,10 @@ static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_cap /** - * Private Function used during initialization. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_caps the bit array (from BIOS) of capability bits. - * @exception the current implementation always returns 1. + * set_platform_caps - Private Function used during initialization. + * @hwmgr: Pointer to the hardware manager. + * @powerplay_caps: the bit array (from BIOS) of capability bits. + * Exception: the current implementation always returns 1. */ static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) { @@ -128,7 +128,7 @@ static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) return 0; } -/** +/* * Private Function to get the PowerPlay Table Address. */ static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) @@ -157,7 +157,7 @@ static int get_vddc_lookup_table( uint32_t max_levels ) { - uint32_t table_size, i; + uint32_t i; phm_ppt_v1_voltage_lookup_table *table; phm_ppt_v1_voltage_lookup_record *record; ATOM_Tonga_Voltage_Lookup_Record *atom_record; @@ -165,12 +165,8 @@ static int get_vddc_lookup_table( PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), "Invalid CAC Leakage PowerPlay Table!", return 1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; - - table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == table) + table = kzalloc(struct_size(table, entries, max_levels), GFP_KERNEL); + if (!table) return -ENOMEM; table->count = vddc_lookup_pp_tables->ucNumEntries; @@ -195,10 +191,10 @@ static int get_vddc_lookup_table( } /** - * Private Function used during initialization. + * get_platform_power_management_table - Private Function used during initialization. * Initialize Platform Power Management Parameter table - * @param hwmgr Pointer to the hardware manager. - * @param atom_ppm_table Pointer to PPM table in VBIOS + * @hwmgr: Pointer to the hardware manager. + * @atom_ppm_table: Pointer to PPM table in VBIOS */ static int get_platform_power_management_table( struct pp_hwmgr *hwmgr, @@ -238,10 +234,10 @@ static int get_platform_power_management_table( } /** - * Private Function used during initialization. + * init_dpm_2_parameters - Private Function used during initialization. * Initialize TDP limits for DPM2 - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. + * @hwmgr: Pointer to the hardware manager. + * @powerplay_table: Pointer to the PowerPlay Table. */ static int init_dpm_2_parameters( struct pp_hwmgr *hwmgr, @@ -318,19 +314,16 @@ static int get_valid_clk( phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table ) { - uint32_t table_size, i; + uint32_t i; struct phm_clock_array *table; phm_ppt_v1_clock_voltage_dependency_record *dep_record; PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(uint32_t) * clk_volt_pp_table->count; - - table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == table) + table = kzalloc(struct_size(table, values, clk_volt_pp_table->count), + GFP_KERNEL); + if (!table) return -ENOMEM; table->count = (uint32_t)clk_volt_pp_table->count; @@ -370,7 +363,7 @@ static int get_mclk_voltage_dependency_table( ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table ) { - uint32_t table_size, i; + uint32_t i; phm_ppt_v1_clock_voltage_dependency_table *mclk_table; phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record; ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; @@ -378,12 +371,9 @@ static int get_mclk_voltage_dependency_table( PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * mclk_dep_table->ucNumEntries; - - mclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == mclk_table) + mclk_table = kzalloc(struct_size(mclk_table, entries, mclk_dep_table->ucNumEntries), + GFP_KERNEL); + if (!mclk_table) return -ENOMEM; mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; @@ -413,7 +403,7 @@ static int get_sclk_voltage_dependency_table( PPTable_Generic_SubTable_Header const *sclk_dep_table ) { - uint32_t table_size, i; + uint32_t i; phm_ppt_v1_clock_voltage_dependency_table *sclk_table; phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record; @@ -425,12 +415,9 @@ static int get_sclk_voltage_dependency_table( PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * tonga_table->ucNumEntries; - - sclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == sclk_table) + sclk_table = kzalloc(struct_size(sclk_table, entries, tonga_table->ucNumEntries), + GFP_KERNEL); + if (!sclk_table) return -ENOMEM; sclk_table->count = (uint32_t)tonga_table->ucNumEntries; @@ -457,12 +444,9 @@ static int get_sclk_voltage_dependency_table( PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * polaris_table->ucNumEntries; - - sclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == sclk_table) + sclk_table = kzalloc(struct_size(sclk_table, entries, polaris_table->ucNumEntries), + GFP_KERNEL); + if (!sclk_table) return -ENOMEM; sclk_table->count = (uint32_t)polaris_table->ucNumEntries; @@ -494,7 +478,7 @@ static int get_pcie_table( PPTable_Generic_SubTable_Header const *ptable ) { - uint32_t table_size, i, pcie_count; + uint32_t i, pcie_count; phm_ppt_v1_pcie_table *pcie_table; struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); @@ -507,12 +491,10 @@ static int get_pcie_table( PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - - if (pcie_table == NULL) + pcie_table = kzalloc(struct_size(pcie_table, entries, + atom_pcie_table->ucNumEntries), + GFP_KERNEL); + if (!pcie_table) return -ENOMEM; /* @@ -546,12 +528,10 @@ static int get_pcie_table( PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - - if (pcie_table == NULL) + pcie_table = kzalloc(struct_size(pcie_table, entries, + atom_pcie_table->ucNumEntries), + GFP_KERNEL); + if (!pcie_table) return -ENOMEM; /* @@ -633,7 +613,7 @@ static int get_cac_tdp_table( le16_to_cpu(tonga_table->usSoftwareShutdownTemp); tdp_table->usClockStretchAmount = le16_to_cpu(tonga_table->usClockStretchAmount); - } else { /* Fiji and newer */ + } else if (table->ucRevId < 4) { /* Fiji and newer */ const ATOM_Fiji_PowerTune_Table *fijitable = (ATOM_Fiji_PowerTune_Table *)table; tdp_table->usTDP = le16_to_cpu(fijitable->usTDP); @@ -677,6 +657,53 @@ static int get_cac_tdp_table( tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line; tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address; tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line; + } else { + const ATOM_Polaris_PowerTune_Table *polaristable = + (ATOM_Polaris_PowerTune_Table *)table; + tdp_table->usTDP = le16_to_cpu(polaristable->usTDP); + tdp_table->usConfigurableTDP = le16_to_cpu(polaristable->usConfigurableTDP); + tdp_table->usTDC = le16_to_cpu(polaristable->usTDC); + tdp_table->usBatteryPowerLimit = le16_to_cpu(polaristable->usBatteryPowerLimit); + tdp_table->usSmallPowerLimit = le16_to_cpu(polaristable->usSmallPowerLimit); + tdp_table->usLowCACLeakage = le16_to_cpu(polaristable->usLowCACLeakage); + tdp_table->usHighCACLeakage = le16_to_cpu(polaristable->usHighCACLeakage); + tdp_table->usMaximumPowerDeliveryLimit = + le16_to_cpu(polaristable->usMaximumPowerDeliveryLimit); + tdp_table->usDefaultTargetOperatingTemp = + le16_to_cpu(polaristable->usTjMax); + tdp_table->usTargetOperatingTemp = + le16_to_cpu(polaristable->usTjMax); /*Set the initial temp to the same as default */ + tdp_table->usPowerTuneDataSetID = + le16_to_cpu(polaristable->usPowerTuneDataSetID); + tdp_table->usSoftwareShutdownTemp = + le16_to_cpu(polaristable->usSoftwareShutdownTemp); + tdp_table->usClockStretchAmount = + le16_to_cpu(polaristable->usClockStretchAmount); + tdp_table->usTemperatureLimitHotspot = + le16_to_cpu(polaristable->usTemperatureLimitHotspot); + tdp_table->usTemperatureLimitLiquid1 = + le16_to_cpu(polaristable->usTemperatureLimitLiquid1); + tdp_table->usTemperatureLimitLiquid2 = + le16_to_cpu(polaristable->usTemperatureLimitLiquid2); + tdp_table->usTemperatureLimitVrVddc = + le16_to_cpu(polaristable->usTemperatureLimitVrVddc); + tdp_table->usTemperatureLimitVrMvdd = + le16_to_cpu(polaristable->usTemperatureLimitVrMvdd); + tdp_table->usTemperatureLimitPlx = + le16_to_cpu(polaristable->usTemperatureLimitPlx); + tdp_table->ucLiquid1_I2C_address = + polaristable->ucLiquid1_I2C_address; + tdp_table->ucLiquid2_I2C_address = + polaristable->ucLiquid2_I2C_address; + tdp_table->ucLiquid_I2C_Line = + polaristable->ucLiquid_I2C_Line; + tdp_table->ucVr_I2C_address = polaristable->ucVr_I2C_address; + tdp_table->ucVr_I2C_Line = polaristable->ucVr_I2C_Line; + tdp_table->ucPlx_I2C_address = polaristable->ucPlx_I2C_address; + tdp_table->ucPlx_I2C_Line = polaristable->ucPlx_I2C_Line; + tdp_table->usBoostPowerLimit = polaristable->usBoostPowerLimit; + tdp_table->ucCKS_LDO_REFSEL = polaristable->ucCKS_LDO_REFSEL; + tdp_table->ucHotSpotOnly = polaristable->ucHotSpotOnly; } *cac_tdp_table = tdp_table; @@ -690,19 +717,16 @@ static int get_mm_clock_voltage_table( const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table ) { - uint32_t table_size, i; + uint32_t i; const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record; PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) - * mm_dependency_table->ucNumEntries; - mm_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == mm_table) + mm_table = kzalloc(struct_size(mm_table, entries, mm_dependency_table->ucNumEntries), + GFP_KERNEL); + if (!mm_table) return -ENOMEM; mm_table->count = mm_dependency_table->ucNumEntries; @@ -755,10 +779,10 @@ static int get_gpio_table(struct pp_hwmgr *hwmgr, return 0; } /** - * Private Function used during initialization. + * init_clock_voltage_dependency - Private Function used during initialization. * Initialize clock voltage dependency - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. + * @hwmgr: Pointer to the hardware manager. + * @powerplay_table: Pointer to the PowerPlay Table. */ static int init_clock_voltage_dependency( struct pp_hwmgr *hwmgr, @@ -847,15 +871,16 @@ static int init_clock_voltage_dependency( return result; } -/** Retrieves the (signed) Overdrive limits from VBIOS. +/** + * init_over_drive_limits - Retrieves the (signed) Overdrive limits from VBIOS. * The max engine clock, memory clock and max temperature come from the firmware info table. * * The information is placed into the platform descriptor. * - * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated. - * @param powerplay_table the address of the PowerPlay table. + * @hwmgr: source of the VBIOS table and owner of the platform descriptor to be updated. + * @powerplay_table: the address of the PowerPlay table. * - * @return 1 as long as the firmware info table was present and of a supported version. + * Return: 1 as long as the firmware info table was present and of a supported version. */ static int init_over_drive_limits( struct pp_hwmgr *hwmgr, @@ -874,11 +899,11 @@ static int init_over_drive_limits( } /** - * Private Function used during initialization. + * init_thermal_controller - Private Function used during initialization. * Inspect the PowerPlay table for obvious signs of corruption. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - * @exception This implementation always returns 1. + * @hwmgr: Pointer to the hardware manager. + * @powerplay_table: Pointer to the PowerPlay Table. + * Exception: This implementation always returns 1. */ static int init_thermal_controller( struct pp_hwmgr *hwmgr, @@ -972,7 +997,7 @@ static int init_thermal_controller( = tonga_fan_table->ucTargetTemperature; hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit = tonga_fan_table->ucMinimumPWMLimit; - } else { + } else if (fan_table->ucRevId == 8) { const ATOM_Fiji_Fan_Table *fiji_fan_table = (ATOM_Fiji_Fan_Table *)fan_table; hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst @@ -1022,17 +1047,73 @@ static int init_thermal_controller( = le16_to_cpu(fiji_fan_table->usFanGainPlx); hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = le16_to_cpu(fiji_fan_table->usFanGainHbm); + } else if (fan_table->ucRevId >= 9) { + const ATOM_Polaris_Fan_Table *polaris_fan_table = + (ATOM_Polaris_Fan_Table *)fan_table; + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst + = polaris_fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin + = le16_to_cpu(polaris_fan_table->usTMin); + hwmgr->thermal_controller.advanceFanControlParameters.usTMed + = le16_to_cpu(polaris_fan_table->usTMed); + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh + = le16_to_cpu(polaris_fan_table->usTHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin + = le16_to_cpu(polaris_fan_table->usPWMMin); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed + = le16_to_cpu(polaris_fan_table->usPWMMed); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh + = le16_to_cpu(polaris_fan_table->usPWMHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = le16_to_cpu(polaris_fan_table->usTMax); + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode + = polaris_fan_table->ucFanControlMode; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM + = le16_to_cpu(polaris_fan_table->usFanPWMMax); + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity + = 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity + = le16_to_cpu(polaris_fan_table->usFanOutputSensitivity); + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM + = le16_to_cpu(polaris_fan_table->usFanRPMMax); + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit + = (le32_to_cpu(polaris_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature + = polaris_fan_table->ucTargetTemperature; + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit + = polaris_fan_table->ucMinimumPWMLimit; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge + = le16_to_cpu(polaris_fan_table->usFanGainEdge); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot + = le16_to_cpu(polaris_fan_table->usFanGainHotspot); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid + = le16_to_cpu(polaris_fan_table->usFanGainLiquid); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc + = le16_to_cpu(polaris_fan_table->usFanGainVrVddc); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd + = le16_to_cpu(polaris_fan_table->usFanGainVrMvdd); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx + = le16_to_cpu(polaris_fan_table->usFanGainPlx); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm + = le16_to_cpu(polaris_fan_table->usFanGainHbm); + hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM + = le16_to_cpu(polaris_fan_table->ucEnableZeroRPM); + hwmgr->thermal_controller.advanceFanControlParameters.ucFanStopTemperature + = le16_to_cpu(polaris_fan_table->ucFanStopTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.ucFanStartTemperature + = le16_to_cpu(polaris_fan_table->ucFanStartTemperature); } return 0; } /** - * Private Function used during initialization. + * check_powerplay_tables - Private Function used during initialization. * Inspect the PowerPlay table for obvious signs of corruption. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - * @exception 2 if the powerplay table is incorrect. + * @hwmgr: Pointer to the hardware manager. + * @powerplay_table: Pointer to the PowerPlay Table. + * Exception: 2 if the powerplay table is incorrect. */ static int check_powerplay_tables( struct pp_hwmgr *hwmgr, @@ -1175,9 +1256,9 @@ int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr) return (uint32_t)(state_arrays->ucNumEntries); } -/** -* Private function to convert flags stored in the BIOS to software flags in PowerPlay. -*/ +/* + * Private function to convert flags stored in the BIOS to software flags in PowerPlay. + */ static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, uint16_t classification, uint16_t classification2) { @@ -1276,13 +1357,13 @@ static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i } /** -* Create a Power State out of an entry in the PowerPlay table. -* This function is called by the hardware back-end. -* @param hwmgr Pointer to the hardware manager. -* @param entry_index The index of the entry to be extracted from the table. -* @param power_state The address of the PowerState instance being created. -* @return -1 if the entry cannot be retrieved. -*/ + * get_powerplay_table_entry_v1_0 - Create a Power State out of an entry in the PowerPlay table. + * This function is called by the hardware back-end. + * @hwmgr: Pointer to the hardware manager. + * @entry_index: The index of the entry to be extracted from the table. + * @power_state: The address of the PowerState instance being created. + * Return: -1 if the entry cannot be retrieved. + */ int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t entry_index, struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c index 719597c5d27d..182118e3fd5f 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c @@ -24,6 +24,8 @@ #include <linux/types.h> #include <linux/kernel.h> #include <linux/slab.h> +#include <linux/pci.h> + #include <drm/amdgpu_drm.h> #include "processpptables.h" #include <atom-types.h> @@ -377,14 +379,11 @@ static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table) { - unsigned long table_size, i; + unsigned long i; struct phm_clock_voltage_dependency_table *dep_table; - table_size = sizeof(unsigned long) + - sizeof(struct phm_clock_voltage_dependency_table) - * table->ucNumEntries; - - dep_table = kzalloc(table_size, GFP_KERNEL); + dep_table = kzalloc(struct_size(dep_table, entries, table->ucNumEntries), + GFP_KERNEL); if (NULL == dep_table) return -ENOMEM; @@ -407,12 +406,11 @@ static int get_valid_clk(struct pp_hwmgr *hwmgr, struct phm_clock_array **ptable, const struct phm_clock_voltage_dependency_table *table) { - unsigned long table_size, i; + unsigned long i; struct phm_clock_array *clock_table; - table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count; - clock_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == clock_table) + clock_table = kzalloc(struct_size(clock_table, values, table->count), GFP_KERNEL); + if (!clock_table) return -ENOMEM; clock_table->count = (unsigned long)table->count; @@ -984,6 +982,8 @@ static int init_thermal_controller( struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) { + struct amdgpu_device *adev = hwmgr->adev; + hwmgr->thermal_controller.ucType = powerplay_table->sThermalController.ucType; hwmgr->thermal_controller.ucI2cLine = @@ -1008,7 +1008,104 @@ static int init_thermal_controller( ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, PHM_PlatformCaps_ThermalController); - hwmgr->thermal_controller.use_hw_fan_control = 1; + if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + + if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) { + hwmgr->thermal_controller.use_hw_fan_control = 1; + return 0; + } else { + const ATOM_PPLIB_FANTABLE *fan_table = + (const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table3->usFanTableOffset)); + + if (1 <= fan_table->ucFanTableFormat) { + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst = + fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin = + le16_to_cpu(fan_table->usTMin); + hwmgr->thermal_controller.advanceFanControlParameters.usTMed = + le16_to_cpu(fan_table->usTMed); + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh = + le16_to_cpu(fan_table->usTHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = + le16_to_cpu(fan_table->usPWMMin); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed = + le16_to_cpu(fan_table->usPWMMed); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh = + le16_to_cpu(fan_table->usPWMHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900; + hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + } + + if (2 <= fan_table->ucFanTableFormat) { + const ATOM_PPLIB_FANTABLE2 *fan_table2 = + (const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table3->usFanTableOffset)); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax = + le16_to_cpu(fan_table2->usTMax); + } + + if (3 <= fan_table->ucFanTableFormat) { + const ATOM_PPLIB_FANTABLE3 *fan_table3 = + (const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table3->usFanTableOffset)); + + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode = + fan_table3->ucFanControlMode; + + if ((3 == fan_table->ucFanTableFormat) && + (0x67B1 == adev->pdev->device)) + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM = + 47; + else + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM = + le16_to_cpu(fan_table3->usFanPWMMax); + + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity = + 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = + le16_to_cpu(fan_table3->usFanOutputSensitivity); + } + + if (6 <= fan_table->ucFanTableFormat) { + const ATOM_PPLIB_FANTABLE4 *fan_table4 = + (const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table3->usFanTableOffset)); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM); + + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM = + le16_to_cpu(fan_table4->usFanRPMMax); + } + + if (7 <= fan_table->ucFanTableFormat) { + const ATOM_PPLIB_FANTABLE5 *fan_table5 = + (const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table3->usFanTableOffset)); + + if (0x67A2 == adev->pdev->device || + 0x67A9 == adev->pdev->device || + 0x67B9 == adev->pdev->device) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_GeminiRegulatorFanControlSupport); + hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow = + le16_to_cpu(fan_table5->usFanCurrentLow); + hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh = + le16_to_cpu(fan_table5->usFanCurrentHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow = + le16_to_cpu(fan_table5->usFanRPMLow); + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh = + le16_to_cpu(fan_table5->usFanRPMHigh); + } + } + } + } return 0; } @@ -1109,15 +1206,12 @@ static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table, const UVDClockInfoArray *array) { - unsigned long table_size, i; + unsigned long i; struct phm_uvd_clock_voltage_dependency_table *uvd_table; - table_size = sizeof(unsigned long) + - sizeof(struct phm_uvd_clock_voltage_dependency_table) * - table->numEntries; - - uvd_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == uvd_table) + uvd_table = kzalloc(struct_size(uvd_table, entries, table->numEntries), + GFP_KERNEL); + if (!uvd_table) return -ENOMEM; uvd_table->count = table->numEntries; @@ -1142,15 +1236,12 @@ static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table, const VCEClockInfoArray *array) { - unsigned long table_size, i; + unsigned long i; struct phm_vce_clock_voltage_dependency_table *vce_table = NULL; - table_size = sizeof(unsigned long) + - sizeof(struct phm_vce_clock_voltage_dependency_table) - * table->numEntries; - - vce_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == vce_table) + vce_table = kzalloc(struct_size(vce_table, entries, table->numEntries), + GFP_KERNEL); + if (!vce_table) return -ENOMEM; vce_table->count = table->numEntries; @@ -1173,15 +1264,12 @@ static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, struct phm_samu_clock_voltage_dependency_table **ptable, const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table) { - unsigned long table_size, i; + unsigned long i; struct phm_samu_clock_voltage_dependency_table *samu_table; - table_size = sizeof(unsigned long) + - sizeof(struct phm_samu_clock_voltage_dependency_table) * - table->numEntries; - - samu_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == samu_table) + samu_table = kzalloc(struct_size(samu_table, entries, table->numEntries), + GFP_KERNEL); + if (!samu_table) return -ENOMEM; samu_table->count = table->numEntries; @@ -1201,15 +1289,12 @@ static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, struct phm_acp_clock_voltage_dependency_table **ptable, const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table) { - unsigned table_size, i; + unsigned long i; struct phm_acp_clock_voltage_dependency_table *acp_table; - table_size = sizeof(unsigned long) + - sizeof(struct phm_acp_clock_voltage_dependency_table) * - table->numEntries; - - acp_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == acp_table) + acp_table = kzalloc(struct_size(acp_table, entries, table->numEntries), + GFP_KERNEL); + if (!acp_table) return -ENOMEM; acp_table->count = (unsigned long)table->numEntries; @@ -1397,17 +1482,14 @@ static int get_cac_leakage_table(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_CAC_Leakage_Table *table) { struct phm_cac_leakage_table *cac_leakage_table; - unsigned long table_size, i; + unsigned long i; - if (hwmgr == NULL || table == NULL || ptable == NULL) + if (!hwmgr || !table || !ptable) return -EINVAL; - table_size = sizeof(ULONG) + - (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries); - - cac_leakage_table = kzalloc(table_size, GFP_KERNEL); - - if (cac_leakage_table == NULL) + cac_leakage_table = kzalloc(struct_size(cac_leakage_table, entries, table->ucNumEntries), + GFP_KERNEL); + if (!cac_leakage_table) return -ENOMEM; cac_leakage_table->count = (ULONG)table->ucNumEntries; @@ -1540,16 +1622,12 @@ static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, (((unsigned long)powerplay_table4) + le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset)); struct phm_phase_shedding_limits_table *table; - unsigned long size, i; - - - size = sizeof(unsigned long) + - (sizeof(struct phm_phase_shedding_limits_table) * - ptable->ucNumEntries); + unsigned long i; - table = kzalloc(size, GFP_KERNEL); - if (table == NULL) + table = kzalloc(struct_size(table, entries, ptable->ucNumEntries), + GFP_KERNEL); + if (!table) return -ENOMEM; table->count = (unsigned long)ptable->ucNumEntries; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index cf60f3992303..e57e64bbacdc 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -130,9 +130,10 @@ static int smu10_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, static int smu10_init_dynamic_state_adjustment_rule_settings( struct pp_hwmgr *hwmgr) { + int count = 8; struct phm_clock_voltage_dependency_table *table_clk_vlt; - table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), + table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, count), GFP_KERNEL); if (NULL == table_clk_vlt) { @@ -140,7 +141,7 @@ static int smu10_init_dynamic_state_adjustment_rule_settings( return -ENOMEM; } - table_clk_vlt->count = 8; + table_clk_vlt->count = count; table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; table_clk_vlt->entries[0].v = 0; table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; @@ -1297,15 +1298,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile) int pplib_workload = 0; switch (power_profile) { - case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: - pplib_workload = WORKLOAD_DEFAULT_BIT; - break; case PP_SMC_POWER_PROFILE_FULLSCREEN3D: pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; break; - case PP_SMC_POWER_PROFILE_POWERSAVING: - pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; - break; case PP_SMC_POWER_PROFILE_VIDEO: pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; break; @@ -1315,6 +1310,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile) case PP_SMC_POWER_PROFILE_COMPUTE: pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; break; + case PP_SMC_POWER_PROFILE_CUSTOM: + pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT; + break; } return pplib_workload; @@ -1438,6 +1436,13 @@ static int smu10_set_fine_grain_clk_vol(struct pp_hwmgr *hwmgr, return 0; } +static int smu10_gfx_state_change(struct pp_hwmgr *hwmgr, uint32_t state) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GpuChangeState, state, NULL); + + return 0; +} + static const struct pp_hwmgr_func smu10_hwmgr_funcs = { .backend_init = smu10_hwmgr_backend_init, .backend_fini = smu10_hwmgr_backend_fini, @@ -1484,6 +1489,7 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = { .set_power_profile_mode = smu10_set_power_profile_mode, .asic_reset = smu10_asic_reset, .set_fine_grain_clk_vol = smu10_set_fine_grain_clk_vol, + .gfx_state_change = smu10_gfx_state_change, }; int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index 1e8919b0acdb..82676c086ce4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -49,6 +49,8 @@ #include "processpptables.h" #include "pp_thermal.h" #include "smu7_baco.h" +#include "smu7_smumgr.h" +#include "polaris10_smumgr.h" #include "ivsrcid/ivsrcid_vislands30.h" @@ -97,6 +99,9 @@ static struct profile_mode_setting smu7_profiling[7] = #define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT 0x00000005 #define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT 0x00000006 +#define STRAP_EVV_REVISION_MSB 2211 +#define STRAP_EVV_REVISION_LSB 2208 + /** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */ enum DPM_EVENT_SRC { DPM_EVENT_SRC_ANALOG = 0, @@ -106,9 +111,66 @@ enum DPM_EVENT_SRC { DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 }; +#define ixDIDT_SQ_EDC_CTRL 0x0013 +#define ixDIDT_SQ_EDC_THRESHOLD 0x0014 +#define ixDIDT_SQ_EDC_STALL_PATTERN_1_2 0x0015 +#define ixDIDT_SQ_EDC_STALL_PATTERN_3_4 0x0016 +#define ixDIDT_SQ_EDC_STALL_PATTERN_5_6 0x0017 +#define ixDIDT_SQ_EDC_STALL_PATTERN_7 0x0018 + +#define ixDIDT_TD_EDC_CTRL 0x0053 +#define ixDIDT_TD_EDC_THRESHOLD 0x0054 +#define ixDIDT_TD_EDC_STALL_PATTERN_1_2 0x0055 +#define ixDIDT_TD_EDC_STALL_PATTERN_3_4 0x0056 +#define ixDIDT_TD_EDC_STALL_PATTERN_5_6 0x0057 +#define ixDIDT_TD_EDC_STALL_PATTERN_7 0x0058 + +#define ixDIDT_TCP_EDC_CTRL 0x0073 +#define ixDIDT_TCP_EDC_THRESHOLD 0x0074 +#define ixDIDT_TCP_EDC_STALL_PATTERN_1_2 0x0075 +#define ixDIDT_TCP_EDC_STALL_PATTERN_3_4 0x0076 +#define ixDIDT_TCP_EDC_STALL_PATTERN_5_6 0x0077 +#define ixDIDT_TCP_EDC_STALL_PATTERN_7 0x0078 + +#define ixDIDT_DB_EDC_CTRL 0x0033 +#define ixDIDT_DB_EDC_THRESHOLD 0x0034 +#define ixDIDT_DB_EDC_STALL_PATTERN_1_2 0x0035 +#define ixDIDT_DB_EDC_STALL_PATTERN_3_4 0x0036 +#define ixDIDT_DB_EDC_STALL_PATTERN_5_6 0x0037 +#define ixDIDT_DB_EDC_STALL_PATTERN_7 0x0038 + +uint32_t DIDTEDCConfig_P12[] = { + ixDIDT_SQ_EDC_STALL_PATTERN_1_2, + ixDIDT_SQ_EDC_STALL_PATTERN_3_4, + ixDIDT_SQ_EDC_STALL_PATTERN_5_6, + ixDIDT_SQ_EDC_STALL_PATTERN_7, + ixDIDT_SQ_EDC_THRESHOLD, + ixDIDT_SQ_EDC_CTRL, + ixDIDT_TD_EDC_STALL_PATTERN_1_2, + ixDIDT_TD_EDC_STALL_PATTERN_3_4, + ixDIDT_TD_EDC_STALL_PATTERN_5_6, + ixDIDT_TD_EDC_STALL_PATTERN_7, + ixDIDT_TD_EDC_THRESHOLD, + ixDIDT_TD_EDC_CTRL, + ixDIDT_TCP_EDC_STALL_PATTERN_1_2, + ixDIDT_TCP_EDC_STALL_PATTERN_3_4, + ixDIDT_TCP_EDC_STALL_PATTERN_5_6, + ixDIDT_TCP_EDC_STALL_PATTERN_7, + ixDIDT_TCP_EDC_THRESHOLD, + ixDIDT_TCP_EDC_CTRL, + ixDIDT_DB_EDC_STALL_PATTERN_1_2, + ixDIDT_DB_EDC_STALL_PATTERN_3_4, + ixDIDT_DB_EDC_STALL_PATTERN_5_6, + ixDIDT_DB_EDC_STALL_PATTERN_7, + ixDIDT_DB_EDC_THRESHOLD, + ixDIDT_DB_EDC_CTRL, + 0xFFFFFFFF // End of list +}; + static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic); static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); +static int smu7_notify_has_display(struct pp_hwmgr *hwmgr); static struct smu7_power_state *cast_phw_smu7_power_state( struct pp_hw_power_state *hw_ps) @@ -131,10 +193,10 @@ static const struct smu7_power_state *cast_const_phw_smu7_power_state( } /** - * Find the MC microcode version and store it in the HwMgr struct + * smu7_get_mc_microcode_version - Find the MC microcode version and store it in the HwMgr struct * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 */ static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr) { @@ -171,14 +233,15 @@ static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) } /** -* Enable voltage control -* -* @param pHwMgr the address of the powerplay hardware manager. -* @return always PP_Result_OK -*/ + * smu7_enable_smc_voltage_controller - Enable voltage control + * + * @hwmgr the address of the powerplay hardware manager. + * Return: always PP_Result_OK + */ static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) { - if (hwmgr->chip_id == CHIP_VEGAM) { + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) { PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0); PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, @@ -192,10 +255,10 @@ static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) } /** -* Checks if we want to support voltage control -* -* @param hwmgr the address of the powerplay hardware manager. -*/ + * smu7_voltage_control - Checks if we want to support voltage control + * + * @hwmgr: the address of the powerplay hardware manager. + */ static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr) { const struct smu7_hwmgr *data = @@ -205,11 +268,11 @@ static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr) } /** -* Enable voltage control -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ + * smu7_enable_voltage_control - Enable voltage control + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 + */ static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr) { /* enable voltage control */ @@ -243,11 +306,11 @@ static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_tabl /** -* Create Voltage Tables. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ + * smu7_construct_voltage_tables - Create Voltage Tables. + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 + */ static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -355,11 +418,11 @@ static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr) } /** -* Programs static screed detection parameters -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ + * smu7_program_static_screen_threshold_parameters - Programs static screed detection parameters + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 + */ static int smu7_program_static_screen_threshold_parameters( struct pp_hwmgr *hwmgr) { @@ -378,11 +441,11 @@ static int smu7_program_static_screen_threshold_parameters( } /** -* Setup display gap for glitch free memory clock switching. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ + * smu7_enable_display_gap - Setup display gap for glitch free memory clock switching. + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 + */ static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr) { uint32_t display_gap = @@ -402,11 +465,11 @@ static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr) } /** -* Programs activity state transition voting clients -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ + * smu7_program_voting_clients - Programs activity state transition voting clients + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 + */ static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -497,12 +560,12 @@ static int smu7_reset_to_default(struct pp_hwmgr *hwmgr) } /** -* Initial switch from ARB F0->F1 -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -* This function is to be called from the SetPowerState table. -*/ + * smu7_initial_switch_from_arbf0_to_f1 - Initial switch from ARB F0->F1 + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 + * This function is to be called from the SetPowerState table. + */ static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr) { return smu7_copy_and_switch_arb_sets(hwmgr, @@ -1088,7 +1151,8 @@ static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) /* enable SCLK dpm */ if (!data->sclk_dpm_key_disabled) { - if (hwmgr->chip_id == CHIP_VEGAM) + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) smu7_disable_sclk_vce_handshake(hwmgr); PP_ASSERT_WITH_CODE( @@ -1109,7 +1173,11 @@ static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) "Failed to enable MCLK DPM during DPM Start Function!", return -EINVAL); - if (hwmgr->chip_family != CHIP_VEGAM) + if ((hwmgr->chip_family == AMDGPU_FAMILY_CI) || + (hwmgr->chip_id == CHIP_POLARIS10) || + (hwmgr->chip_id == CHIP_POLARIS11) || + (hwmgr->chip_id == CHIP_POLARIS12) || + (hwmgr->chip_id == CHIP_TONGA)) PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); @@ -1331,6 +1399,50 @@ static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) return 0; } +static int smu7_program_edc_didt_registers(struct pp_hwmgr *hwmgr, + uint32_t *cac_config_regs, + AtomCtrl_EDCLeakgeTable *edc_leakage_table) +{ + uint32_t data, i = 0; + + while (cac_config_regs[i] != 0xFFFFFFFF) { + data = edc_leakage_table->DIDT_REG[i]; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__DIDT, + cac_config_regs[i], + data); + i++; + } + + return 0; +} + +static int smu7_populate_edc_leakage_registers(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (!data->disable_edc_leakage_controller && + data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset && + data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) { + ret = smu7_program_edc_didt_registers(hwmgr, + DIDTEDCConfig_P12, + &data->edc_leakage_table); + if (ret) + return ret; + + ret = smum_send_msg_to_smc(hwmgr, + (PPSMC_Msg)PPSMC_MSG_EnableEDCController, + NULL); + } else { + ret = smum_send_msg_to_smc(hwmgr, + (PPSMC_Msg)PPSMC_MSG_DisableEDCController, + NULL); + } + + return ret; +} + static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) { int tmp_result = 0; @@ -1395,7 +1507,21 @@ static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to enable VR hot GPIO interrupt!", result = tmp_result); - smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL); + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) { + tmp_result = smu7_notify_has_display(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable display setting!", result = tmp_result); + } else { + smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL); + } + + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) { + tmp_result = smu7_populate_edc_leakage_registers(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to populate edc leakage registers!", result = tmp_result); + } tmp_result = smu7_enable_sclk_control(hwmgr); PP_ASSERT_WITH_CODE((0 == tmp_result), @@ -1541,6 +1667,10 @@ static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to reset to default!", result = tmp_result); + tmp_result = smum_stop_smc(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to stop smc!", result = tmp_result); + tmp_result = smu7_force_switch_to_arbf0(hwmgr); PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to force to switch arbf0!", result = tmp_result); @@ -1554,6 +1684,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); struct amdgpu_device *adev = hwmgr->adev; + uint8_t tmp1, tmp2; + uint16_t tmp3 = 0; data->dll_default_on = false; data->mclk_dpm0_activity_target = 0xa; @@ -1585,36 +1717,29 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) data->current_profile_setting.sclk_down_hyst = 100; data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT; data->current_profile_setting.bupdate_mclk = 1; - if (adev->gmc.vram_width == 256) { - data->current_profile_setting.mclk_up_hyst = 10; - data->current_profile_setting.mclk_down_hyst = 60; - data->current_profile_setting.mclk_activity = 25; - } else if (adev->gmc.vram_width == 128) { - data->current_profile_setting.mclk_up_hyst = 5; - data->current_profile_setting.mclk_down_hyst = 16; - data->current_profile_setting.mclk_activity = 20; - } else if (adev->gmc.vram_width == 64) { - data->current_profile_setting.mclk_up_hyst = 3; - data->current_profile_setting.mclk_down_hyst = 16; - data->current_profile_setting.mclk_activity = 20; + if (hwmgr->chip_id >= CHIP_POLARIS10) { + if (adev->gmc.vram_width == 256) { + data->current_profile_setting.mclk_up_hyst = 10; + data->current_profile_setting.mclk_down_hyst = 60; + data->current_profile_setting.mclk_activity = 25; + } else if (adev->gmc.vram_width == 128) { + data->current_profile_setting.mclk_up_hyst = 5; + data->current_profile_setting.mclk_down_hyst = 16; + data->current_profile_setting.mclk_activity = 20; + } else if (adev->gmc.vram_width == 64) { + data->current_profile_setting.mclk_up_hyst = 3; + data->current_profile_setting.mclk_down_hyst = 16; + data->current_profile_setting.mclk_activity = 20; + } + } else { + data->current_profile_setting.mclk_up_hyst = 0; + data->current_profile_setting.mclk_down_hyst = 100; + data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT; } hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D]; hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; - if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) { - uint8_t tmp1, tmp2; - uint16_t tmp3 = 0; - atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2, - &tmp3); - tmp3 = (tmp3 >> 5) & 0x3; - data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3; - } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { - data->vddc_phase_shed_control = 1; - } else { - data->vddc_phase_shed_control = 0; - } - if (hwmgr->chip_id == CHIP_HAWAII) { data->thermal_temp_setting.temperature_low = 94500; data->thermal_temp_setting.temperature_high = 95000; @@ -1673,6 +1798,22 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ControlVDDCI); + data->vddc_phase_shed_control = 1; + if ((hwmgr->chip_id == CHIP_POLARIS12) || + ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P30(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) { + if (data->voltage_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { + atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2, + &tmp3); + tmp3 = (tmp3 >> 5) & 0x3; + data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3; + } + } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { + data->vddc_phase_shed_control = 1; + } + if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK) && (table_info->cac_dtp_table->usClockStretchAmount != 0)) phm_cap_set(hwmgr->platform_descriptor.platformCaps, @@ -1694,14 +1835,93 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) if (adev->pg_flags & AMD_PG_SUPPORT_VCE) phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); + + data->disable_edc_leakage_controller = true; + if (((adev->asic_type == CHIP_POLARIS10) && hwmgr->is_kicker) || + ((adev->asic_type == CHIP_POLARIS11) && hwmgr->is_kicker) || + (adev->asic_type == CHIP_POLARIS12) || + (adev->asic_type == CHIP_VEGAM)) + data->disable_edc_leakage_controller = false; + + if (!atomctrl_is_asic_internal_ss_supported(hwmgr)) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport); + } + + if ((adev->pdev->device == 0x699F) && + (adev->pdev->revision == 0xCF)) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + data->enable_tdc_limit_feature = false; + data->enable_pkg_pwr_tracking_feature = false; + data->disable_edc_leakage_controller = true; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + } +} + +static int smu7_calculate_ro_range(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + uint32_t asicrev1, evv_revision, max = 0, min = 0; + + atomctrl_read_efuse(hwmgr, STRAP_EVV_REVISION_LSB, STRAP_EVV_REVISION_MSB, + &evv_revision); + + atomctrl_read_efuse(hwmgr, 568, 579, &asicrev1); + + if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) { + min = 1200; + max = 2500; + } else if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) { + min = 900; + max= 2100; + } else if (hwmgr->chip_id == CHIP_POLARIS10) { + if (adev->pdev->subsystem_vendor == 0x106B) { + min = 1000; + max = 2300; + } else { + if (evv_revision == 0) { + min = 1000; + max = 2300; + } else if (evv_revision == 1) { + if (asicrev1 == 326) { + min = 1200; + max = 2500; + /* TODO: PATCH RO in VBIOS */ + } else { + min = 1200; + max = 2000; + } + } else if (evv_revision == 2) { + min = 1200; + max = 2500; + } + } + } else { + min = 1100; + max = 2100; + } + + data->ro_range_minimum = min; + data->ro_range_maximum = max; + + /* TODO: PATCH RO in VBIOS here */ + + return 0; } /** -* Get Leakage VDDC based on leakage ID. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ + * smu7_get_evv_voltages - Get Leakage VDDC based on leakage ID. + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 + */ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -1714,6 +1934,10 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) (struct phm_ppt_v1_information *)hwmgr->pptable; struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL; + if (hwmgr->chip_id == CHIP_POLARIS10 || + hwmgr->chip_id == CHIP_POLARIS11 || + hwmgr->chip_id == CHIP_POLARIS12) + smu7_calculate_ro_range(hwmgr); for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; @@ -1793,11 +2017,11 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) } /** - * Change virtual leakage voltage to actual value. + * smu7_patch_ppt_v1_with_vdd_leakage - Change virtual leakage voltage to actual value. * - * @param hwmgr the address of the powerplay hardware manager. - * @param pointer to changing voltage - * @param pointer to leakage table + * @hwmgr: the address of the powerplay hardware manager. + * @voltage: pointer to changing voltage + * @leakage_table: pointer to leakage table */ static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr, uint16_t *voltage, struct smu7_leakage_voltage *leakage_table) @@ -1819,13 +2043,13 @@ static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr, } /** -* Patch voltage lookup table by EVV leakages. -* -* @param hwmgr the address of the powerplay hardware manager. -* @param pointer to voltage lookup table -* @param pointer to leakage table -* @return always 0 -*/ + * smu7_patch_lookup_table_with_leakage - Patch voltage lookup table by EVV leakages. + * + * @hwmgr: the address of the powerplay hardware manager. + * @lookup_table: pointer to voltage lookup table + * @leakage_table: pointer to leakage table + * Return: always 0 + */ static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table, struct smu7_leakage_voltage *leakage_table) @@ -2077,6 +2301,28 @@ static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr) return result; } +static int smu7_find_highest_vddc(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = + table_info->vdd_dep_on_sclk; + struct phm_ppt_v1_voltage_lookup_table *lookup_table = + table_info->vddc_lookup_table; + uint16_t highest_voltage; + uint32_t i; + + highest_voltage = allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; + + for (i = 0; i < lookup_table->count; i++) { + if (lookup_table->entries[i].us_vdd < ATOM_VIRTUAL_VOLTAGE_ID0 && + lookup_table->entries[i].us_vdd > highest_voltage) + highest_voltage = lookup_table->entries[i].us_vdd; + } + + return highest_voltage; +} + static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr) { struct phm_ppt_v1_information *table_info = @@ -2105,8 +2351,12 @@ static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr) allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; table_info->max_clock_voltage_on_ac.mclk = allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; - table_info->max_clock_voltage_on_ac.vddc = - allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; + if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM) + table_info->max_clock_voltage_on_ac.vddc = + smu7_find_highest_vddc(hwmgr); + else + table_info->max_clock_voltage_on_ac.vddc = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; table_info->max_clock_voltage_on_ac.vddci = allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; @@ -2138,10 +2388,17 @@ static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr) sub_sys_id = adev->pdev->subsystem_device; sub_vendor_id = adev->pdev->subsystem_vendor; - if (hwmgr->chip_id == CHIP_POLARIS10 && hw_revision == 0xC7 && - ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) || - (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) || - (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) { + if (adev->pdev->device == 0x67DF && hw_revision == 0xC7 && + ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) || + (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) || + (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) { + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, + PWR_CKS_CNTL, + CKS_STRETCH_AMOUNT, + 0x3); + if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000) return 0; @@ -2243,11 +2500,11 @@ static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr) } /** - * Change virtual leakage voltage to actual value. + * smu7_patch_ppt_v0_with_vdd_leakage - Change virtual leakage voltage to actual value. * - * @param hwmgr the address of the powerplay hardware manager. - * @param pointer to changing voltage - * @param pointer to leakage table + * @hwmgr: the address of the powerplay hardware manager. + * @voltage: pointer to changing voltage + * @leakage_table: pointer to leakage table */ static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr, uint32_t *voltage, struct smu7_leakage_voltage *leakage_table) @@ -2542,6 +2799,42 @@ static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr) return 0; } +#define LEAKAGE_ID_MSB 463 +#define LEAKAGE_ID_LSB 454 + +static int smu7_update_edc_leakage_table(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t efuse; + uint16_t offset; + int ret = 0; + + if (data->disable_edc_leakage_controller) + return 0; + + ret = atomctrl_get_edc_hilo_leakage_offset_table(hwmgr, + &data->edc_hilo_leakage_offset_from_vbios); + if (ret) + return ret; + + if (data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset && + data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset) { + atomctrl_read_efuse(hwmgr, LEAKAGE_ID_LSB, LEAKAGE_ID_MSB, &efuse); + if (efuse < data->edc_hilo_leakage_offset_from_vbios.usHiLoLeakageThreshold) + offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtLoDpm7TableOffset; + else + offset = data->edc_hilo_leakage_offset_from_vbios.usEdcDidtHiDpm7TableOffset; + + ret = atomctrl_get_edc_leakage_table(hwmgr, + &data->edc_leakage_table, + offset); + if (ret) + return ret; + } + + return ret; +} + static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data; @@ -2591,6 +2884,8 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) data->pcie_gen_cap = adev->pm.pcie_gen_mask; if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) data->pcie_spc_cap = 20; + else + data->pcie_spc_cap = 16; data->pcie_lane_cap = adev->pm.pcie_mlw_mask; hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ @@ -2603,6 +2898,10 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) smu7_hwmgr_backend_fini(hwmgr); } + result = smu7_update_edc_leakage_table(hwmgr); + if (result) + return result; + return 0; } @@ -2880,7 +3179,7 @@ static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr, case CHIP_POLARIS10: case CHIP_POLARIS11: case CHIP_POLARIS12: - if (hwmgr->is_kicker) + if (hwmgr->is_kicker || (hwmgr->chip_id == CHIP_POLARIS12)) switch_limit_us = data->is_memory_gddr5 ? 450 : 150; else switch_limit_us = data->is_memory_gddr5 ? 200 : 150; @@ -2911,6 +3210,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, struct PP_Clocks minimum_clocks = {0}; bool disable_mclk_switching; bool disable_mclk_switching_for_frame_lock; + bool disable_mclk_switching_for_display; const struct phm_clock_and_voltage_limits *max_limits; uint32_t i; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -2918,9 +3218,12 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, (struct phm_ppt_v1_information *)(hwmgr->pptable); int32_t count; int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + uint32_t latency; + bool latency_allowed = false; data->battery_state = (PP_StateUILabel_Battery == request_ps->classification.ui_label); + data->mclk_ignore_signal = false; PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2, "VI should always have 2 performance levels", @@ -2971,19 +3274,26 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); + disable_mclk_switching_for_display = ((1 < hwmgr->display_config->num_display) && + !hwmgr->display_config->multi_monitor_in_sync) || + smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time); - if (hwmgr->display_config->num_display == 0) - disable_mclk_switching = false; - else - disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && - !hwmgr->display_config->multi_monitor_in_sync) || - disable_mclk_switching_for_frame_lock || - smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time); + disable_mclk_switching = disable_mclk_switching_for_frame_lock || + disable_mclk_switching_for_display; + + if (hwmgr->display_config->num_display == 0) { + if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM) + data->mclk_ignore_signal = true; + else + disable_mclk_switching = false; + } sclk = smu7_ps->performance_levels[0].engine_clock; mclk = smu7_ps->performance_levels[0].memory_clock; - if (disable_mclk_switching) + if (disable_mclk_switching && + (!(hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM))) mclk = smu7_ps->performance_levels [smu7_ps->performance_level_count - 1].memory_clock; @@ -3008,8 +3318,41 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, if (mclk < smu7_ps->performance_levels[1].memory_clock) mclk = smu7_ps->performance_levels[1].memory_clock; + if (hwmgr->chip_id >= CHIP_POLARIS10 && hwmgr->chip_id <= CHIP_VEGAM) { + if (disable_mclk_switching_for_display) { + /* Find the lowest MCLK frequency that is within + * the tolerable latency defined in DAL + */ + latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; + for (i = 0; i < data->mclk_latency_table.count; i++) { + if (data->mclk_latency_table.entries[i].latency <= latency) { + latency_allowed = true; + + if ((data->mclk_latency_table.entries[i].frequency >= + smu7_ps->performance_levels[0].memory_clock) && + (data->mclk_latency_table.entries[i].frequency <= + smu7_ps->performance_levels[1].memory_clock)) { + mclk = data->mclk_latency_table.entries[i].frequency; + break; + } + } + } + if ((i >= data->mclk_latency_table.count - 1) && !latency_allowed) { + data->mclk_ignore_signal = true; + } else { + data->mclk_ignore_signal = false; + } + } + + if (disable_mclk_switching_for_frame_lock) + mclk = smu7_ps->performance_levels[1].memory_clock; + } + smu7_ps->performance_levels[0].memory_clock = mclk; - smu7_ps->performance_levels[1].memory_clock = mclk; + + if (!(hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM)) + smu7_ps->performance_levels[1].memory_clock = mclk; } else { if (smu7_ps->performance_levels[1].memory_clock < smu7_ps->performance_levels[0].memory_clock) @@ -3755,6 +4098,7 @@ static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) } if ((0 == data->mclk_dpm_key_disabled) && + !data->mclk_ignore_signal && (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) { PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), @@ -3911,6 +4255,7 @@ static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) } if ((0 == data->mclk_dpm_key_disabled) && + !data->mclk_ignore_signal && (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) { PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), @@ -3964,7 +4309,12 @@ static int smu7_notify_link_speed_change_after_state_change( return 0; } -static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) +static int smu7_notify_no_display(struct pp_hwmgr *hwmgr) +{ + return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL) == 0) ? 0 : -EINVAL; +} + +static int smu7_notify_has_display(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -3977,10 +4327,25 @@ static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) smum_send_msg_to_smc_with_parameter(hwmgr, (PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2, NULL); + data->last_sent_vbi_timeout = data->frame_time_x2; } + return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay, NULL) == 0) ? 0 : -EINVAL; } +static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + + if (data->mclk_ignore_signal) + result = smu7_notify_no_display(hwmgr); + else + result = smu7_notify_has_display(hwmgr); + + return result; +} + static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) { int tmp_result, result = 0; @@ -4031,11 +4396,6 @@ static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) "Failed to update SCLK threshold!", result = tmp_result); - tmp_result = smu7_notify_smc_display(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to notify smc display settings!", - result = tmp_result); - tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr); PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to unfreeze SCLK MCLK DPM!", @@ -4046,6 +4406,11 @@ static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) "Failed to upload DPM level enabled mask!", result = tmp_result); + tmp_result = smu7_notify_smc_display(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to notify smc display settings!", + result = tmp_result); + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest)) { tmp_result = @@ -4069,29 +4434,17 @@ static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f } static int -smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) -{ - PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; - - return (smum_send_msg_to_smc(hwmgr, msg, NULL) == 0) ? 0 : -1; -} - -static int smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) { - if (hwmgr->display_config->num_display > 1 && - !hwmgr->display_config->multi_monitor_in_sync) - smu7_notify_smc_display_change(hwmgr, false); - return 0; } /** -* Programs the display gap -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always OK -*/ + * smu7_program_display_gap - Programs the display gap + * + * @hwmgr: the address of the powerplay hardware manager. + * Return: always OK + */ static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -4145,12 +4498,12 @@ static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr) } /** -* Set maximum target operating fan output RPM -* -* @param hwmgr: the address of the powerplay hardware manager. -* @param usMaxFanRpm: max operating fan RPM value. -* @return The response that came from the SMC. -*/ + * smu7_set_max_fan_rpm_output - Set maximum target operating fan output RPM + * + * @hwmgr: the address of the powerplay hardware manager. + * @usMaxFanRpm: max operating fan RPM value. + * Return: The response that came from the SMC. + */ static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm) { hwmgr->thermal_controller. @@ -4205,6 +4558,11 @@ smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh) is_update_required = true; + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM && + data->last_sent_vbi_timeout != data->frame_time_x2) + is_update_required = true; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr && (data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK || @@ -4340,10 +4698,10 @@ static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr) } /** - * Find out if memory is GDDR5. + * smu7_get_memory_type - Find out if memory is GDDR5. * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 */ static int smu7_get_memory_type(struct pp_hwmgr *hwmgr) { @@ -4356,10 +4714,10 @@ static int smu7_get_memory_type(struct pp_hwmgr *hwmgr) } /** - * Enables Dynamic Power Management by SMC + * smu7_enable_acpi_power_management - Enables Dynamic Power Management by SMC * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 */ static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr) { @@ -4370,10 +4728,10 @@ static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr) } /** - * Initialize PowerGating States for different engines + * smu7_init_power_gate_state - Initialize PowerGating States for different engines * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 + * @hwmgr: the address of the powerplay hardware manager. + * Return: always 0 */ static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr) { @@ -4761,6 +5119,125 @@ static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type return 0; } +static int smu7_get_sclks_with_latency(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = + table_info->vdd_dep_on_sclk; + int i; + + clocks->num_levels = 0; + for (i = 0; i < dep_sclk_table->count; i++) { + if (dep_sclk_table->entries[i].clk) { + clocks->data[clocks->num_levels].clocks_in_khz = + dep_sclk_table->entries[i].clk * 10; + clocks->num_levels++; + } + } + + return 0; +} + +static int smu7_get_mclks_with_latency(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = + table_info->vdd_dep_on_mclk; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int i; + + clocks->num_levels = 0; + data->mclk_latency_table.count = 0; + for (i = 0; i < dep_mclk_table->count; i++) { + if (dep_mclk_table->entries[i].clk) { + clocks->data[clocks->num_levels].clocks_in_khz = + dep_mclk_table->entries[i].clk * 10; + data->mclk_latency_table.entries[data->mclk_latency_table.count].frequency = + dep_mclk_table->entries[i].clk; + clocks->data[clocks->num_levels].latency_in_us = + data->mclk_latency_table.entries[data->mclk_latency_table.count].latency = + smu7_get_mem_latency(hwmgr, dep_mclk_table->entries[i].clk); + clocks->num_levels++; + data->mclk_latency_table.count++; + } + } + + return 0; +} + +static int smu7_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + if (!(hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM)) + return -EINVAL; + + switch (type) { + case amd_pp_sys_clock: + smu7_get_sclks_with_latency(hwmgr, clocks); + break; + case amd_pp_mem_clock: + smu7_get_mclks_with_latency(hwmgr, clocks); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smu7_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, + void *clock_range) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = + table_info->vdd_dep_on_mclk; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = + table_info->vdd_dep_on_sclk; + struct polaris10_smumgr *smu_data = + (struct polaris10_smumgr *)(hwmgr->smu_backend); + SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct dm_pp_wm_sets_with_clock_ranges *watermarks = + (struct dm_pp_wm_sets_with_clock_ranges *)clock_range; + uint32_t i, j, k; + bool valid_entry; + + if (!(hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM)) + return -EINVAL; + + for (i = 0; i < dep_mclk_table->count; i++) { + for (j = 0; j < dep_sclk_table->count; j++) { + valid_entry = false; + for (k = 0; k < watermarks->num_wm_sets; k++) { + if (dep_sclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_eng_clk_in_khz && + dep_sclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_eng_clk_in_khz && + dep_mclk_table->entries[i].clk / 10 >= watermarks->wm_clk_ranges[k].wm_min_mem_clk_in_khz && + dep_mclk_table->entries[i].clk / 10 < watermarks->wm_clk_ranges[k].wm_max_mem_clk_in_khz) { + valid_entry = true; + table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k].wm_set_id; + break; + } + } + PP_ASSERT_WITH_CODE(valid_entry, + "Clock is not in range of specified clock range for watermark from DAL! Using highest water mark set.", + table->DisplayWatermark[i][j] = watermarks->wm_clk_ranges[k - 1].wm_set_id); + } + } + + return smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, DisplayWatermark), + (uint8_t *)table->DisplayWatermark, + sizeof(uint8_t) * SMU74_MAX_LEVELS_MEMORY * SMU74_MAX_LEVELS_GRAPHICS, + SMC_RAM_END); +} + static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, uint32_t virtual_addr_low, uint32_t virtual_addr_hi, @@ -5178,6 +5655,8 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .get_mclk_od = smu7_get_mclk_od, .set_mclk_od = smu7_set_mclk_od, .get_clock_by_type = smu7_get_clock_by_type, + .get_clock_by_type_with_latency = smu7_get_clock_by_type_with_latency, + .set_watermarks_for_clocks_ranges = smu7_set_watermarks_for_clocks_ranges, .read_sensor = smu7_read_sensor, .dynamic_state_management_disable = smu7_disable_dpm_tasks, .avfs_control = smu7_avfs_control, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h index 69d361f8dfca..d9e8b386bd4d 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h @@ -200,10 +200,21 @@ struct profile_mode_setting { uint16_t mclk_activity; }; +struct smu7_mclk_latency_entries { + uint32_t frequency; + uint32_t latency; +}; + +struct smu7_mclk_latency_table { + uint32_t count; + struct smu7_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; +}; + struct smu7_hwmgr { struct smu7_dpm_table dpm_table; struct smu7_dpm_table golden_dpm_table; struct smu7_odn_dpm_table odn_dpm_table; + struct smu7_mclk_latency_table mclk_latency_table; uint32_t voting_rights_clients[8]; uint32_t static_screen_threshold_unit; @@ -239,6 +250,7 @@ struct smu7_hwmgr { bool pcie_performance_request; bool battery_state; + bool mclk_ignore_signal; bool is_tlu_enabled; bool disable_handshake; bool smc_voltage_control_enabled; @@ -324,10 +336,18 @@ struct smu7_hwmgr { uint32_t avfs_vdroop_override_setting; bool apply_avfs_cks_off_voltage; uint32_t frame_time_x2; + uint32_t last_sent_vbi_timeout; uint16_t mem_latency_high; uint16_t mem_latency_low; uint32_t vr_config; struct profile_mode_setting current_profile_setting; + + uint32_t ro_range_minimum; + uint32_t ro_range_maximum; + + bool disable_edc_leakage_controller; + AtomCtrl_HiLoLeakageOffsetTable edc_hilo_leakage_offset_from_vbios; + AtomCtrl_EDCLeakgeTable edc_leakage_table; }; /* To convert to Q8.8 format for firmware */ diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c index 5d4971576111..32a5a00fd8ae 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c @@ -852,12 +852,14 @@ static const struct gpu_pt_config_reg DIDTConfig_VegaM[] = }; static int smu7_enable_didt(struct pp_hwmgr *hwmgr, const bool enable) { + struct amdgpu_device *adev = hwmgr->adev; uint32_t en = enable ? 1 : 0; uint32_t block_en = 0; int32_t result = 0; uint32_t didt_block; - if (hwmgr->chip_id == CHIP_POLARIS11) + if ((hwmgr->chip_id == CHIP_POLARIS11) && + (adev->pdev->subsystem_vendor != 0x106B)) didt_block = Polaris11_DIDTBlock_Info; else didt_block = DIDTBlock_Info; @@ -962,6 +964,7 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) uint32_t num_se = 0; uint32_t count, value, value2; struct amdgpu_device *adev = hwmgr->adev; + uint32_t efuse; num_se = adev->gfx.config.max_shader_engines; @@ -988,7 +991,9 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) } else if (hwmgr->chip_id == CHIP_POLARIS11) { result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11); PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - if (hwmgr->is_kicker) + + if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11_Kicker); else result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11); @@ -1016,7 +1021,32 @@ int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) NULL); PP_ASSERT_WITH_CODE((0 == result), "Failed to enable DPM DIDT.", goto error); + + if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) { + result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_EnableDpmMcBlackout), + NULL); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to enable workaround for CRC issue.", goto error); + } else { + atomctrl_read_efuse(hwmgr, 547, 547, &efuse); + if (efuse == 1) { + result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_EnableDpmMcBlackout), + NULL); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to enable workaround for CRC issue.", goto error); + } else { + result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_DisableDpmMcBlackout), + NULL); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to enable workaround for CRC issue.", goto error); + } + } } + mutex_unlock(&adev->grbm_idx_mutex); amdgpu_gfx_rlc_exit_safe_mode(adev); } diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c index 0b30f73649a8..0d38d4206848 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c @@ -103,11 +103,11 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) } /** -* Set Fan Speed Control to static mode, so that the user can decide what speed to use. -* @param hwmgr the address of the powerplay hardware manager. -* mode the fan control mode, 0 default, 1 by percent, 5, by RPM -* @exception Should always succeed. -*/ + * smu7_fan_ctrl_set_static_mode - Set Fan Speed Control to static mode, so that the user can decide what speed to use. + * @hwmgr: the address of the powerplay hardware manager. + * @mode: the fan control mode, 0 default, 1 by percent, 5, by RPM + * Exception: Should always succeed. + */ int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { if (hwmgr->fan_ctrl_is_in_default_mode) { @@ -130,8 +130,8 @@ int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) /** * Reset Fan Speed Control to default mode. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Should always succeed. +* @hwmgr: the address of the powerplay hardware manager. +* Exception: Should always succeed. */ int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) { @@ -175,6 +175,17 @@ int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) hwmgr->thermal_controller. advanceFanControlParameters.ucTargetTemperature, NULL); + + if (!result && + (hwmgr->chip_id == CHIP_POLARIS10 || + hwmgr->chip_id == CHIP_POLARIS11 || + hwmgr->chip_id == CHIP_POLARIS12) && + hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM && + !PP_CAP(PHM_PlatformCaps_customThermalManagement)) + result = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_EnableZeroRpm, + NULL); + hwmgr->fan_ctrl_enabled = true; return result; @@ -188,11 +199,11 @@ int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) } /** -* Set Fan Speed in percent. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (0% - 100%) to be set. -* @exception Fails is the 100% setting appears to be 0. -*/ + * smu7_fan_ctrl_set_fan_speed_percent - Set Fan Speed in percent. + * @hwmgr: the address of the powerplay hardware manager. + * @speed: is the percentage value (0% - 100%) to be set. + * Exception: Fails is the 100% setting appears to be 0. + */ int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed) { @@ -226,9 +237,9 @@ int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, } /** -* Reset Fan Speed to default. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Always succeeds. +* smu7_fan_ctrl_reset_fan_speed_to_default - Reset Fan Speed to default. +* @hwmgr: the address of the powerplay hardware manager. +* Exception: Always succeeds. */ int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) { @@ -248,11 +259,11 @@ int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) } /** -* Set Fan Speed in RPM. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (min - max) to be set. -* @exception Fails is the speed not lie between min and max. -*/ + * smu7_fan_ctrl_set_fan_speed_rpm - Set Fan Speed in RPM. + * @hwmgr: the address of the powerplay hardware manager. + * @speed: is the percentage value (min - max) to be set. + * Exception: Fails is the speed not lie between min and max. + */ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) { uint32_t tach_period; @@ -280,10 +291,10 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) } /** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * smu7_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr) { int temp; @@ -303,12 +314,13 @@ int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr) } /** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ + * smu7_thermal_set_temperature_range - Set the requested temperature range for high and low alert signals + * + * @hwmgr: The address of the hardware manager. + * @low_temp: Temperature to be programmed for high alert signals + * @high_temp: Temperature to be programmed for low alert signals + * Exception: PP_Result_BadInput if the input data is not valid. + */ static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, int low_temp, int high_temp) { @@ -339,10 +351,10 @@ static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, } /** -* Programs thermal controller one-time setting registers -* -* @param hwmgr The address of the hardware manager. -*/ + * smu7_thermal_initialize - Programs thermal controller one-time setting registers + * + * @hwmgr: The address of the hardware manager. + */ static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr) { if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) @@ -358,10 +370,10 @@ static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr) } /** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * smu7_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ static void smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) { uint32_t alert; @@ -377,9 +389,9 @@ static void smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) } /** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ + * smu7_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller. + * @hwmgr: The address of the hardware manager. + */ int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr) { uint32_t alert; @@ -395,10 +407,10 @@ int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr) } /** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ + * smu7_thermal_stop_thermal_controller - Uninitialize the thermal controller. + * Currently just disables alerts. + * @hwmgr: The address of the hardware manager. + */ int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) { int result = smu7_thermal_disable_alert(hwmgr); @@ -410,14 +422,10 @@ int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) } /** -* Start the fan control on the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ + * smu7_thermal_start_smc_fan_control - Start the fan control on the SMC. + * @hwmgr: the address of the powerplay hardware manager. + * Return: result from set temperature range routine + */ static int smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) { /* If the fantable setup has failed we could have disabled diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c index 35ed47ebaf09..ed9b89980184 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c @@ -276,7 +276,7 @@ static int smu8_init_dynamic_state_adjustment_rule_settings( { struct phm_clock_voltage_dependency_table *table_clk_vlt; - table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), + table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 8), GFP_KERNEL); if (NULL == table_clk_vlt) { diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c index 60b5ca974356..bfe80ac0ad8c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c @@ -103,7 +103,7 @@ uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size return original_data; } -/** +/* * Returns once the part of the register indicated by the mask has * reached the given value. */ @@ -132,7 +132,7 @@ int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, } -/** +/* * Returns once the part of the register indicated by the mask has * reached the given value.The indirect space is described by giving * the memory-mapped index of the indirect index register. @@ -486,19 +486,18 @@ int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, } /** - * Initialize Dynamic State Adjustment Rule Settings + * phm_initializa_dynamic_state_adjustment_rule_settings - Initialize Dynamic State Adjustment Rule Settings * - * @param hwmgr the address of the powerplay hardware manager. + * @hwmgr: the address of the powerplay hardware manager. */ int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr) { - uint32_t table_size; struct phm_clock_voltage_dependency_table *table_clk_vlt; struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); /* initialize vddc_dep_on_dal_pwrl table */ - table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record); - table_clk_vlt = kzalloc(table_size, GFP_KERNEL); + table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 4), + GFP_KERNEL); if (NULL == table_clk_vlt) { pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n"); @@ -506,11 +505,23 @@ int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr } else { table_clk_vlt->count = 4; table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW; - table_clk_vlt->entries[0].v = 0; + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) + table_clk_vlt->entries[0].v = 700; + else + table_clk_vlt->entries[0].v = 0; table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW; - table_clk_vlt->entries[1].v = 720; + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) + table_clk_vlt->entries[1].v = 740; + else + table_clk_vlt->entries[1].v = 720; table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL; - table_clk_vlt->entries[2].v = 810; + if (hwmgr->chip_id >= CHIP_POLARIS10 && + hwmgr->chip_id <= CHIP_VEGAM) + table_clk_vlt->entries[2].v = 800; + else + table_clk_vlt->entries[2].v = 810; table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; table_clk_vlt->entries[3].v = 900; if (pptable_info != NULL) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c index 7eada3098ffc..1b47f94e0331 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c @@ -3141,6 +3141,8 @@ static int vega10_get_pp_table_entry(struct pp_hwmgr *hwmgr, result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state, vega10_get_pp_table_entry_callback_func); + if (result) + return result; /* * This is the earliest time we have all the dependency table diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c index f29af5ca0aa0..95b988823f50 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c @@ -344,18 +344,15 @@ static int get_mm_clock_voltage_table( phm_ppt_v1_mm_clock_voltage_dependency_table **vega10_mm_table, const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table) { - uint32_t table_size, i; + uint32_t i; const ATOM_Vega10_MM_Dependency_Record *mm_dependency_record; phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; PP_ASSERT_WITH_CODE((mm_dependency_table->ucNumEntries != 0), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) * - mm_dependency_table->ucNumEntries; - mm_table = kzalloc(table_size, GFP_KERNEL); - + mm_table = kzalloc(struct_size(mm_table, entries, mm_dependency_table->ucNumEntries), + GFP_KERNEL); if (!mm_table) return -ENOMEM; @@ -571,18 +568,14 @@ static int get_socclk_voltage_dependency_table( phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_clk_dep_table, const ATOM_Vega10_SOCCLK_Dependency_Table *clk_dep_table) { - uint32_t table_size, i; + uint32_t i; phm_ppt_v1_clock_voltage_dependency_table *clk_table; PP_ASSERT_WITH_CODE(clk_dep_table->ucNumEntries, "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - clk_dep_table->ucNumEntries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - + clk_table = kzalloc(struct_size(clk_table, entries, clk_dep_table->ucNumEntries), + GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -605,18 +598,14 @@ static int get_mclk_voltage_dependency_table( phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_mclk_dep_table, const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table) { - uint32_t table_size, i; + uint32_t i; phm_ppt_v1_clock_voltage_dependency_table *mclk_table; PP_ASSERT_WITH_CODE(mclk_dep_table->ucNumEntries, "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - mclk_dep_table->ucNumEntries; - - mclk_table = kzalloc(table_size, GFP_KERNEL); - + mclk_table = kzalloc(struct_size(mclk_table, entries, mclk_dep_table->ucNumEntries), + GFP_KERNEL); if (!mclk_table) return -ENOMEM; @@ -644,7 +633,7 @@ static int get_gfxclk_voltage_dependency_table( **pp_vega10_clk_dep_table, const ATOM_Vega10_GFXCLK_Dependency_Table *clk_dep_table) { - uint32_t table_size, i; + uint32_t i; struct phm_ppt_v1_clock_voltage_dependency_table *clk_table; ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; @@ -652,12 +641,8 @@ static int get_gfxclk_voltage_dependency_table( PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - clk_dep_table->ucNumEntries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - + clk_table = kzalloc(struct_size(clk_table, entries, clk_dep_table->ucNumEntries), + GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -711,19 +696,15 @@ static int get_pix_clk_voltage_dependency_table( **pp_vega10_clk_dep_table, const ATOM_Vega10_PIXCLK_Dependency_Table *clk_dep_table) { - uint32_t table_size, i; + uint32_t i; struct phm_ppt_v1_clock_voltage_dependency_table *clk_table; PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - clk_dep_table->ucNumEntries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - + clk_table = kzalloc(struct_size(clk_table, entries, clk_dep_table->ucNumEntries), + GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -747,7 +728,7 @@ static int get_dcefclk_voltage_dependency_table( **pp_vega10_clk_dep_table, const ATOM_Vega10_DCEFCLK_Dependency_Table *clk_dep_table) { - uint32_t table_size, i; + uint32_t i; uint8_t num_entries; struct phm_ppt_v1_clock_voltage_dependency_table *clk_table; @@ -775,12 +756,8 @@ static int get_dcefclk_voltage_dependency_table( num_entries = clk_dep_table->ucNumEntries; - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - num_entries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - + clk_table = kzalloc(struct_size(clk_table, entries, num_entries), + GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -807,7 +784,7 @@ static int get_pcie_table(struct pp_hwmgr *hwmgr, struct phm_ppt_v1_pcie_table **vega10_pcie_table, const Vega10_PPTable_Generic_SubTable_Header *table) { - uint32_t table_size, i, pcie_count; + uint32_t i, pcie_count; struct phm_ppt_v1_pcie_table *pcie_table; struct phm_ppt_v2_information *table_info = (struct phm_ppt_v2_information *)(hwmgr->pptable); @@ -818,12 +795,8 @@ static int get_pcie_table(struct pp_hwmgr *hwmgr, "Invalid PowerPlay Table!", return 0); - table_size = sizeof(uint32_t) + - sizeof(struct phm_ppt_v1_pcie_record) * - atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - + pcie_table = kzalloc(struct_size(pcie_table, entries, atom_pcie_table->ucNumEntries), + GFP_KERNEL); if (!pcie_table) return -ENOMEM; @@ -875,17 +848,14 @@ static int get_valid_clk( struct phm_clock_array **clk_table, const phm_ppt_v1_clock_voltage_dependency_table *clk_volt_pp_table) { - uint32_t table_size, i; + uint32_t i; struct phm_clock_array *table; PP_ASSERT_WITH_CODE(clk_volt_pp_table->count, "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(uint32_t) * clk_volt_pp_table->count; - - table = kzalloc(table_size, GFP_KERNEL); - + table = kzalloc(struct_size(table, values, clk_volt_pp_table->count), + GFP_KERNEL); if (!table) return -ENOMEM; @@ -1066,18 +1036,14 @@ static int get_vddc_lookup_table( const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables, uint32_t max_levels) { - uint32_t table_size, i; + uint32_t i; phm_ppt_v1_voltage_lookup_table *table; PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0), "Invalid SOC_VDDD Lookup Table!", return 1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; - - table = kzalloc(table_size, GFP_KERNEL); - - if (table == NULL) + table = kzalloc(struct_size(table, entries, max_levels), GFP_KERNEL); + if (!table) return -ENOMEM; table->count = vddc_lookup_pp_tables->ucNumEntries; @@ -1179,7 +1145,7 @@ static int init_dpm_2_parameters( return result; } -int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) +static int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) { int result = 0; const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index 952cd3d7240e..9b46b27bd30c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -118,12 +118,12 @@ int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) } /** -* Set Fan Speed Control to static mode, -* so that the user can decide what speed to use. -* @param hwmgr the address of the powerplay hardware manager. -* mode the fan control mode, 0 default, 1 by percent, 5, by RPM -* @exception Should always succeed. -*/ + * vega10_fan_ctrl_set_static_mode - Set Fan Speed Control to static mode, + * so that the user can decide what speed to use. + * @hwmgr: the address of the powerplay hardware manager. + * @mode: the fan control mode, 0 default, 1 by percent, 5, by RPM + * Exception: Should always succeed. + */ int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) { struct amdgpu_device *adev = hwmgr->adev; @@ -149,10 +149,10 @@ int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) } /** -* Reset Fan Speed Control to default mode. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Should always succeed. -*/ + * vega10_fan_ctrl_set_default_mode - Reset Fan Speed Control to default mode. + * @hwmgr: the address of the powerplay hardware manager. + * Exception: Should always succeed. + */ int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -173,11 +173,10 @@ int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) } /** - * @fn vega10_enable_fan_control_feature - * @brief Enables the SMC Fan Control Feature. + * vega10_enable_fan_control_feature - Enables the SMC Fan Control Feature. * - * @param hwmgr - the address of the powerplay hardware manager. - * @return 0 on success. -1 otherwise. + * @hwmgr: the address of the powerplay hardware manager. + * Return: 0 on success. -1 otherwise. */ static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr) { @@ -242,11 +241,11 @@ int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) } /** -* Set Fan Speed in percent. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (0% - 100%) to be set. -* @exception Fails is the 100% setting appears to be 0. -*/ + * vega10_fan_ctrl_set_fan_speed_percent - Set Fan Speed in percent. + * @hwmgr: the address of the powerplay hardware manager. + * @speed: is the percentage value (0% - 100%) to be set. + * Exception: Fails is the 100% setting appears to be 0. + */ int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed) { @@ -282,10 +281,10 @@ int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, } /** -* Reset Fan Speed to default. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Always succeeds. -*/ + * vega10_fan_ctrl_reset_fan_speed_to_default - Reset Fan Speed to default. + * @hwmgr: the address of the powerplay hardware manager. + * Exception: Always succeeds. + */ int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) { if (hwmgr->thermal_controller.fanInfo.bNoFan) @@ -298,11 +297,11 @@ int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) } /** -* Set Fan Speed in RPM. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (min - max) to be set. -* @exception Fails is the speed not lie between min and max. -*/ + * vega10_fan_ctrl_set_fan_speed_rpm - Set Fan Speed in RPM. + * @hwmgr: the address of the powerplay hardware manager. + * @speed: is the percentage value (min - max) to be set. + * Exception: Fails is the speed not lie between min and max. + */ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) { struct amdgpu_device *adev = hwmgr->adev; @@ -331,10 +330,10 @@ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) } /** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * vega10_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -353,13 +352,13 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) } /** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for -* high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ + * vega10_thermal_set_temperature_range - Set the requested temperature range for high and low alert signals + * + * @hwmgr: The address of the hardware manager. + * @range: Temperature range to be programmed for + * high and low alert signals + * Exception: PP_Result_BadInput if the input data is not valid. + */ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { @@ -406,10 +405,10 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, } /** -* Programs thermal controller one-time setting registers -* -* @param hwmgr The address of the hardware manager. -*/ + * vega10_thermal_initialize - Programs thermal controller one-time setting registers + * + * @hwmgr: The address of the hardware manager. + */ static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -429,10 +428,10 @@ static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr) } /** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * vega10_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -461,9 +460,9 @@ static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) } /** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ + * vega10_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller. + * @hwmgr: The address of the hardware manager. + */ int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -488,10 +487,10 @@ int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) } /** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ + * vega10_thermal_stop_thermal_controller - Uninitialize the thermal controller. + * Currently just disables alerts. + * @hwmgr: The address of the hardware manager. + */ int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) { int result = vega10_thermal_disable_alert(hwmgr); @@ -503,14 +502,10 @@ int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) } /** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ + * vega10_thermal_setup_fan_table - Set up the fan table to control the fan using the SMC. + * @hwmgr: the address of the powerplay hardware manager. + * Return: result from set temperature range routine + */ static int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { int ret; @@ -606,14 +601,10 @@ int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr) } /** -* Start the fan control on the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ + * vega10_thermal_start_smc_fan_control - Start the fan control on the SMC. + * @hwmgr: the address of the powerplay hardware manager. + * Return: result from set temperature range routine + */ static int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) { /* If the fantable setup has failed we could have disabled diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c index 740e2fc7a034..1e79baab753e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c @@ -252,12 +252,11 @@ static int init_powerplay_table_information( phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT); phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT); - pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); + pptable_information->smc_pptable = kmemdup(&(powerplay_table->smcPPTable), + sizeof(PPTable_t), GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; - memcpy(pptable_information->smc_pptable, &(powerplay_table->smcPPTable), sizeof(PPTable_t)); - result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); return result; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c index 7ace439dcde7..0dc16f25a463 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c @@ -60,11 +60,10 @@ int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) } /** - * @fn vega12_enable_fan_control_feature - * @brief Enables the SMC Fan Control Feature. + * vega12_enable_fan_control_feature -Enables the SMC Fan Control Feature. * - * @param hwmgr - the address of the powerplay hardware manager. - * @return 0 on success. -1 otherwise. + * @hwmgr: the address of the powerplay hardware manager. + * Return: 0 on success. -1 otherwise. */ static int vega12_enable_fan_control_feature(struct pp_hwmgr *hwmgr) { @@ -129,20 +128,20 @@ int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) } /** -* Reset Fan Speed to default. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Always succeeds. -*/ + * vega12_fan_ctrl_reset_fan_speed_to_default - Reset Fan Speed to default. + * @hwmgr: the address of the powerplay hardware manager. + * Exception Always succeeds. + */ int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) { return vega12_fan_ctrl_start_smc_fan_control(hwmgr); } /** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * vega12_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -160,13 +159,13 @@ int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr) } /** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for -* high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ + * Set the requested temperature range for high and low alert signals + * + * @hwmgr: The address of the hardware manager. + * @range: Temperature range to be programmed for + * high and low alert signals + * Exception: PP_Result_BadInput if the input data is not valid. + */ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { @@ -200,10 +199,10 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, } /** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * vega12_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ static int vega12_thermal_enable_alert(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -219,9 +218,9 @@ static int vega12_thermal_enable_alert(struct pp_hwmgr *hwmgr) } /** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ + * vega12_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller. + * @hwmgr: The address of the hardware manager. + */ int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -232,10 +231,10 @@ int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr) } /** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ + * vega12_thermal_stop_thermal_controller - Uninitialize the thermal controller. + * Currently just disables alerts. + * @hwmgr: The address of the hardware manager. + */ int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) { int result = vega12_thermal_disable_alert(hwmgr); @@ -244,14 +243,9 @@ int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) } /** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ + * vega12_thermal_setup_fan_table - Set up the fan table to control the fan using the SMC. + * @hwmgr: the address of the powerplay hardware manager. + */ static int vega12_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { int ret; @@ -267,14 +261,10 @@ static int vega12_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) } /** -* Start the fan control on the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ + * vega12_thermal_start_smc_fan_control - Start the fan control on the SMC. + * @hwmgr: the address of the powerplay hardware manager. + * Return: result from set temperature range routine + */ static int vega12_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) { /* If the fantable setup has failed we could have disabled diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index 364162ddaa9c..269dd7e95a44 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -209,10 +209,10 @@ int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) } /** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * vega20_thermal_get_temperature - Reads the remote temperature from the SIslands thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -230,13 +230,12 @@ int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr) } /** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for -* high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ + * vega20_thermal_set_temperature_range - Set the requested temperature range for high and low alert signals + * + * @hwmgr: The address of the hardware manager. + * @range: Temperature range to be programmed for high and low alert signals + * Exception: PP_Result_BadInput if the input data is not valid. + */ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { @@ -270,10 +269,10 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, } /** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ + * vega20_thermal_enable_alert - Enable thermal alerts on the RV770 thermal controller. + * + * @hwmgr: The address of the hardware manager. + */ static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -289,9 +288,9 @@ static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr) } /** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ + * vega20_thermal_disable_alert - Disable thermal alerts on the RV770 thermal controller. + * @hwmgr: The address of the hardware manager. + */ int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = hwmgr->adev; @@ -302,10 +301,10 @@ int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr) } /** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ + * vega20_thermal_stop_thermal_controller - Uninitialize the thermal controller. + * Currently just disables alerts. + * @hwmgr: The address of the hardware manager. + */ int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) { int result = vega20_thermal_disable_alert(hwmgr); @@ -314,14 +313,9 @@ int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) } /** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ + * vega20_thermal_setup_fan_table - Set up the fan table to control the fan using the SMC. + * @hwmgr: the address of the powerplay hardware manager. + */ static int vega20_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { int ret; diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c index 4b3faaccecb9..66daabebee35 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c @@ -1675,14 +1675,13 @@ static void kv_dpm_powergate_uvd(void *handle, bool gate) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); - int ret; pi->uvd_power_gated = gate; if (gate) { /* stop the UVD block */ - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); kv_update_uvd_dpm(adev, gate); if (pi->caps_uvd_pg) /* power off the UVD block */ @@ -1694,8 +1693,8 @@ static void kv_dpm_powergate_uvd(void *handle, bool gate) /* re-init the UVD block */ kv_update_uvd_dpm(adev, gate); - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_UNGATE); } } @@ -1703,14 +1702,13 @@ static void kv_dpm_powergate_vce(void *handle, bool gate) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct kv_power_info *pi = kv_get_pi(adev); - int ret; pi->vce_power_gated = gate; if (gate) { /* stop the VCE block */ - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); kv_enable_vce_dpm(adev, false); if (pi->caps_vce_pg) /* power off the VCE block */ amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF); @@ -1719,8 +1717,8 @@ static void kv_dpm_powergate_vce(void *handle, bool gate) amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); kv_enable_vce_dpm(adev, true); /* re-init the VCE block */ - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); } } diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c index b5986d19dc08..afa1711c9620 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c @@ -6200,8 +6200,8 @@ static void si_request_link_speed_change_before_state_change(struct amdgpu_devic case AMDGPU_PCIE_GEN2: if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) break; + fallthrough; #endif - /* fall through */ default: si_pi->force_pcie_gen = si_get_current_pcie_speed(adev); break; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c index e4d1f3d66ef4..93a1c7248e26 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c @@ -2193,7 +2193,7 @@ static int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) res = ci_copy_bytes_to_smc(hwmgr, ci_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); - return 0; + return res; } static int ci_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) @@ -2726,10 +2726,7 @@ static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) { - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, - VOLTAGE_CONTROLLER_ON)) - ? true : false; + return ci_is_smc_ram_running(hwmgr); } static int ci_smu_init(struct pp_hwmgr *hwmgr) @@ -2939,6 +2936,29 @@ static int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) return 0; } +static void ci_reset_smc(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, + rst_reg, 1); +} + + +static void ci_stop_smc_clock(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, + ck_disable, 1); +} + +static int ci_stop_smc(struct pp_hwmgr *hwmgr) +{ + ci_reset_smc(hwmgr); + ci_stop_smc_clock(hwmgr); + + return 0; +} + const struct pp_smumgr_func ci_smu_funcs = { .name = "ci_smu", .smu_init = ci_smu_init, @@ -2964,4 +2984,5 @@ const struct pp_smumgr_func ci_smu_funcs = { .is_dpm_running = ci_is_dpm_running, .update_dpm_settings = ci_update_dpm_settings, .update_smc_table = ci_update_smc_table, + .stop_smc = ci_stop_smc, }; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c index ecb9ee46d6b3..02c094a06605 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c @@ -318,13 +318,12 @@ static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr) { uint32_t efuse = 0; - uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1; if (!hwmgr->not_vf) return false; if (!atomctrl_read_efuse(hwmgr, AVFS_EN_LSB, AVFS_EN_MSB, - mask, &efuse)) { + &efuse)) { if (efuse) return true; } @@ -1091,7 +1090,7 @@ static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) } -/** +/* * MCLK Frequency Ratio * SEQ_CG_RESP Bit[31:24] - 0x0 * Bit[27:24] \96 DDR3 Frequency ratio @@ -1601,20 +1600,19 @@ static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, struct SMU73_Discrete_DpmTable *table) { - int result = 0; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); table->GraphicsBootLevel = 0; table->MemoryBootLevel = 0; /* find boot level from dpm table */ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(table->GraphicsBootLevel)); + phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(table->GraphicsBootLevel)); - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(table->MemoryBootLevel)); + phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(table->MemoryBootLevel)); table->BootVddc = data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c index 431ad2fd38df..03df35dee8ba 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c @@ -2082,7 +2082,7 @@ static int iceland_init_smc_table(struct pp_hwmgr *hwmgr) return 0; } -int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +static int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) { struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; @@ -2156,7 +2156,7 @@ int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) res = smu7_copy_bytes_to_smc(hwmgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); - return 0; + return res; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c index c3d2e6dcf62a..45214a364baa 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c @@ -401,6 +401,8 @@ static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, *voltage |= (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; else if (dep_table->entries[i-1].vddci) { + *voltage |= (dep_table->entries[i - 1].vddci * VOLTAGE_SCALE) << VDDC_SHIFT; + } else { vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), (dep_table->entries[i].vddc - (uint16_t)VDDC_VDDCI_DELTA)); @@ -470,6 +472,21 @@ static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmg return 0; } +static void polaris10_populate_zero_rpm_parameters(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + uint16_t fan_stop_temp = + ((uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucFanStopTemperature) << 8; + uint16_t fan_start_temp = + ((uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucFanStartTemperature) << 8; + + if (hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM) { + table->FanStartTemperature = PP_HOST_TO_SMC_US(fan_start_temp); + table->FanStopTemperature = PP_HOST_TO_SMC_US(fan_stop_temp); + } +} + static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr) { struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); @@ -671,6 +688,31 @@ static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, return 0; } +static int polaris10_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + uint32_t count, level; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + count = data->vddc_voltage_table.count; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { + if (count > SMU_MAX_SMIO_LEVELS) + count = SMU_MAX_SMIO_LEVELS; + for (level = 0; level < count; ++level) { + table->SmioTable1.Pattern[level].Voltage = + PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[level].value * VOLTAGE_SCALE); + table->SmioTable1.Pattern[level].Smio = (uint8_t) level; + + table->Smio[level] |= data->vddc_voltage_table.entries[level].smio_low; + } + + table->SmioMask1 = data->vddc_voltage_table.mask_low; + } + + return 0; +} + static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, struct SMU74_Discrete_DpmTable *table) { @@ -689,9 +731,9 @@ static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low; } - } - table->SmioMask1 = data->vddci_voltage_table.mask_low; + table->SmioMask1 = data->vddci_voltage_table.mask_low; + } return 0; } @@ -725,6 +767,7 @@ static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr, static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, struct SMU74_Discrete_DpmTable *table) { + polaris10_populate_smc_vddc_table(hwmgr, table); polaris10_populate_smc_vddci_table(hwmgr, table); polaris10_populate_smc_mvdd_table(hwmgr, table); polaris10_populate_cac_table(hwmgr, table); @@ -738,6 +781,7 @@ static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct amdgpu_device *adev = hwmgr->adev; state->CcPwrDynRm = 0; state->CcPwrDynRm1 = 0; @@ -746,7 +790,11 @@ static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) + if ((hwmgr->chip_id == CHIP_POLARIS12) || + ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P21(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P30(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; else state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1; @@ -975,6 +1023,16 @@ static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr, return 0; } +static void polaris10_get_vddc_shared_railinfo(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + uint8_t shared_rail; + + if (!atomctrl_get_vddc_shared_railinfo(hwmgr, &shared_rail)) + table->SharedRails = shared_rail; +} + static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -996,6 +1054,13 @@ static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0, count = 0; + struct amdgpu_device *adev = hwmgr->adev; + pp_atomctrl_clock_dividers_vi dividers; + uint32_t dpm0_sclkfrequency = levels[0].SclkSetting.SclkFrequency; + + if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) || + ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) + polaris10_get_vddc_shared_railinfo(hwmgr); polaris10_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table)); @@ -1012,15 +1077,31 @@ static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) levels[i].DeepSleepDivId = 0; } if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SPLLShutdownSupport)) + PHM_PlatformCaps_SPLLShutdownSupport)) { smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0; + if (dpm0_sclkfrequency != levels[0].SclkSetting.SclkFrequency) { + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + dpm_table->sclk_table.dpm_levels[0].value, + ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for sclk", + return result); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetGpuPllDfsForSclk, + dividers.real_clock < dpm_table->sclk_table.dpm_levels[0].value ? + dividers.pll_post_divider - 1 : dividers.pll_post_divider, + NULL); + } + } - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; smu_data->smc_state_table.GraphicsDpmLevelCount = (uint8_t)dpm_table->sclk_table.count; hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) + smu_data->smc_state_table.GraphicsLevel[i].EnabledForActivity = + (hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask & (1 << i)) >> i; if (pcie_table != NULL) { PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), @@ -1110,7 +1191,9 @@ static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, if (mclk_stutter_mode_threshold && (clock <= mclk_stutter_mode_threshold) && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE) & 0x1)) + STUTTER_ENABLE) & 0x1) && + (data->display_timing.num_existing_displays <= 2) && + data->display_timing.num_existing_displays) mem_level->StutterEnable = true; if (!result) { @@ -1144,27 +1227,21 @@ static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) result = polaris10_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, &levels[i]); - if (i == dpm_table->mclk_table.count - 1) { + if (i == dpm_table->mclk_table.count - 1) levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - levels[i].EnabledForActivity = 1; - } if (result) return result; } - /* In order to prevent MC activity from stutter mode to push DPM up, - * the UVD change complements this by putting the MCLK in - * a higher state by default such that we are not affected by - * up threshold or and MCLK DPM latency. - */ - levels[0].ActivityLevel = 0x1f; - CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) + smu_data->smc_state_table.MemoryLevel[i].EnabledForActivity = + (hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask & (1 << i)) >> i; + /* level count will send to smc once at init smc table and never change */ result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, (uint32_t)array_size, SMC_RAM_END); @@ -1275,8 +1352,9 @@ static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, table->MemoryACPILevel.UpHyst = 0; table->MemoryACPILevel.DownHyst = 100; table->MemoryACPILevel.VoltageDownHyst = 0; + /* To align with the settings from other OSes */ table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); + PP_HOST_TO_SMC_US(data->current_profile_setting.sclk_activity); CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); @@ -1334,6 +1412,55 @@ static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr, return result; } +static int polaris10_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->SamuLevelCount = (uint8_t)(mm_table->count); + table->SamuBootLevel = 0; + + for (count = 0; count < table->SamuLevelCount; count++) { + table->SamuLevel[count].Frequency = mm_table->entries[count].samclock; + table->SamuLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + + table->SamuLevel[count].MinVoltage |= + (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /*retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage); + } + return result; +} + static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, int32_t eng_clock, int32_t mem_clock, SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs) @@ -1374,7 +1501,7 @@ static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) hw_data->dpm_table.sclk_table.dpm_levels[i].value, hw_data->dpm_table.mclk_table.dpm_levels[j].value, &arb_regs.entries[i][j]); - if (result == 0) + if (result == 0 && i == 0) result = atomctrl_set_ac_timing_ai(hwmgr, hw_data->dpm_table.mclk_table.dpm_levels[j].value, j); if (result != 0) return result; @@ -1460,10 +1587,18 @@ static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr, result = phm_find_boot_level(&(data->dpm_table.sclk_table), data->vbios_boot_state.sclk_bootup_value, (uint32_t *)&(table->GraphicsBootLevel)); + if (result) { + table->GraphicsBootLevel = 0; + result = 0; + } result = phm_find_boot_level(&(data->dpm_table.mclk_table), data->vbios_boot_state.mclk_bootup_value, (uint32_t *)&(table->MemoryBootLevel)); + if (result) { + table->MemoryBootLevel = 0; + result = 0; + } table->BootVddc = data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; @@ -1509,49 +1644,28 @@ static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) return 0; } +#define STRAP_ASIC_RO_LSB 2168 +#define STRAP_ASIC_RO_MSB 2175 + static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) { - uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - uint8_t i, stretch_amount, volt_offset = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = table_info->vdd_dep_on_sclk; + uint32_t ro, efuse, volt_without_cks, volt_with_cks, value; + uint8_t i, stretch_amount, volt_offset = 0; stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; /* Read SMU_Eefuse to read and calculate RO and determine * if the part is SS or FF. if RO >= 1660MHz, part is FF. */ - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (67 * 4)); - efuse &= 0xFF000000; - efuse = efuse >> 24; - - if (hwmgr->chip_id == CHIP_POLARIS10) { - if (hwmgr->is_kicker) { - min = 1200; - max = 2500; - } else { - min = 1000; - max = 2300; - } - } else if (hwmgr->chip_id == CHIP_POLARIS11) { - if (hwmgr->is_kicker) { - min = 900; - max = 2100; - } else { - min = 1100; - max = 2100; - } - } else { - min = 1100; - max = 2100; - } - - ro = efuse * (max - min) / 255 + min; + atomctrl_read_efuse(hwmgr, STRAP_ASIC_RO_LSB, STRAP_ASIC_RO_MSB, &efuse); + ro = ((efuse * (data->ro_range_maximum - data->ro_range_minimum)) / 255) + + data->ro_range_minimum; /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ for (i = 0; i < sclk_table->count; i++) { @@ -1576,7 +1690,8 @@ static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; } - smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6; + smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 5; + /* Populate CKS Lookup Table */ if (stretch_amount == 0 || stretch_amount > 5) { phm_cap_unset(hwmgr->platform_descriptor.platformCaps, @@ -1607,6 +1722,9 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { config = VR_SVI2_PLANE_1; table->VRConfig |= config; + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= config; } else { PP_ASSERT_WITH_CODE(false, "VDDC should be on SVI2 control in merged mode!", @@ -1625,7 +1743,17 @@ static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, } /* Set Mvdd Voltage Controller */ if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { - config = VR_SVI2_PLANE_2; + if (config != VR_SVI2_PLANE_2) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start + + offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + config = VR_SMIO_PATTERN_2; table->VRConfig |= (config << VRCONF_MVDD_SHIFT); cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start + offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1); @@ -1660,16 +1788,18 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) if (!hwmgr->avfs_supported) return 0; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { + hwmgr->avfs_supported = 0; + return 0; + } + result = atomctrl_get_avfs_information(hwmgr, &avfs_params); if (0 == result) { - if (((adev->pdev->device == 0x67ef) && - ((adev->pdev->revision == 0xe0) || - (adev->pdev->revision == 0xe5))) || - ((adev->pdev->device == 0x67ff) && - ((adev->pdev->revision == 0xcf) || - (adev->pdev->revision == 0xef) || - (adev->pdev->revision == 0xff)))) { + if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision) || + ((hwmgr->chip_id == CHIP_POLARIS12) && !ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) || + ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)) { avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; if ((adev->pdev->device == 0x67ef && adev->pdev->revision == 0xe5) || (adev->pdev->device == 0x67ff && adev->pdev->revision == 0xef)) { @@ -1686,32 +1816,21 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0; avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x23; } + } else if (hwmgr->chip_id == CHIP_POLARIS12 && !ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) { + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF6B024DD; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x3005E; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x18A5F; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0x315; + avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFED1; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x3B; + } else if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)) { + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF843B66B; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x59CB5; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0xFFFF287F; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; + avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFF23; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x58; } - } else if (hwmgr->chip_id == CHIP_POLARIS12 && !hwmgr->is_kicker) { - avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF6B024DD; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x3005E; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x18A5F; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0x315; - avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFED1; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x3B; - } else if (((adev->pdev->device == 0x67df) && - ((adev->pdev->revision == 0xe0) || - (adev->pdev->revision == 0xe3) || - (adev->pdev->revision == 0xe4) || - (adev->pdev->revision == 0xe5) || - (adev->pdev->revision == 0xe7) || - (adev->pdev->revision == 0xef))) || - ((adev->pdev->device == 0x6fdf) && - ((adev->pdev->revision == 0xef) || - (adev->pdev->revision == 0xff)))) { - avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF843B66B; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x59CB5; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0xFFFF287F; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; - avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFF23; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x58; } } @@ -1774,33 +1893,6 @@ static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) return result; } -static int polaris10_init_arb_table_index(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - - /* This is a read-modify-write on the first byte of the ARB table. - * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure - * is the field 'current'. - * This solution is ugly, but we never write the whole table only - * individual fields in it. - * In reality this field should not be in that structure - * but in a soft register. - */ - result = smu7_read_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); - - if (result) - return result; - - tmp &= 0x00FFFFFF; - tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - - return smu7_write_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); -} - static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) { struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); @@ -1830,6 +1922,7 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) uint8_t i; struct pp_atomctrl_gpio_pin_assignment gpio_pin; pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_gpio_table *gpio_table = table_info->gpio_table; polaris10_initialize_power_tune_defaults(hwmgr); @@ -1876,6 +1969,10 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize VCE Level!", return result); + result = polaris10_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result); + /* Since only the initial state is completely set up at this point * (the other states are just copies of the boot state) we only * need to populate the ARB settings for the initial state. @@ -1900,6 +1997,8 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); + polaris10_populate_zero_rpm_parameters(hwmgr); + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ClockStretcher)) { result = polaris10_populate_clock_stretcher_data_table(hwmgr); @@ -1928,7 +2027,7 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) table->VoltageResponseTime = 0; table->PhaseResponseTime = 0; table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; + table->PCIeBootLinkLevel = hw_data->dpm_table.pcie_speed_table.count; table->PCIeGenInterval = 1; table->VRConfig = 0; @@ -1941,6 +2040,8 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + if (gpio_table) + table->VRHotLevel = gpio_table->vrhot_triggered_sclk_dpm_index; } else { table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; phm_cap_unset(hwmgr->platform_descriptor.platformCaps, @@ -1950,8 +2051,11 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, &gpio_pin)) { table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition) && + !smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UseNewGPIOScheme, NULL)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); } else { table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; phm_cap_unset(hwmgr->platform_descriptor.platformCaps, @@ -2020,10 +2124,6 @@ static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(0 == result, "Failed to upload dpm data to SMC memory!", return result); - result = polaris10_init_arb_table_index(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload arb data to SMC memory!", return result); - result = polaris10_populate_pm_fuses(hwmgr); PP_ASSERT_WITH_CODE(0 == result, "Failed to populate PM fuses to SMC memory!", return result); @@ -2042,7 +2142,7 @@ static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) return 0; } -int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +static int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -2272,6 +2372,7 @@ static int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) break; case SMU_BIF_TABLE: polaris10_update_bif_smc_table(hwmgr); + break; default: break; } @@ -2380,7 +2481,8 @@ static uint32_t polaris10_get_mac_definition(uint32_t value) case SMU_MAX_LEVELS_MVDD: return SMU74_MAX_LEVELS_MVDD; case SMU_UVD_MCLK_HANDSHAKE_DISABLE: - return SMU7_UVD_MCLK_HANDSHAKE_DISABLE; + return SMU7_UVD_MCLK_HANDSHAKE_DISABLE | + SMU7_VCE_MCLK_HANDSHAKE_DISABLE; } pr_warn("can't get the mac of %x\n", value); @@ -2458,6 +2560,24 @@ static int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) return error ? -1 : 0; } +static uint8_t polaris10_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static int polaris10_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + pp_atomctrl_mc_reg_table *mc_reg_table = &smu_data->mc_reg_table; + uint8_t module_index = polaris10_get_memory_modile_index(hwmgr); + + memset(mc_reg_table, 0, sizeof(pp_atomctrl_mc_reg_table)); + result = atomctrl_initialize_mc_reg_table_v2_2(hwmgr, module_index, mc_reg_table); + + return result; +} + static bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr) { return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, @@ -2584,6 +2704,7 @@ const struct pp_smumgr_func polaris10_smu_funcs = { .populate_all_graphic_levels = polaris10_populate_all_graphic_levels, .populate_all_memory_levels = polaris10_populate_all_memory_levels, .get_mac_definition = polaris10_get_mac_definition, + .initialize_mc_reg_table = polaris10_initialize_mc_reg_table, .is_dpm_running = polaris10_is_dpm_running, .is_hw_avfs_present = polaris10_is_hw_avfs_present, .update_dpm_settings = polaris10_update_dpm_settings, diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h index 1ec425df9eda..6f4c48ac34b8 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h @@ -60,6 +60,7 @@ struct polaris10_smumgr { struct polaris10_range_table range_table[NUM_SCLK_RANGE]; const struct polaris10_pt_defaults *power_tune_defaults; uint32_t bif_sclk_table[SMU74_MAX_LEVELS_LINK]; + pp_atomctrl_mc_reg_table mc_reg_table; }; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c index ea2279bb8cbf..47b34c6ca924 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c @@ -139,8 +139,7 @@ static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr, priv->smu_tables.entry[table_id].table_id, NULL); - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); + amdgpu_asic_invalidate_hdp(adev, NULL); memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table, priv->smu_tables.entry[table_id].size); diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c index 8a9aee85043e..23e5de3c4ec1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c @@ -22,6 +22,7 @@ */ #include "smumgr.h" +#include "smu9_smumgr.h" #include "vega10_inc.h" #include "soc15_common.h" #include "pp_debug.h" diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c index b6fb48066841..b6921db3c130 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c @@ -245,3 +245,11 @@ int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t tabl return -EINVAL; } + +int smum_stop_smc(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->smumgr_funcs->stop_smc) + return hwmgr->smumgr_funcs->stop_smc(hwmgr); + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c index 4bfadb49521b..04b561f5d932 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c @@ -2545,7 +2545,7 @@ static int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) (uint32_t)sizeof(fan_table), SMC_RAM_END); - return 0; + return res; } diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c index daf122f24f23..a70d73896649 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c @@ -60,8 +60,7 @@ static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr, priv->smu_tables.entry[table_id].table_id, NULL); - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); + amdgpu_asic_invalidate_hdp(adev, NULL); memcpy(table, priv->smu_tables.entry[table_id].table, priv->smu_tables.entry[table_id].size); @@ -209,13 +208,11 @@ static int vega10_smu_init(struct pp_hwmgr *hwmgr) int ret; struct cgs_firmware_info info = {0}; - if (!amdgpu_sriov_vf((struct amdgpu_device *)hwmgr->adev)) { - ret = cgs_get_firmware_info(hwmgr->device, - CGS_UCODE_ID_SMU, - &info); - if (ret || !info.kptr) - return -EINVAL; - } + ret = cgs_get_firmware_info(hwmgr->device, + CGS_UCODE_ID_SMU, + &info); + if (ret || !info.kptr) + return -EINVAL; priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL); diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c index f54df76537e4..b52ce135d84d 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c @@ -68,8 +68,7 @@ static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr, "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", return -EINVAL); - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); + amdgpu_asic_invalidate_hdp(adev, NULL); memcpy(table, priv->smu_tables.entry[table_id].table, priv->smu_tables.entry[table_id].size); diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c index cf43629d29d2..741fbc87467f 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c @@ -192,8 +192,7 @@ static int vega20_copy_table_from_smc(struct pp_hwmgr *hwmgr, "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", return ret); - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); + amdgpu_asic_invalidate_hdp(adev, NULL); memcpy(table, priv->smu_tables.entry[table_id].table, priv->smu_tables.entry[table_id].size); @@ -307,8 +306,7 @@ int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr, "[GetActivityMonitor] Attempt to Transfer Table From SMU Failed!", return ret); - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); + amdgpu_asic_invalidate_hdp(adev, NULL); memcpy(table, priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table, priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size); diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c index 0ecc18b55ffb..7d024d3facef 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c @@ -1495,12 +1495,11 @@ static int vegam_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) (struct phm_ppt_v1_information *)(hwmgr->pptable); struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = table_info->vdd_dep_on_sclk; - uint32_t mask = (1 << ((STRAP_ASIC_RO_MSB - STRAP_ASIC_RO_LSB) + 1)) - 1; stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; atomctrl_read_efuse(hwmgr, STRAP_ASIC_RO_LSB, STRAP_ASIC_RO_MSB, - mask, &efuse); + &efuse); min = 1200; max = 2500; @@ -2247,7 +2246,7 @@ static int vegam_update_sclk_threshold(struct pp_hwmgr *hwmgr) return result; } -int vegam_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +static int vegam_thermal_avfs_enable(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); int ret; |