aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/pm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/pm')
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_dpm.c3
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c21
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h64
-rw-r--r--drivers/gpu/drm/amd/pm/inc/hwmgr.h26
-rw-r--r--drivers/gpu/drm/amd/pm/inc/pp_thermal.h4
-rw-r--r--drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h3
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu10.h14
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h28
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu11_driver_if_vangogh.h245
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu74_discrete.h3
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h6
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_types.h76
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_0.h11
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h6
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_5_pmfw.h123
-rw-r--r--drivers/gpu/drm/amd/pm/inc/smu_v11_5_ppsmc.h115
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c19
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c56
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c14
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h8
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c7
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c207
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h28
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c24
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h6
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h66
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c273
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c188
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c22
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c737
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h20
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c34
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c114
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c31
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c90
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c131
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c5
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c82
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c54
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c18
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/si_dpm.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c18
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c4
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c359
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h1
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c3
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c1
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c15
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c3
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c6
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c244
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile1
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c130
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c302
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c412
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c140
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c773
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.h39
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c216
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c57
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_internal.h9
69 files changed, 3893 insertions, 1848 deletions
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
index 17a45baff638..8fb12afe3c96 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
@@ -1168,6 +1168,9 @@ int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev,
{
int ret = 0;
+ if (amdgpu_sriov_vf(adev))
+ return 0;
+
if (is_support_sw_smu(adev))
ret = smu_switch_power_profile(&adev->smu, type, en);
else if (adev->powerplay.pp_funcs &&
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 529816637c73..7b6ef05a1d35 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -39,6 +39,7 @@
#include "hwmgr.h"
static const struct cg_flag_name clocks[] = {
+ {AMD_CG_SUPPORT_GFX_FGCG, "Graphics Fine Grain Clock Gating"},
{AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"},
{AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"},
{AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"},
@@ -63,6 +64,11 @@ static const struct cg_flag_name clocks[] = {
{AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"},
{AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"},
{AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_VCN_MGCG, "VCN Medium Grain Clock Gating"},
+ {AMD_CG_SUPPORT_HDP_DS, "Host Data Path Deep Sleep"},
+ {AMD_CG_SUPPORT_HDP_SD, "Host Data Path Shutdown"},
+ {AMD_CG_SUPPORT_IH_CG, "Interrupt Handler Clock Gating"},
+ {AMD_CG_SUPPORT_JPEG_MGCG, "JPEG Medium Grain Clock Gating"},
{AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"},
{AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"},
@@ -940,8 +946,6 @@ static ssize_t amdgpu_set_pp_features(struct device *dev,
if (ret)
return -EINVAL;
- pr_debug("featuremask = 0x%llx\n", featuremask);
-
ret = pm_runtime_get_sync(ddev->dev);
if (ret < 0) {
pm_runtime_put_autosuspend(ddev->dev);
@@ -1501,7 +1505,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev,
}
if (is_support_sw_smu(adev))
- value = smu_get_od_percentage(&(adev->smu), SMU_OD_SCLK);
+ value = 0;
else if (adev->powerplay.pp_funcs->get_sclk_od)
value = amdgpu_dpm_get_sclk_od(adev);
@@ -1536,7 +1540,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev,
}
if (is_support_sw_smu(adev)) {
- value = smu_set_od_percentage(&(adev->smu), SMU_OD_SCLK, (uint32_t)value);
+ value = 0;
} else {
if (adev->powerplay.pp_funcs->set_sclk_od)
amdgpu_dpm_set_sclk_od(adev, (uint32_t)value);
@@ -1574,7 +1578,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev,
}
if (is_support_sw_smu(adev))
- value = smu_get_od_percentage(&(adev->smu), SMU_OD_MCLK);
+ value = 0;
else if (adev->powerplay.pp_funcs->get_mclk_od)
value = amdgpu_dpm_get_mclk_od(adev);
@@ -1609,7 +1613,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev,
}
if (is_support_sw_smu(adev)) {
- value = smu_set_od_percentage(&(adev->smu), SMU_OD_MCLK, (uint32_t)value);
+ value = 0;
} else {
if (adev->powerplay.pp_funcs->set_mclk_od)
amdgpu_dpm_set_mclk_od(adev, (uint32_t)value);
@@ -2060,9 +2064,6 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_
} else if (DEVICE_ATTR_IS(pp_dpm_fclk)) {
if (asic_type < CHIP_VEGA20)
*states = ATTR_STATE_UNSUPPORTED;
- } else if (DEVICE_ATTR_IS(pp_dpm_pcie)) {
- if (asic_type == CHIP_ARCTURUS)
- *states = ATTR_STATE_UNSUPPORTED;
} else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) {
*states = ATTR_STATE_UNSUPPORTED;
if ((is_support_sw_smu(adev) && adev->smu.od_enabled) ||
@@ -3467,7 +3468,7 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev)
{
uint32_t value;
- uint64_t value64;
+ uint64_t value64 = 0;
uint32_t query = 0;
int size;
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
index 44fd0cd069de..4bdbcce7092d 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
@@ -31,6 +31,7 @@
#define SMU_THERMAL_MINIMUM_ALERT_TEMP 0
#define SMU_THERMAL_MAXIMUM_ALERT_TEMP 255
#define SMU_TEMPERATURE_UNITS_PER_CENTIGRADES 1000
+#define SMU_FW_NAME_LEN 0x24
struct smu_hw_power_state {
unsigned int magic;
@@ -98,7 +99,7 @@ struct smu_state_display_block {
bool enable_vari_bright;
};
-struct smu_state_memroy_block {
+struct smu_state_memory_block {
bool dll_off;
uint8_t m3arb;
uint8_t unused[3];
@@ -145,7 +146,7 @@ struct smu_power_state {
struct smu_state_validation_block validation;
struct smu_state_pcie_block pcie;
struct smu_state_display_block display;
- struct smu_state_memroy_block memory;
+ struct smu_state_memory_block memory;
struct smu_state_software_algorithm_block software;
struct smu_uvd_clocks uvd_clocks;
struct smu_hw_power_state hardware;
@@ -225,6 +226,8 @@ struct smu_bios_boot_up_values
uint32_t format_revision;
uint32_t content_revision;
uint32_t fclk;
+ uint32_t lclk;
+ uint32_t firmware_caps;
};
enum smu_table_id
@@ -457,6 +460,11 @@ struct smu_context
unsigned fan_max_rpm;
unsigned manual_fan_speed_rpm;
+
+ uint32_t gfx_default_hard_min_freq;
+ uint32_t gfx_default_soft_max_freq;
+ uint32_t gfx_actual_hard_min_freq;
+ uint32_t gfx_actual_soft_max_freq;
};
struct i2c_adapter;
@@ -470,11 +478,6 @@ struct pptable_funcs {
int (*populate_umd_state_clk)(struct smu_context *smu);
int (*print_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf);
int (*force_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t mask);
- int (*set_default_od8_settings)(struct smu_context *smu);
- int (*get_od_percentage)(struct smu_context *smu, enum smu_clk_type clk_type);
- int (*set_od_percentage)(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint32_t value);
int (*od_edit_dpm_table)(struct smu_context *smu,
enum PP_OD_DPM_TABLE_COMMAND type,
long *input, uint32_t size);
@@ -483,11 +486,6 @@ struct pptable_funcs {
struct
pp_clock_levels_with_latency
*clocks);
- int (*get_clock_by_type_with_voltage)(struct smu_context *smu,
- enum amd_pp_clock_type type,
- struct
- pp_clock_levels_with_voltage
- *clocks);
int (*get_power_profile_mode)(struct smu_context *smu, char *buf);
int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size);
int (*dpm_set_vcn_enable)(struct smu_context *smu, bool enable);
@@ -498,7 +496,6 @@ struct pptable_funcs {
int (*display_config_changed)(struct smu_context *smu);
int (*apply_clocks_adjust_rules)(struct smu_context *smu);
int (*notify_smc_display_config)(struct smu_context *smu);
- int (*set_cpu_power_state)(struct smu_context *smu);
bool (*is_dpm_running)(struct smu_context *smu);
int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
int (*set_watermarks_table)(struct smu_context *smu,
@@ -534,7 +531,6 @@ struct pptable_funcs {
int (*set_driver_table_location)(struct smu_context *smu);
int (*set_tool_table_location)(struct smu_context *smu);
int (*notify_memory_pool_location)(struct smu_context *smu);
- int (*set_last_dcef_min_deep_sleep_clk)(struct smu_context *smu);
int (*system_features_control)(struct smu_context *smu, bool en);
int (*send_smc_msg_with_param)(struct smu_context *smu,
enum smu_message_type msg, uint32_t param, uint32_t *read_arg);
@@ -552,27 +548,9 @@ struct pptable_funcs {
int (*enable_thermal_alert)(struct smu_context *smu);
int (*disable_thermal_alert)(struct smu_context *smu);
int (*set_min_dcef_deep_sleep)(struct smu_context *smu, uint32_t clk);
- int (*set_active_display_count)(struct smu_context *smu, uint32_t count);
- int (*store_cc6_data)(struct smu_context *smu, uint32_t separation_time,
- bool cc6_disable, bool pstate_disable,
- bool pstate_switch_disable);
- int (*get_clock_by_type)(struct smu_context *smu,
- enum amd_pp_clock_type type,
- struct amd_pp_clocks *clocks);
- int (*get_max_high_clocks)(struct smu_context *smu,
- struct amd_pp_simple_clock_info *clocks);
int (*display_clock_voltage_request)(struct smu_context *smu, struct
pp_display_clock_request
*clock_req);
- int (*get_dal_power_level)(struct smu_context *smu,
- struct amd_pp_simple_clock_info *clocks);
- int (*get_perf_level)(struct smu_context *smu,
- enum smu_perf_level_designation designation,
- struct smu_performance_level *level);
- int (*get_current_shallow_sleep_clocks)(struct smu_context *smu,
- struct smu_clock_info *clocks);
- int (*notify_smu_enable_pwe)(struct smu_context *smu);
- int (*conv_power_profile_to_pplib_workload)(int power_profile);
uint32_t (*get_fan_control_mode)(struct smu_context *smu);
int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed);
@@ -603,6 +581,9 @@ struct pptable_funcs {
int (*get_fan_parameters)(struct smu_context *smu);
int (*post_init)(struct smu_context *smu);
void (*interrupt_work)(struct smu_context *smu);
+ int (*gpo_control)(struct smu_context *smu, bool enablement);
+ int (*gfx_state_change_set)(struct smu_context *smu, uint32_t state);
+ int (*set_fine_grain_gfx_freq_parameters)(struct smu_context *smu);
};
typedef enum {
@@ -633,6 +614,8 @@ typedef enum {
METRICS_TEMPERATURE_VRMEM,
METRICS_THROTTLER_STATUS,
METRICS_CURR_FANSPEED,
+ METRICS_VOLTAGE_VDDSOC,
+ METRICS_VOLTAGE_VDDGFX,
} MetricsMember_t;
enum smu_cmn2asic_mapping_type {
@@ -683,8 +666,6 @@ int smu_get_power_limit(struct smu_context *smu,
int smu_set_power_limit(struct smu_context *smu, uint32_t limit);
int smu_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf);
-int smu_get_od_percentage(struct smu_context *smu, enum smu_clk_type type);
-int smu_set_od_percentage(struct smu_context *smu, enum smu_clk_type type, uint32_t value);
int smu_od_edit_dpm_table(struct smu_context *smu,
enum PP_OD_DPM_TABLE_COMMAND type,
@@ -707,25 +688,13 @@ int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed);
int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk);
-int smu_get_clock_by_type(struct smu_context *smu,
- enum amd_pp_clock_type type,
- struct amd_pp_clocks *clocks);
-
-int smu_get_max_high_clocks(struct smu_context *smu,
- struct amd_pp_simple_clock_info *clocks);
-
int smu_get_clock_by_type_with_latency(struct smu_context *smu,
enum smu_clk_type clk_type,
struct pp_clock_levels_with_latency *clocks);
-int smu_get_clock_by_type_with_voltage(struct smu_context *smu,
- enum amd_pp_clock_type type,
- struct pp_clock_levels_with_voltage *clocks);
-
int smu_display_clock_voltage_request(struct smu_context *smu,
struct pp_display_clock_request *clock_req);
int smu_display_disable_memory_clock_switch(struct smu_context *smu, bool disable_memory_clock_switch);
-int smu_notify_smu_enable_pwe(struct smu_context *smu);
int smu_set_xgmi_pstate(struct smu_context *smu,
uint32_t pstate);
@@ -763,8 +732,6 @@ int smu_set_watermarks_for_clock_ranges(
extern int smu_display_configuration_change(struct smu_context *smu, const
struct amd_pp_display_configuration
*display_config);
-extern int smu_get_current_clocks(struct smu_context *smu,
- struct amd_pp_clock_info *clocks);
extern int smu_dpm_set_power_gate(struct smu_context *smu,uint32_t block_type, bool gate);
extern int smu_handle_task(struct smu_context *smu,
enum amd_dpm_forced_level level,
@@ -807,6 +774,7 @@ int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value);
ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, void **table);
int smu_enable_mgpu_fan_boost(struct smu_context *smu);
+int smu_gfx_state_change_set(struct smu_context *smu, uint32_t state);
#endif
#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/inc/hwmgr.h
index 518796a26eda..490371bd2520 100644
--- a/drivers/gpu/drm/amd/pm/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/pm/inc/hwmgr.h
@@ -60,7 +60,7 @@ struct vi_dpm_level {
struct vi_dpm_table {
uint32_t count;
- struct vi_dpm_level dpm_level[1];
+ struct vi_dpm_level dpm_level[];
};
#define PCIE_PERF_REQ_REMOVE_REGISTRY 0
@@ -91,7 +91,7 @@ struct phm_set_power_state_input {
struct phm_clock_array {
uint32_t count;
- uint32_t values[1];
+ uint32_t values[];
};
struct phm_clock_voltage_dependency_record {
@@ -122,8 +122,8 @@ struct phm_acpclock_voltage_dependency_record {
};
struct phm_clock_voltage_dependency_table {
- uint32_t count; /* Number of entries. */
- struct phm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */
+ uint32_t count; /* Number of entries. */
+ struct phm_clock_voltage_dependency_record entries[]; /* Dynamically allocate count entries. */
};
struct phm_phase_shedding_limits_record {
@@ -140,7 +140,7 @@ struct phm_uvd_clock_voltage_dependency_record {
struct phm_uvd_clock_voltage_dependency_table {
uint8_t count;
- struct phm_uvd_clock_voltage_dependency_record entries[1];
+ struct phm_uvd_clock_voltage_dependency_record entries[];
};
struct phm_acp_clock_voltage_dependency_record {
@@ -150,7 +150,7 @@ struct phm_acp_clock_voltage_dependency_record {
struct phm_acp_clock_voltage_dependency_table {
uint32_t count;
- struct phm_acp_clock_voltage_dependency_record entries[1];
+ struct phm_acp_clock_voltage_dependency_record entries[];
};
struct phm_vce_clock_voltage_dependency_record {
@@ -161,7 +161,7 @@ struct phm_vce_clock_voltage_dependency_record {
struct phm_phase_shedding_limits_table {
uint32_t count;
- struct phm_phase_shedding_limits_record entries[1];
+ struct phm_phase_shedding_limits_record entries[];
};
struct phm_vceclock_voltage_dependency_table {
@@ -186,7 +186,7 @@ struct phm_acpclock_voltage_dependency_table {
struct phm_vce_clock_voltage_dependency_table {
uint8_t count;
- struct phm_vce_clock_voltage_dependency_record entries[1];
+ struct phm_vce_clock_voltage_dependency_record entries[];
};
@@ -366,6 +366,7 @@ struct pp_hwmgr_func {
int (*disable_power_features_for_compute_performance)(struct pp_hwmgr *hwmgr,
bool disable);
ssize_t (*get_gpu_metrics)(struct pp_hwmgr *hwmgr, void **table);
+ int (*gfx_state_change)(struct pp_hwmgr *hwmgr, uint32_t state);
};
struct pp_table_func {
@@ -394,7 +395,7 @@ union phm_cac_leakage_record {
struct phm_cac_leakage_table {
uint32_t count;
- union phm_cac_leakage_record entries[1];
+ union phm_cac_leakage_record entries[];
};
struct phm_samu_clock_voltage_dependency_record {
@@ -405,7 +406,7 @@ struct phm_samu_clock_voltage_dependency_record {
struct phm_samu_clock_voltage_dependency_table {
uint8_t count;
- struct phm_samu_clock_voltage_dependency_record entries[1];
+ struct phm_samu_clock_voltage_dependency_record entries[];
};
struct phm_cac_tdp_table {
@@ -442,6 +443,7 @@ struct phm_cac_tdp_table {
uint8_t ucPlx_I2C_Line;
uint32_t usBoostPowerLimit;
uint8_t ucCKS_LDO_REFSEL;
+ uint8_t ucHotSpotOnly;
};
struct phm_tdp_table {
@@ -826,5 +828,9 @@ int hwmgr_handle_task(struct pp_hwmgr *hwmgr,
#define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU
+int smu7_init_function_pointers(struct pp_hwmgr *hwmgr);
+int smu8_init_function_pointers(struct pp_hwmgr *hwmgr);
+int vega12_hwmgr_init(struct pp_hwmgr *hwmgr);
+int vega20_hwmgr_init(struct pp_hwmgr *hwmgr);
#endif /* _HWMGR_H_ */
diff --git a/drivers/gpu/drm/amd/pm/inc/pp_thermal.h b/drivers/gpu/drm/amd/pm/inc/pp_thermal.h
index 3e30768f9e1c..f7c41185097e 100644
--- a/drivers/gpu/drm/amd/pm/inc/pp_thermal.h
+++ b/drivers/gpu/drm/amd/pm/inc/pp_thermal.h
@@ -25,13 +25,13 @@
#include "power_state.h"
-static const struct PP_TemperatureRange SMU7ThermalWithDelayPolicy[] =
+static const struct PP_TemperatureRange __maybe_unused SMU7ThermalWithDelayPolicy[] =
{
{-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
{ 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
};
-static const struct PP_TemperatureRange SMU7ThermalPolicy[] =
+static const struct PP_TemperatureRange __maybe_unused SMU7ThermalPolicy[] =
{
{-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
{ 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
diff --git a/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h
index df4677da736c..4c7e08ba5fa4 100644
--- a/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h
@@ -83,7 +83,8 @@
#define PPSMC_MSG_SetSoftMaxVcn 0x34
#define PPSMC_MSG_PowerGateMmHub 0x35
#define PPSMC_MSG_SetRccPfcPmeRestoreRegister 0x36
-#define PPSMC_Message_Count 0x37
+#define PPSMC_MSG_GpuChangeState 0x37
+#define PPSMC_Message_Count 0x42
typedef uint16_t PPSMC_Result;
typedef int PPSMC_Msg;
diff --git a/drivers/gpu/drm/amd/pm/inc/smu10.h b/drivers/gpu/drm/amd/pm/inc/smu10.h
index b96520528240..9e837a5014c5 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu10.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu10.h
@@ -136,14 +136,12 @@
#define FEATURE_CORE_CSTATES_MASK (1 << FEATURE_CORE_CSTATES_BIT)
/* Workload bits */
-#define WORKLOAD_DEFAULT_BIT 0
-#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1
-#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2
-#define WORKLOAD_PPLIB_VIDEO_BIT 3
-#define WORKLOAD_PPLIB_VR_BIT 4
-#define WORKLOAD_PPLIB_COMPUTE_BIT 5
-#define WORKLOAD_PPLIB_CUSTOM_BIT 6
-#define WORKLOAD_PPLIB_COUNT 7
+#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 0
+#define WORKLOAD_PPLIB_VIDEO_BIT 2
+#define WORKLOAD_PPLIB_VR_BIT 3
+#define WORKLOAD_PPLIB_COMPUTE_BIT 4
+#define WORKLOAD_PPLIB_CUSTOM_BIT 5
+#define WORKLOAD_PPLIB_COUNT 6
typedef struct {
/* MP1_EXT_SCRATCH0 */
diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h
index 1275246769d9..fa95147b5a63 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h
@@ -27,9 +27,9 @@
// *** IMPORTANT ***
// SMU TEAM: Always increment the interface version if
// any structure is changed in this file
-#define SMU11_DRIVER_IF_VERSION 0x39
+#define SMU11_DRIVER_IF_VERSION 0x3B
-#define PPTABLE_Sienna_Cichlid_SMU_VERSION 6
+#define PPTABLE_Sienna_Cichlid_SMU_VERSION 7
#define NUM_GFXCLK_DPM_LEVELS 16
#define NUM_SMNCLK_DPM_LEVELS 2
@@ -226,6 +226,8 @@ typedef enum {
#define FW_DSTATE_MEM_PLL_PWRDN_BIT 9
#define FW_DSTATE_OPTIMIZE_MALL_REFRESH_BIT 10
#define FW_DSTATE_MEM_PSI_BIT 11
+#define FW_DSTATE_HSR_NON_STROBE_BIT 12
+#define FW_DSTATE_MP0_ENTER_WFI_BIT 13
#define FW_DSTATE_SOC_ULV_MASK (1 << FW_DSTATE_SOC_ULV_BIT )
#define FW_DSTATE_G6_HSR_MASK (1 << FW_DSTATE_G6_HSR_BIT )
@@ -239,6 +241,8 @@ typedef enum {
#define FW_DSTATE_MEM_PLL_PWRDN_MASK (1 << FW_DSTATE_MEM_PLL_PWRDN_BIT )
#define FW_DSTATE_OPTIMIZE_MALL_REFRESH_MASK (1 << FW_DSTATE_OPTIMIZE_MALL_REFRESH_BIT )
#define FW_DSTATE_MEM_PSI_MASK (1 << FW_DSTATE_MEM_PSI_BIT )
+#define FW_DSTATE_HSR_NON_STROBE_MASK (1 << FW_DSTATE_HSR_NON_STROBE_BIT )
+#define FW_DSTATE_MP0_ENTER_WFI_MASK (1 << FW_DSTATE_MP0_ENTER_WFI_BIT )
// GFX GPO Feature Contains PACE and DEM sub features
#define GFX_GPO_PACE_BIT 0
@@ -433,6 +437,7 @@ typedef enum {
PIECEWISE_LINEAR_FUSED_MODEL = 0,
PIECEWISE_LINEAR_PP_MODEL,
QUADRATIC_PP_MODEL,
+ PERPART_PIECEWISE_LINEAR_PP_MODEL,
} DfllDroopModelSelect_e;
typedef struct {
@@ -608,7 +613,9 @@ typedef struct {
uint16_t SmnclkDpmFreq [NUM_SMNCLK_DPM_LEVELS]; // in MHz
uint16_t SmnclkDpmVoltage [NUM_SMNCLK_DPM_LEVELS]; // mV(Q2)
- uint32_t PaddingAPCC[4];
+ uint32_t PaddingAPCC;
+ uint16_t PerPartDroopVsetGfxDfll[NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS]; //In mV(Q2)
+ uint16_t PaddingPerPartDroop;
// SECTION: Throttler settings
uint32_t ThrottlerControlMask; // See Throtter masks defines
@@ -663,7 +670,9 @@ typedef struct {
uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; // In MHz
uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz
uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz
- uint32_t Paddingclks[16];
+ uint32_t Paddingclks;
+
+ DroopInt_t PerPartDroopModelGfxDfll[NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS]; //GHz ->Vstore in IEEE float format
uint32_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz
@@ -804,7 +813,11 @@ typedef struct {
uint32_t VcBtcVminA; // A_VMIN
uint32_t VcBtcVminB; // B_VMIN
- uint32_t SkuReserved[9];
+ //GPIO Board feature
+ uint16_t LedGpio; //GeneriA GPIO flag used to control the radeon LEDs
+ uint16_t GfxPowerStagesGpio; //Genlk_vsync GPIO flag used to control gfx power stages
+
+ uint32_t SkuReserved[8];
// MAJOR SECTION: BOARD PARAMETERS
@@ -1026,6 +1039,8 @@ typedef struct {
uint16_t VcnActivityPercentage ; //place holder, David N. to provide full sequence
uint8_t PcieRate ;
uint8_t PcieWidth ;
+ uint16_t AverageGfxclkFrequencyTarget;
+ uint16_t Padding16_2;
} SmuMetrics_t;
@@ -1211,7 +1226,8 @@ typedef struct {
#define WORKLOAD_PPLIB_VR_BIT 4
#define WORKLOAD_PPLIB_COMPUTE_BIT 5
#define WORKLOAD_PPLIB_CUSTOM_BIT 6
-#define WORKLOAD_PPLIB_COUNT 7
+#define WORKLOAD_PPLIB_W3D_BIT 7
+#define WORKLOAD_PPLIB_COUNT 8
// These defines are used with the following messages:
diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_vangogh.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_vangogh.h
new file mode 100644
index 000000000000..1c19eae93ff1
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_vangogh.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __SMU11_DRIVER_IF_VANGOGH_H__
+#define __SMU11_DRIVER_IF_VANGOGH_H__
+
+// *** IMPORTANT ***
+// SMU TEAM: Always increment the interface version if
+// any structure is changed in this file
+#define SMU13_DRIVER_IF_VERSION 2
+
+typedef struct {
+ int32_t value;
+ uint32_t numFractionalBits;
+} FloatInIntFormat_t;
+
+typedef enum {
+ DSPCLK_DCFCLK = 0,
+ DSPCLK_DISPCLK,
+ DSPCLK_PIXCLK,
+ DSPCLK_PHYCLK,
+ DSPCLK_COUNT,
+} DSPCLK_e;
+
+typedef struct {
+ uint16_t Freq; // in MHz
+ uint16_t Vid; // min voltage in SVI2 VID
+} DisplayClockTable_t;
+
+typedef struct {
+ uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MinMclk;
+ uint16_t MaxMclk;
+
+ uint8_t WmSetting;
+ uint8_t WmType; // Used for normal pstate change or memory retraining
+ uint8_t Padding[2];
+} WatermarkRowGeneric_t;
+
+#define NUM_WM_RANGES 4
+#define WM_PSTATE_CHG 0
+#define WM_RETRAINING 1
+
+typedef enum {
+ WM_SOCCLK = 0,
+ WM_DCFCLK,
+ WM_COUNT,
+} WM_CLOCK_e;
+
+typedef struct {
+ // Watermarks
+ WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+
+ uint32_t MmHubPadding[7]; // SMU internal use
+} Watermarks_t;
+
+typedef enum {
+ CUSTOM_DPM_SETTING_GFXCLK,
+ CUSTOM_DPM_SETTING_CCLK,
+ CUSTOM_DPM_SETTING_FCLK_CCX,
+ CUSTOM_DPM_SETTING_FCLK_GFX,
+ CUSTOM_DPM_SETTING_FCLK_STALLS,
+ CUSTOM_DPM_SETTING_LCLK,
+ CUSTOM_DPM_SETTING_COUNT,
+} CUSTOM_DPM_SETTING_e;
+
+typedef struct {
+ uint8_t ActiveHystLimit;
+ uint8_t IdleHystLimit;
+ uint8_t FPS;
+ uint8_t MinActiveFreqType;
+ FloatInIntFormat_t MinActiveFreq;
+ FloatInIntFormat_t PD_Data_limit;
+ FloatInIntFormat_t PD_Data_time_constant;
+ FloatInIntFormat_t PD_Data_error_coeff;
+ FloatInIntFormat_t PD_Data_error_rate_coeff;
+} DpmActivityMonitorCoeffExt_t;
+
+typedef struct {
+ DpmActivityMonitorCoeffExt_t DpmActivityMonitorCoeff[CUSTOM_DPM_SETTING_COUNT];
+} CustomDpmSettings_t;
+
+#define NUM_DCFCLK_DPM_LEVELS 7
+#define NUM_DISPCLK_DPM_LEVELS 7
+#define NUM_DPPCLK_DPM_LEVELS 7
+#define NUM_SOCCLK_DPM_LEVELS 7
+#define NUM_ISPICLK_DPM_LEVELS 7
+#define NUM_ISPXCLK_DPM_LEVELS 7
+#define NUM_VCN_DPM_LEVELS 5
+#define NUM_FCLK_DPM_LEVELS 4
+#define NUM_SOC_VOLTAGE_LEVELS 8
+
+typedef struct {
+ uint32_t fclk;
+ uint32_t memclk;
+ uint32_t voltage;
+} df_pstate_t;
+
+typedef struct {
+ uint32_t vclk;
+ uint32_t dclk;
+} vcn_clk_t;
+
+//Freq in MHz
+//Voltage in milli volts with 2 fractional bits
+
+typedef struct {
+ uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS];
+ uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS];
+ uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS];
+ uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS];
+ uint32_t IspiClocks[NUM_ISPICLK_DPM_LEVELS];
+ uint32_t IspxClocks[NUM_ISPXCLK_DPM_LEVELS];
+ vcn_clk_t VcnClocks[NUM_VCN_DPM_LEVELS];
+
+ uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS];
+
+ df_pstate_t DfPstateTable[NUM_FCLK_DPM_LEVELS];
+
+ uint32_t MinGfxClk;
+ uint32_t MaxGfxClk;
+
+ uint8_t NumDfPstatesEnabled;
+ uint8_t NumDpmLevelsEnabled;
+ uint8_t NumDcfclkLevelsEnabled;
+ uint8_t NumDispClkLevelsEnabled; //applies to both dispclk and dppclk
+ uint8_t NumSocClkLevelsEnabled;
+
+ uint8_t IspClkLevelsEnabled; //applies to both ispiclk and ispxclk
+ uint8_t VcnClkLevelsEnabled; //applies to both vclk/dclk
+ uint8_t spare[2];
+} DpmClocks_t;
+
+
+// Throttler Status Bitmask
+#define THROTTLER_STATUS_BIT_SPL 0
+#define THROTTLER_STATUS_BIT_FPPT 1
+#define THROTTLER_STATUS_BIT_SPPT 2
+#define THROTTLER_STATUS_BIT_SPPT_APU 3
+#define THROTTLER_STATUS_BIT_THM_CORE 4
+#define THROTTLER_STATUS_BIT_THM_GFX 5
+#define THROTTLER_STATUS_BIT_THM_SOC 6
+#define THROTTLER_STATUS_BIT_TDC_VDD 7
+#define THROTTLER_STATUS_BIT_TDC_SOC 8
+#define THROTTLER_STATUS_BIT_TDC_GFX 9
+#define THROTTLER_STATUS_BIT_TDC_CVIP 10
+
+typedef struct {
+ uint16_t GfxclkFrequency; //[MHz]
+ uint16_t SocclkFrequency; //[MHz]
+ uint16_t VclkFrequency; //[MHz]
+ uint16_t DclkFrequency; //[MHz]
+ uint16_t MemclkFrequency; //[MHz]
+ uint16_t spare;
+
+ uint16_t GfxActivity; //[centi]
+ uint16_t UvdActivity; //[centi]
+
+ uint16_t Voltage[3]; //[mV] indices: VDDCR_VDD, VDDCR_SOC, VDDCR_GFX
+ uint16_t Current[3]; //[mA] indices: VDDCR_VDD, VDDCR_SOC, VDDCR_GFX
+ uint16_t Power[3]; //[mW] indices: VDDCR_VDD, VDDCR_SOC, VDDCR_GFX
+ uint16_t CurrentSocketPower; //[mW]
+
+ //3rd party tools in Windows need info in the case of APUs
+ uint16_t CoreFrequency[8]; //[MHz]
+ uint16_t CorePower[8]; //[mW]
+ uint16_t CoreTemperature[8]; //[centi-Celsius]
+ uint16_t L3Frequency[2]; //[MHz]
+ uint16_t L3Temperature[2]; //[centi-Celsius]
+
+ uint16_t GfxTemperature; //[centi-Celsius]
+ uint16_t SocTemperature; //[centi-Celsius]
+ uint16_t EdgeTemperature;
+ uint16_t ThrottlerStatus;
+} SmuMetrics_t;
+
+
+// Workload bits
+#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 0
+#define WORKLOAD_PPLIB_VIDEO_BIT 2
+#define WORKLOAD_PPLIB_VR_BIT 3
+#define WORKLOAD_PPLIB_COMPUTE_BIT 4
+#define WORKLOAD_PPLIB_CUSTOM_BIT 5
+#define WORKLOAD_PPLIB_COUNT 6
+
+#define TABLE_BIOS_IF 0 // Called by BIOS
+#define TABLE_WATERMARKS 1 // Called by DAL through VBIOS
+#define TABLE_CUSTOM_DPM 2 // Called by Driver
+#define TABLE_SPARE1 3
+#define TABLE_DPMCLOCKS 4 // Called by Driver
+#define TABLE_SPARE2 5 // Called by Tools
+#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log
+#define TABLE_SMU_METRICS 7 // Called by Driver
+#define TABLE_COUNT 8
+
+//ISP tile definitions
+typedef enum {
+ TILE_ISPX = 0, // ISPX
+ TILE_ISPM, // ISPM
+ TILE_ISPC, // ISPCORE
+ TILE_ISPPRE, // ISPPRE
+ TILE_ISPPOST, // ISPPOST
+ TILE_MAX
+} TILE_NUM_e;
+
+// Tile Selection (Based on arguments)
+#define TILE_SEL_ISPX (1<<(TILE_ISPX))
+#define TILE_SEL_ISPM (1<<(TILE_ISPM))
+#define TILE_SEL_ISPC (1<<(TILE_ISPC))
+#define TILE_SEL_ISPPRE (1<<(TILE_ISPPRE))
+#define TILE_SEL_ISPPOST (1<<(TILE_ISPPOST))
+
+// Mask for ISP tiles in PGFSM PWR Status Registers
+//Bit[1:0] maps to ISPX, (ISPX)
+//Bit[3:2] maps to ISPM, (ISPM)
+//Bit[5:4] maps to ISPCORE, (ISPCORE)
+//Bit[7:6] maps to ISPPRE, (ISPPRE)
+//Bit[9:8] maps to POST, (ISPPOST
+#define TILE_ISPX_MASK ((1<<0) | (1<<1))
+#define TILE_ISPM_MASK ((1<<2) | (1<<3))
+#define TILE_ISPC_MASK ((1<<4) | (1<<5))
+#define TILE_ISPPRE_MASK ((1<<6) | (1<<7))
+#define TILE_ISPPOST_MASK ((1<<8) | (1<<9))
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu74_discrete.h b/drivers/gpu/drm/amd/pm/inc/smu74_discrete.h
index 899d6d8108c2..350889e408d2 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu74_discrete.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu74_discrete.h
@@ -271,7 +271,8 @@ struct SMU74_Discrete_DpmTable {
uint8_t VRHotLevel;
uint8_t LdoRefSel;
- uint8_t Reserved1[2];
+ uint8_t SharedRails;
+ uint8_t Reserved1;
uint16_t FanStartTemperature;
uint16_t FanStopTemperature;
uint16_t MaxVoltage;
diff --git a/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h
index 6e19f4c7cf8f..a0a38b8a4b1b 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h
@@ -394,6 +394,7 @@ typedef uint16_t PPSMC_Result;
#define PPSMC_MSG_SetGpuPllDfsForSclk ((uint16_t) 0x300)
#define PPSMC_MSG_Didt_Block_Function ((uint16_t) 0x301)
+#define PPSMC_MSG_EnableZeroRpm ((uint16_t) 0x302)
#define PPSMC_MSG_SetVBITimeout ((uint16_t) 0x306)
@@ -402,6 +403,11 @@ typedef uint16_t PPSMC_Result;
#define PPSMC_MSG_EnableDpmDidt ((uint16_t) 0x309)
#define PPSMC_MSG_DisableDpmDidt ((uint16_t) 0x30A)
+#define PPSMC_MSG_EnableDpmMcBlackout ((uint16_t) 0x30B)
+#define PPSMC_MSG_DisableDpmMcBlackout ((uint16_t) 0x30C)
+
+#define PPSMC_MSG_EnableEDCController ((uint16_t) 0x316)
+#define PPSMC_MSG_DisableEDCController ((uint16_t) 0x317)
#define PPSMC_MSG_SecureSRBMWrite ((uint16_t) 0x600)
#define PPSMC_MSG_SecureSRBMRead ((uint16_t) 0x601)
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h
index cbf4a58b77d9..720d15612fe1 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_types.h
@@ -35,6 +35,7 @@
__SMU_DUMMY_MAP(EnableSmuFeaturesHigh), \
__SMU_DUMMY_MAP(DisableSmuFeaturesLow), \
__SMU_DUMMY_MAP(DisableSmuFeaturesHigh), \
+ __SMU_DUMMY_MAP(GetEnabledSmuFeatures), \
__SMU_DUMMY_MAP(GetEnabledSmuFeaturesLow), \
__SMU_DUMMY_MAP(GetEnabledSmuFeaturesHigh), \
__SMU_DUMMY_MAP(SetWorkloadMask), \
@@ -122,7 +123,7 @@
__SMU_DUMMY_MAP(GetVoltageByDpm), \
__SMU_DUMMY_MAP(GetVoltageByDpmOverdrive), \
__SMU_DUMMY_MAP(PowerUpVcn0), \
- __SMU_DUMMY_MAP(PowerDownVcn0), \
+ __SMU_DUMMY_MAP(PowerDownVcn0), \
__SMU_DUMMY_MAP(PowerUpVcn1), \
__SMU_DUMMY_MAP(PowerDownVcn1), \
__SMU_DUMMY_MAP(PowerUpGfx), \
@@ -165,18 +166,51 @@
__SMU_DUMMY_MAP(GpuChangeState), \
__SMU_DUMMY_MAP(SetPowerLimitPercentage), \
__SMU_DUMMY_MAP(ForceGfxContentSave), \
- __SMU_DUMMY_MAP(EnableTmdp48MHzRefclkPwrDown), \
+ __SMU_DUMMY_MAP(EnableTmdp48MHzRefclkPwrDown),\
__SMU_DUMMY_MAP(PowerGateAtHub), \
__SMU_DUMMY_MAP(SetSoftMinJpeg), \
__SMU_DUMMY_MAP(SetHardMinFclkByFreq), \
- __SMU_DUMMY_MAP(DFCstateControl), \
- __SMU_DUMMY_MAP(GmiPwrDnControl), \
- __SMU_DUMMY_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE), \
+ __SMU_DUMMY_MAP(DFCstateControl), \
+ __SMU_DUMMY_MAP(GmiPwrDnControl), \
+ __SMU_DUMMY_MAP(DAL_DISABLE_DUMMY_PSTATE_CHANGE),\
__SMU_DUMMY_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE), \
__SMU_DUMMY_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_HIGH), \
__SMU_DUMMY_MAP(SET_DRIVER_DUMMY_TABLE_DRAM_ADDR_LOW), \
__SMU_DUMMY_MAP(GET_UMC_FW_WA), \
__SMU_DUMMY_MAP(Mode1Reset), \
+ __SMU_DUMMY_MAP(RlcPowerNotify), \
+ __SMU_DUMMY_MAP(SetHardMinIspiclkByFreq), \
+ __SMU_DUMMY_MAP(SetHardMinIspxclkByFreq), \
+ __SMU_DUMMY_MAP(SetSoftMinSocclkByFreq), \
+ __SMU_DUMMY_MAP(PowerUpCvip), \
+ __SMU_DUMMY_MAP(PowerDownCvip), \
+ __SMU_DUMMY_MAP(EnableGfxOff), \
+ __SMU_DUMMY_MAP(SetSoftMinGfxclk), \
+ __SMU_DUMMY_MAP(SetSoftMinFclk), \
+ __SMU_DUMMY_MAP(GetThermalLimit), \
+ __SMU_DUMMY_MAP(GetCurrentTemperature), \
+ __SMU_DUMMY_MAP(GetCurrentPower), \
+ __SMU_DUMMY_MAP(GetCurrentVoltage), \
+ __SMU_DUMMY_MAP(GetCurrentCurrent), \
+ __SMU_DUMMY_MAP(GetAverageCpuActivity), \
+ __SMU_DUMMY_MAP(GetAverageGfxActivity), \
+ __SMU_DUMMY_MAP(GetAveragePower), \
+ __SMU_DUMMY_MAP(GetAverageTemperature), \
+ __SMU_DUMMY_MAP(SetAveragePowerTimeConstant), \
+ __SMU_DUMMY_MAP(SetAverageActivityTimeConstant), \
+ __SMU_DUMMY_MAP(SetAverageTemperatureTimeConstant), \
+ __SMU_DUMMY_MAP(SetMitigationEndHysteresis), \
+ __SMU_DUMMY_MAP(GetCurrentFreq), \
+ __SMU_DUMMY_MAP(SetReducedPptLimit), \
+ __SMU_DUMMY_MAP(SetReducedThermalLimit), \
+ __SMU_DUMMY_MAP(DramLogSetDramAddr), \
+ __SMU_DUMMY_MAP(StartDramLogging), \
+ __SMU_DUMMY_MAP(StopDramLogging), \
+ __SMU_DUMMY_MAP(SetSoftMinCclk), \
+ __SMU_DUMMY_MAP(SetSoftMaxCclk), \
+ __SMU_DUMMY_MAP(SetGpoFeaturePMask), \
+ __SMU_DUMMY_MAP(DisallowGpo), \
+ __SMU_DUMMY_MAP(Enable2ndUSB20Port), \
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
@@ -266,7 +300,37 @@ enum smu_clk_type {
__SMU_DUMMY_MAP(ATHUB_PG), \
__SMU_DUMMY_MAP(APCC_DFLL), \
__SMU_DUMMY_MAP(DPM_GFX_GPO), \
- __SMU_DUMMY_MAP(WAFL_CG),
+ __SMU_DUMMY_MAP(WAFL_CG), \
+ __SMU_DUMMY_MAP(CCLK_DPM), \
+ __SMU_DUMMY_MAP(FAN_CONTROLLER), \
+ __SMU_DUMMY_MAP(VCN_DPM), \
+ __SMU_DUMMY_MAP(LCLK_DPM), \
+ __SMU_DUMMY_MAP(SHUBCLK_DPM), \
+ __SMU_DUMMY_MAP(DCFCLK_DPM), \
+ __SMU_DUMMY_MAP(DS_DCFCLK), \
+ __SMU_DUMMY_MAP(S0I2), \
+ __SMU_DUMMY_MAP(SMU_LOW_POWER), \
+ __SMU_DUMMY_MAP(GFX_DEM), \
+ __SMU_DUMMY_MAP(PSI), \
+ __SMU_DUMMY_MAP(PROCHOT), \
+ __SMU_DUMMY_MAP(CPUOFF), \
+ __SMU_DUMMY_MAP(STAPM), \
+ __SMU_DUMMY_MAP(S0I3), \
+ __SMU_DUMMY_MAP(DF_CSTATES), \
+ __SMU_DUMMY_MAP(PERF_LIMIT), \
+ __SMU_DUMMY_MAP(CORE_DLDO), \
+ __SMU_DUMMY_MAP(RSMU_LOW_POWER), \
+ __SMU_DUMMY_MAP(SMN_LOW_POWER), \
+ __SMU_DUMMY_MAP(THM_LOW_POWER), \
+ __SMU_DUMMY_MAP(SMUIO_LOW_POWER), \
+ __SMU_DUMMY_MAP(MP1_LOW_POWER), \
+ __SMU_DUMMY_MAP(DS_VCN), \
+ __SMU_DUMMY_MAP(CPPC), \
+ __SMU_DUMMY_MAP(OS_CSTATES), \
+ __SMU_DUMMY_MAP(ISP_DPM), \
+ __SMU_DUMMY_MAP(A55_DPM), \
+ __SMU_DUMMY_MAP(CVIP_DSP_DPM), \
+ __SMU_DUMMY_MAP(MSMU_LOW_POWER),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(feature) SMU_FEATURE_##feature##_BIT
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
index 2d1c3babaa3a..13de692a4213 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
@@ -30,8 +30,10 @@
#define SMU11_DRIVER_IF_VERSION_NV10 0x36
#define SMU11_DRIVER_IF_VERSION_NV12 0x36
#define SMU11_DRIVER_IF_VERSION_NV14 0x36
-#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x39
-#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x5
+#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x3D
+#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0xC
+#define SMU11_DRIVER_IF_VERSION_VANGOGH 0x02
+#define SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish 0xF
/* MP Apertures */
#define MP0_Public 0x03800000
@@ -56,7 +58,8 @@
#define CTF_OFFSET_HOTSPOT 5
#define CTF_OFFSET_MEM 5
-static const struct smu_temperature_range smu11_thermal_policy[] =
+static const
+struct smu_temperature_range __maybe_unused smu11_thermal_policy[] =
{
{-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
{ 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
@@ -274,6 +277,8 @@ int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu);
void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics);
+void smu_v11_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics);
+
int smu_v11_0_gfx_ulv_control(struct smu_context *smu,
bool enablement);
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h
index 35dd6072cc45..d2e10a724560 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h
@@ -134,6 +134,10 @@
#define PPSMC_MSG_SetGpoFeaturePMask 0x45
#define PPSMC_MSG_SetSMBUSInterrupt 0x46
-#define PPSMC_Message_Count 0x47
+#define PPSMC_MSG_DisallowGpo 0x56
+
+#define PPSMC_MSG_Enable2ndUSB20Port 0x57
+
+#define PPSMC_Message_Count 0x58
#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_5_pmfw.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_5_pmfw.h
new file mode 100644
index 000000000000..22edd88b8117
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_5_pmfw.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __SMU_V11_5_0_PMFW_H__
+#define __SMU_V11_5_0_PMFW_H__
+
+#include "smu11_driver_if_vangogh.h"
+
+#pragma pack(push, 1)
+
+#define ENABLE_DEBUG_FEATURES
+
+// Feature Control Defines
+#define FEATURE_CCLK_DPM_BIT 0
+#define FEATURE_FAN_CONTROLLER_BIT 1
+#define FEATURE_DATA_CALCULATION_BIT 2
+#define FEATURE_PPT_BIT 3
+#define FEATURE_TDC_BIT 4
+#define FEATURE_THERMAL_BIT 5
+#define FEATURE_FIT_BIT 6
+#define FEATURE_EDC_BIT 7
+#define FEATURE_PLL_POWER_DOWN_BIT 8
+#define FEATURE_ULV_BIT 9
+#define FEATURE_VDDOFF_BIT 10
+#define FEATURE_VCN_DPM_BIT 11
+#define FEATURE_CSTATE_BOOST_BIT 12
+#define FEATURE_FCLK_DPM_BIT 13
+#define FEATURE_SOCCLK_DPM_BIT 14
+#define FEATURE_MP0CLK_DPM_BIT 15
+#define FEATURE_LCLK_DPM_BIT 16
+#define FEATURE_SHUBCLK_DPM_BIT 17
+#define FEATURE_DCFCLK_DPM_BIT 18
+#define FEATURE_GFX_DPM_BIT 19
+#define FEATURE_DS_GFXCLK_BIT 20
+#define FEATURE_DS_SOCCLK_BIT 21
+#define FEATURE_DS_LCLK_BIT 22
+#define FEATURE_DS_DCFCLK_BIT 23
+#define FEATURE_DS_SHUBCLK_BIT 24
+#define FEATURE_GFX_TEMP_VMIN_BIT 25
+#define FEATURE_S0I2_BIT 26
+#define FEATURE_WHISPER_MODE_BIT 27
+#define FEATURE_DS_FCLK_BIT 28
+#define FEATURE_DS_SMNCLK_BIT 29
+#define FEATURE_DS_MP1CLK_BIT 30
+#define FEATURE_DS_MP0CLK_BIT 31
+#define FEATURE_SMU_LOW_POWER_BIT 32
+#define FEATURE_FUSE_PG_BIT 33
+#define FEATURE_GFX_DEM_BIT 34
+#define FEATURE_PSI_BIT 35
+#define FEATURE_PROCHOT_BIT 36
+#define FEATURE_CPUOFF_BIT 37
+#define FEATURE_STAPM_BIT 38
+#define FEATURE_S0I3_BIT 39
+#define FEATURE_DF_CSTATES_BIT 40
+#define FEATURE_PERF_LIMIT_BIT 41
+#define FEATURE_CORE_DLDO_BIT 42
+#define FEATURE_RSMU_LOW_POWER_BIT 43
+#define FEATURE_SMN_LOW_POWER_BIT 44
+#define FEATURE_THM_LOW_POWER_BIT 45
+#define FEATURE_SMUIO_LOW_POWER_BIT 46
+#define FEATURE_MP1_LOW_POWER_BIT 47
+#define FEATURE_DS_VCN_BIT 48
+#define FEATURE_CPPC_BIT 49
+#define FEATURE_OS_CSTATES_BIT 50
+#define FEATURE_ISP_DPM_BIT 51
+#define FEATURE_A55_DPM_BIT 52
+#define FEATURE_CVIP_DSP_DPM_BIT 53
+#define FEATURE_MSMU_LOW_POWER_BIT 54
+#define FEATURE_SOC_VOLTAGE_MON_BIT 55
+#define FEATURE_ATHUB_PG_BIT 56
+#define FEATURE_ECO_DEEPCSTATE_BIT 57
+#define FEATURE_CC6_BIT 58
+#define FEATURE_GFX_EDC_BIT 59
+#define NUM_FEATURES 60
+
+typedef struct {
+ // MP1_EXT_SCRATCH0
+ uint32_t DpmHandlerID : 8;
+ uint32_t ActivityMonitorID : 8;
+ uint32_t DpmTimerID : 8;
+ uint32_t DpmHubID : 4;
+ uint32_t DpmHubTask : 4;
+ // MP1_EXT_SCRATCH1
+ uint32_t GfxStatus : 2;
+ uint32_t GfxoffStatus : 8;
+ uint32_t CpuOff : 1;
+ uint32_t VddOff : 1;
+ uint32_t InUlv : 1;
+ uint32_t InS0i2 : 2;
+ uint32_t InWhisperMode : 1;
+ uint32_t spare1 : 16;
+ // MP1_EXT_SCRATCH2
+ uint32_t P2JobHandler : 32;
+ // MP1_EXT_SCRATCH3: used for postcodes
+
+ // MP1_EXT_SCRATCH4:6 are used by Kernel
+ // MP1_EXT_SCRATCH7: used by HW
+} FwStatus_t;
+
+
+#pragma pack(pop)
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_5_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_5_ppsmc.h
new file mode 100644
index 000000000000..55d7892e4e0e
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_5_ppsmc.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef SMU_11_5_0_PPSMC_H
+#define SMU_11_5_0_PPSMC_H
+
+// SMU Response Codes:
+#define PPSMC_Result_OK 0x1
+#define PPSMC_Result_Failed 0xFF
+#define PPSMC_Result_UnknownCmd 0xFE
+#define PPSMC_Result_CmdRejectedPrereq 0xFD
+#define PPSMC_Result_CmdRejectedBusy 0xFC
+
+// Message Definitions:
+#define PPSMC_MSG_TestMessage 0x1
+#define PPSMC_MSG_GetSmuVersion 0x2
+#define PPSMC_MSG_GetDriverIfVersion 0x3
+#define PPSMC_MSG_EnableGfxOff 0x4
+#define PPSMC_MSG_DisableGfxOff 0x5
+#define PPSMC_MSG_PowerDownIspByTile 0x6 // ISP is power gated by default
+#define PPSMC_MSG_PowerUpIspByTile 0x7
+#define PPSMC_MSG_PowerDownVcn 0x8 // VCN is power gated by default
+#define PPSMC_MSG_PowerUpVcn 0x9
+#define PPSMC_MSG_RlcPowerNotify 0xA
+#define PPSMC_MSG_SetHardMinVcn 0xB // For wireless display
+#define PPSMC_MSG_SetSoftMinGfxclk 0xC //Sets SoftMin for GFXCLK. Arg is in MHz
+#define PPSMC_MSG_ActiveProcessNotify 0xD
+#define PPSMC_MSG_SetHardMinIspiclkByFreq 0xE
+#define PPSMC_MSG_SetHardMinIspxclkByFreq 0xF
+#define PPSMC_MSG_SetDriverDramAddrHigh 0x10
+#define PPSMC_MSG_SetDriverDramAddrLow 0x11
+#define PPSMC_MSG_TransferTableSmu2Dram 0x12
+#define PPSMC_MSG_TransferTableDram2Smu 0x13
+#define PPSMC_MSG_GfxDeviceDriverReset 0x14 //mode 2 reset during TDR
+#define PPSMC_MSG_GetEnabledSmuFeatures 0x15
+#define PPSMC_MSG_spare1 0x16
+#define PPSMC_MSG_SetHardMinSocclkByFreq 0x17
+#define PPSMC_MSG_SetSoftMinFclk 0x18 //Used to be PPSMC_MSG_SetMinVideoFclkFreq
+#define PPSMC_MSG_SetSoftMinVcn 0x19
+#define PPSMC_MSG_EnablePostCode 0x1A
+#define PPSMC_MSG_GetGfxclkFrequency 0x1B
+#define PPSMC_MSG_GetFclkFrequency 0x1C
+#define PPSMC_MSG_AllowGfxOff 0x1D
+#define PPSMC_MSG_DisallowGfxOff 0x1E
+#define PPSMC_MSG_SetSoftMaxGfxClk 0x1F
+#define PPSMC_MSG_SetHardMinGfxClk 0x20
+#define PPSMC_MSG_SetSoftMaxSocclkByFreq 0x21
+#define PPSMC_MSG_SetSoftMaxFclkByFreq 0x22
+#define PPSMC_MSG_SetSoftMaxVcn 0x23
+#define PPSMC_MSG_spare2 0x24
+#define PPSMC_MSG_SetPowerLimitPercentage 0x25
+#define PPSMC_MSG_PowerDownJpeg 0x26
+#define PPSMC_MSG_PowerUpJpeg 0x27
+#define PPSMC_MSG_SetHardMinFclkByFreq 0x28
+#define PPSMC_MSG_SetSoftMinSocclkByFreq 0x29
+#define PPSMC_MSG_PowerUpCvip 0x2A
+#define PPSMC_MSG_PowerDownCvip 0x2B
+#define PPSMC_MSG_GetPptLimit 0x2C
+#define PPSMC_MSG_GetThermalLimit 0x2D
+#define PPSMC_MSG_GetCurrentTemperature 0x2E
+#define PPSMC_MSG_GetCurrentPower 0x2F
+#define PPSMC_MSG_GetCurrentVoltage 0x30
+#define PPSMC_MSG_GetCurrentCurrent 0x31
+#define PPSMC_MSG_GetAverageCpuActivity 0x32
+#define PPSMC_MSG_GetAverageGfxActivity 0x33
+#define PPSMC_MSG_GetAveragePower 0x34
+#define PPSMC_MSG_GetAverageTemperature 0x35
+#define PPSMC_MSG_SetAveragePowerTimeConstant 0x36
+#define PPSMC_MSG_SetAverageActivityTimeConstant 0x37
+#define PPSMC_MSG_SetAverageTemperatureTimeConstant 0x38
+#define PPSMC_MSG_SetMitigationEndHysteresis 0x39
+#define PPSMC_MSG_GetCurrentFreq 0x3A
+#define PPSMC_MSG_SetReducedPptLimit 0x3B
+#define PPSMC_MSG_SetReducedThermalLimit 0x3C
+#define PPSMC_MSG_DramLogSetDramAddr 0x3D
+#define PPSMC_MSG_StartDramLogging 0x3E
+#define PPSMC_MSG_StopDramLogging 0x3F
+#define PPSMC_MSG_SetSoftMinCclk 0x40
+#define PPSMC_MSG_SetSoftMaxCclk 0x41
+#define PPSMC_MSG_SetDfPstateActiveLevel 0x42
+#define PPSMC_MSG_SetDfPstateSoftMinLevel 0x43
+#define PPSMC_MSG_SetCclkPolicy 0x44
+#define PPSMC_MSG_DramLogSetDramAddrHigh 0x45
+#define PPSMC_MSG_DramLogSetDramBufferSize 0x46
+#define PPSMC_MSG_RequestActiveWgp 0x47
+#define PPSMC_MSG_QueryActiveWgp 0x48
+#define PPSMC_Message_Count 0x49
+
+//Argument for PPSMC_MSG_GfxDeviceDriverReset
+enum {
+ MODE1_RESET = 1,
+ MODE2_RESET = 2
+};
+
+#endif
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/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 35629140fc7a..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),
@@ -1558,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;
@@ -1612,19 +1740,6 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
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;
@@ -1683,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,
@@ -1704,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);
@@ -1724,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;
@@ -1803,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)
@@ -1829,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)
@@ -2087,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 =
@@ -2115,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;
@@ -2148,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;
@@ -2253,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)
@@ -2552,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;
@@ -2601,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 */
@@ -2613,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;
}
@@ -2890,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;
@@ -2921,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);
@@ -2928,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",
@@ -2981,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;
@@ -3018,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)
@@ -3765,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),
@@ -3921,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),
@@ -3974,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);
@@ -3987,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;
@@ -4041,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!",
@@ -4056,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 =
@@ -4079,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);
@@ -4155,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.
@@ -4215,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 ||
@@ -4350,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)
{
@@ -4366,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)
{
@@ -4380,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)
{
@@ -4771,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,
@@ -5188,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 329bf4d44bbc..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)
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,
+ &dividers);
+ 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, &dividers);
+ 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/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;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index b1e5ec01527b..8b867a6d52b5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -33,6 +33,7 @@
#include "navi10_ppt.h"
#include "sienna_cichlid_ppt.h"
#include "renoir_ppt.h"
+#include "vangogh_ppt.h"
#include "amd_pcie.h"
/*
@@ -396,11 +397,17 @@ static int smu_set_funcs(struct amdgpu_device *adev)
break;
case CHIP_SIENNA_CICHLID:
case CHIP_NAVY_FLOUNDER:
+ case CHIP_DIMGREY_CAVEFISH:
sienna_cichlid_set_ppt_funcs(smu);
break;
case CHIP_RENOIR:
renoir_set_ppt_funcs(smu);
break;
+ case CHIP_VANGOGH:
+ vangogh_set_ppt_funcs(smu);
+ /* enable the OD by default to allow the fine grain tuning function */
+ smu->od_enabled = true;
+ break;
default:
return -EINVAL;
}
@@ -469,6 +476,11 @@ static int smu_late_init(void *handle)
struct smu_context *smu = &adev->smu;
int ret = 0;
+ smu_set_fine_grain_gfx_freq_parameters(smu);
+
+ if (adev->asic_type == CHIP_VANGOGH)
+ return 0;
+
if (!smu->pm_enabled)
return 0;
@@ -835,12 +847,10 @@ static int smu_sw_init(void *handle)
smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
- if (!amdgpu_sriov_vf(adev)) {
- ret = smu_init_microcode(smu);
- if (ret) {
- dev_err(adev->dev, "Failed to load smu firmware!\n");
- return ret;
- }
+ ret = smu_init_microcode(smu);
+ if (ret) {
+ dev_err(adev->dev, "Failed to load smu firmware!\n");
+ return ret;
}
ret = smu_smc_table_sw_init(smu);
@@ -906,11 +916,15 @@ static int smu_smc_hw_setup(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
uint32_t pcie_gen = 0, pcie_width = 0;
- int ret;
+ int ret = 0;
if (adev->in_suspend && smu_is_dpm_running(smu)) {
dev_info(adev->dev, "dpm has been enabled\n");
- return 0;
+ /* this is needed specifically */
+ if ((adev->asic_type >= CHIP_SIENNA_CICHLID) &&
+ (adev->asic_type <= CHIP_DIMGREY_CAVEFISH))
+ ret = smu_system_features_control(smu, true);
+ return ret;
}
ret = smu_init_display_count(smu, 0);
@@ -1171,7 +1185,7 @@ static int smu_disable_dpms(struct smu_context *smu)
*/
if (smu->uploading_custom_pp_table &&
(adev->asic_type >= CHIP_NAVI10) &&
- (adev->asic_type <= CHIP_NAVY_FLOUNDER))
+ (adev->asic_type <= CHIP_DIMGREY_CAVEFISH))
return 0;
/*
@@ -1359,96 +1373,11 @@ int smu_display_configuration_change(struct smu_context *smu,
num_of_active_display++;
}
- smu_set_active_display_count(smu, num_of_active_display);
-
- smu_store_cc6_data(smu, display_config->cpu_pstate_separation_time,
- display_config->cpu_cc6_disable,
- display_config->cpu_pstate_disable,
- display_config->nb_pstate_switch_disable);
-
mutex_unlock(&smu->mutex);
return 0;
}
-static int smu_get_clock_info(struct smu_context *smu,
- struct smu_clock_info *clk_info,
- enum smu_perf_level_designation designation)
-{
- int ret;
- struct smu_performance_level level = {0};
-
- if (!clk_info)
- return -EINVAL;
-
- ret = smu_get_perf_level(smu, PERF_LEVEL_ACTIVITY, &level);
- if (ret)
- return -EINVAL;
-
- clk_info->min_mem_clk = level.memory_clock;
- clk_info->min_eng_clk = level.core_clock;
- clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width;
-
- ret = smu_get_perf_level(smu, designation, &level);
- if (ret)
- return -EINVAL;
-
- clk_info->min_mem_clk = level.memory_clock;
- clk_info->min_eng_clk = level.core_clock;
- clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width;
-
- return 0;
-}
-
-int smu_get_current_clocks(struct smu_context *smu,
- struct amd_pp_clock_info *clocks)
-{
- struct amd_pp_simple_clock_info simple_clocks = {0};
- struct smu_clock_info hw_clocks;
- int ret = 0;
-
- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
- return -EOPNOTSUPP;
-
- mutex_lock(&smu->mutex);
-
- smu_get_dal_power_level(smu, &simple_clocks);
-
- if (smu->support_power_containment)
- ret = smu_get_clock_info(smu, &hw_clocks,
- PERF_LEVEL_POWER_CONTAINMENT);
- else
- ret = smu_get_clock_info(smu, &hw_clocks, PERF_LEVEL_ACTIVITY);
-
- if (ret) {
- dev_err(smu->adev->dev, "Error in smu_get_clock_info\n");
- goto failed;
- }
-
- clocks->min_engine_clock = hw_clocks.min_eng_clk;
- clocks->max_engine_clock = hw_clocks.max_eng_clk;
- clocks->min_memory_clock = hw_clocks.min_mem_clk;
- clocks->max_memory_clock = hw_clocks.max_mem_clk;
- clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth;
- clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth;
- clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
- clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
-
- if (simple_clocks.level == 0)
- clocks->max_clocks_state = PP_DAL_POWERLEVEL_7;
- else
- clocks->max_clocks_state = simple_clocks.level;
-
- if (!smu_get_current_shallow_sleep_clocks(smu, &hw_clocks)) {
- clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk;
- clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk;
- }
-
-failed:
- mutex_unlock(&smu->mutex);
- return ret;
-}
-
static int smu_set_clockgating_state(void *handle,
enum amd_clockgating_state state)
{
@@ -1480,6 +1409,7 @@ static int smu_enable_umd_pstate(void *handle,
if (*level & profile_mode_mask) {
smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
smu_dpm_ctx->enable_umd_pstate = true;
+ smu_gpo_control(smu, false);
amdgpu_device_ip_set_powergating_state(smu->adev,
AMD_IP_BLOCK_TYPE_GFX,
AMD_PG_STATE_UNGATE);
@@ -1488,6 +1418,7 @@ static int smu_enable_umd_pstate(void *handle,
AMD_CG_STATE_UNGATE);
smu_gfx_ulv_control(smu, false);
smu_deep_sleep_control(smu, false);
+ amdgpu_asic_update_umd_stable_pstate(smu->adev, true);
}
} else {
/* exit umd pstate, restore level, enable gfx cg*/
@@ -1495,6 +1426,7 @@ static int smu_enable_umd_pstate(void *handle,
if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)
*level = smu_dpm_ctx->saved_dpm_level;
smu_dpm_ctx->enable_umd_pstate = false;
+ amdgpu_asic_update_umd_stable_pstate(smu->adev, false);
smu_deep_sleep_control(smu, true);
smu_gfx_ulv_control(smu, true);
amdgpu_device_ip_set_clockgating_state(smu->adev,
@@ -1503,6 +1435,7 @@ static int smu_enable_umd_pstate(void *handle,
amdgpu_device_ip_set_powergating_state(smu->adev,
AMD_IP_BLOCK_TYPE_GFX,
AMD_PG_STATE_GATE);
+ smu_gpo_control(smu, true);
}
}
@@ -1581,9 +1514,6 @@ int smu_handle_task(struct smu_context *smu,
ret = smu_pre_display_config_changed(smu);
if (ret)
goto out;
- ret = smu_set_cpu_power_state(smu);
- if (ret)
- goto out;
ret = smu_adjust_power_state_dynamic(smu, level, false);
break;
case AMD_PP_TASK_COMPLETE_INIT:
@@ -2033,40 +1963,6 @@ int smu_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, ch
return ret;
}
-int smu_get_od_percentage(struct smu_context *smu, enum smu_clk_type type)
-{
- int ret = 0;
-
- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
- return -EOPNOTSUPP;
-
- mutex_lock(&smu->mutex);
-
- if (smu->ppt_funcs->get_od_percentage)
- ret = smu->ppt_funcs->get_od_percentage(smu, type);
-
- mutex_unlock(&smu->mutex);
-
- return ret;
-}
-
-int smu_set_od_percentage(struct smu_context *smu, enum smu_clk_type type, uint32_t value)
-{
- int ret = 0;
-
- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
- return -EOPNOTSUPP;
-
- mutex_lock(&smu->mutex);
-
- if (smu->ppt_funcs->set_od_percentage)
- ret = smu->ppt_funcs->set_od_percentage(smu, type, value);
-
- mutex_unlock(&smu->mutex);
-
- return ret;
-}
-
int smu_od_edit_dpm_table(struct smu_context *smu,
enum PP_OD_DPM_TABLE_COMMAND type,
long *input, uint32_t size)
@@ -2307,43 +2203,6 @@ int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk)
return ret;
}
-int smu_get_clock_by_type(struct smu_context *smu,
- enum amd_pp_clock_type type,
- struct amd_pp_clocks *clocks)
-{
- int ret = 0;
-
- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
- return -EOPNOTSUPP;
-
- mutex_lock(&smu->mutex);
-
- if (smu->ppt_funcs->get_clock_by_type)
- ret = smu->ppt_funcs->get_clock_by_type(smu, type, clocks);
-
- mutex_unlock(&smu->mutex);
-
- return ret;
-}
-
-int smu_get_max_high_clocks(struct smu_context *smu,
- struct amd_pp_simple_clock_info *clocks)
-{
- int ret = 0;
-
- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
- return -EOPNOTSUPP;
-
- mutex_lock(&smu->mutex);
-
- if (smu->ppt_funcs->get_max_high_clocks)
- ret = smu->ppt_funcs->get_max_high_clocks(smu, clocks);
-
- mutex_unlock(&smu->mutex);
-
- return ret;
-}
-
int smu_get_clock_by_type_with_latency(struct smu_context *smu,
enum smu_clk_type clk_type,
struct pp_clock_levels_with_latency *clocks)
@@ -2363,26 +2222,6 @@ int smu_get_clock_by_type_with_latency(struct smu_context *smu,
return ret;
}
-int smu_get_clock_by_type_with_voltage(struct smu_context *smu,
- enum amd_pp_clock_type type,
- struct pp_clock_levels_with_voltage *clocks)
-{
- int ret = 0;
-
- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
- return -EOPNOTSUPP;
-
- mutex_lock(&smu->mutex);
-
- if (smu->ppt_funcs->get_clock_by_type_with_voltage)
- ret = smu->ppt_funcs->get_clock_by_type_with_voltage(smu, type, clocks);
-
- mutex_unlock(&smu->mutex);
-
- return ret;
-}
-
-
int smu_display_clock_voltage_request(struct smu_context *smu,
struct pp_display_clock_request *clock_req)
{
@@ -2419,23 +2258,6 @@ int smu_display_disable_memory_clock_switch(struct smu_context *smu, bool disabl
return ret;
}
-int smu_notify_smu_enable_pwe(struct smu_context *smu)
-{
- int ret = 0;
-
- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
- return -EOPNOTSUPP;
-
- mutex_lock(&smu->mutex);
-
- if (smu->ppt_funcs->notify_smu_enable_pwe)
- ret = smu->ppt_funcs->notify_smu_enable_pwe(smu);
-
- mutex_unlock(&smu->mutex);
-
- return ret;
-}
-
int smu_set_xgmi_pstate(struct smu_context *smu,
uint32_t pstate)
{
@@ -2713,3 +2535,15 @@ int smu_enable_mgpu_fan_boost(struct smu_context *smu)
return ret;
}
+
+int smu_gfx_state_change_set(struct smu_context *smu, uint32_t state)
+{
+ int ret = 0;
+
+ mutex_lock(&smu->mutex);
+ if (smu->ppt_funcs->gfx_state_change_set)
+ ret = smu->ppt_funcs->gfx_state_change_set(smu, state);
+ mutex_unlock(&smu->mutex);
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile
index f98d97192635..0138c982dfd3 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile
@@ -26,6 +26,7 @@
SMU11_MGR = arcturus_ppt.o \
navi10_ppt.o \
sienna_cichlid_ppt.o \
+ vangogh_ppt.o \
smu_v11_0.o
AMD_SWSMU_SMU11MGR = $(addprefix $(AMD_SWSMU_PATH)/smu11/,$(SMU11_MGR))
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index fc376281e629..cd7b411457ff 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -717,6 +717,7 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
struct smu_11_0_dpm_table *single_dpm_table;
struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
struct smu_11_0_dpm_context *dpm_context = NULL;
+ uint32_t gen_speed, lane_width;
if (amdgpu_ras_intr_triggered())
return snprintf(buf, PAGE_SIZE, "unavailable\n");
@@ -820,6 +821,23 @@ static int arcturus_print_clk_levels(struct smu_context *smu,
now) ? "*" : ""));
break;
+ case SMU_PCIE:
+ gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu);
+ lane_width = smu_v11_0_get_current_pcie_link_width_level(smu);
+ size += sprintf(buf + size, "0: %s %s %dMhz *\n",
+ (gen_speed == 0) ? "2.5GT/s," :
+ (gen_speed == 1) ? "5.0GT/s," :
+ (gen_speed == 2) ? "8.0GT/s," :
+ (gen_speed == 3) ? "16.0GT/s," : "",
+ (lane_width == 1) ? "x1" :
+ (lane_width == 2) ? "x2" :
+ (lane_width == 3) ? "x4" :
+ (lane_width == 4) ? "x8" :
+ (lane_width == 5) ? "x12" :
+ (lane_width == 6) ? "x16" : "",
+ smu->smu_table.boot_values.lclk / 100);
+ break;
+
default:
break;
}
@@ -982,77 +1000,6 @@ static int arcturus_get_thermal_temperature_range(struct smu_context *smu,
return 0;
}
-static int arcturus_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_AVERAGE_GFXACTIVITY,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_LOAD:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_AVERAGE_MEMACTIVITY,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
-static int arcturus_get_gpu_power(struct smu_context *smu, uint32_t *value)
-{
- if (!value)
- return -EINVAL;
-
- return arcturus_get_smu_metrics_data(smu,
- METRICS_AVERAGE_SOCKETPOWER,
- value);
-}
-
-static int arcturus_thermal_get_temperature(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_HOTSPOT,
- value);
- break;
- case AMDGPU_PP_SENSOR_EDGE_TEMP:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_EDGE,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = arcturus_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_MEM,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static int arcturus_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1074,21 +1021,39 @@ static int arcturus_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = arcturus_get_current_activity_percent(smu,
- sensor,
- (uint32_t *)data);
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = arcturus_get_gpu_power(smu, (uint32_t *)data);
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = arcturus_thermal_get_temperature(smu, sensor,
- (uint32_t *)data);
+ ret = arcturus_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
@@ -1121,14 +1086,9 @@ static int arcturus_get_fan_speed_rpm(struct smu_context *smu,
if (!speed)
return -EINVAL;
- switch (smu_v11_0_get_fan_control_mode(smu)) {
- case AMD_FAN_CTRL_AUTO:
- return arcturus_get_smu_metrics_data(smu,
- METRICS_CURR_FANSPEED,
- speed);
- default:
- return smu_v11_0_get_fan_speed_rpm(smu, speed);
- }
+ return arcturus_get_smu_metrics_data(smu,
+ METRICS_CURR_FANSPEED,
+ speed);
}
static int arcturus_get_fan_parameters(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index ef1a62e86a0e..51e83123f72a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1302,44 +1302,6 @@ static int navi10_display_config_changed(struct smu_context *smu)
return ret;
}
-static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value)
-{
- if (!value)
- return -EINVAL;
-
- return navi10_get_smu_metrics_data(smu,
- METRICS_AVERAGE_SOCKETPOWER,
- value);
-}
-
-static int navi10_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_AVERAGE_GFXACTIVITY,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_LOAD:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_AVERAGE_MEMACTIVITY,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static bool navi10_is_dpm_running(struct smu_context *smu)
{
int ret = 0;
@@ -1652,39 +1614,6 @@ static int navi10_set_watermarks_table(struct smu_context *smu,
return 0;
}
-static int navi10_thermal_get_temperature(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_HOTSPOT,
- value);
- break;
- case AMDGPU_PP_SENSOR_EDGE_TEMP:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_EDGE,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = navi10_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_MEM,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static int navi10_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1703,18 +1632,39 @@ static int navi10_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data);
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = navi10_get_gpu_power(smu, (uint32_t *)data);
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data);
+ ret = navi10_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
@@ -2325,210 +2275,6 @@ static int navi10_run_umc_cdr_workaround(struct smu_context *smu)
return 0;
}
-static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write,
- uint8_t address, uint32_t numbytes,
- uint8_t *data)
-{
- int i;
-
- req->I2CcontrollerPort = 0;
- req->I2CSpeed = 2;
- req->SlaveAddress = address;
- req->NumCmds = numbytes;
-
- for (i = 0; i < numbytes; i++) {
- SwI2cCmd_t *cmd = &req->SwI2cCmds[i];
-
- /* First 2 bytes are always write for lower 2b EEPROM address */
- if (i < 2)
- cmd->Cmd = 1;
- else
- cmd->Cmd = write;
-
-
- /* Add RESTART for read after address filled */
- cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
-
- /* Add STOP in the end */
- cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
-
- /* Fill with data regardless if read or write to simplify code */
- cmd->RegisterAddr = data[i];
- }
-}
-
-static int navi10_i2c_read_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
-{
- uint32_t i, ret = 0;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
- struct smu_table_context *smu_table = &adev->smu.smu_table;
- struct smu_table *table = &smu_table->driver_table;
-
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
- }
-
- memset(&req, 0, sizeof(req));
- navi10_fill_i2c_req(&req, false, address, numbytes, data);
-
- mutex_lock(&adev->smu.mutex);
- /* Now read data starting with that address */
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
- true);
- mutex_unlock(&adev->smu.mutex);
-
- if (!ret) {
- SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
-
- /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */
- for (i = 0; i < numbytes; i++)
- data[i] = res->SwI2cCmds[i].Data;
-
- dev_dbg(adev->dev, "navi10_i2c_read_data, address = %x, bytes = %d, data :",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- } else
- dev_err(adev->dev, "navi10_i2c_read_data - error occurred :%x", ret);
-
- return ret;
-}
-
-static int navi10_i2c_write_data(struct i2c_adapter *control,
- uint8_t address,
- uint8_t *data,
- uint32_t numbytes)
-{
- uint32_t ret;
- SwI2cRequest_t req;
- struct amdgpu_device *adev = to_amdgpu_device(control);
-
- if (numbytes > MAX_SW_I2C_COMMANDS) {
- dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n",
- numbytes, MAX_SW_I2C_COMMANDS);
- return -EINVAL;
- }
-
- memset(&req, 0, sizeof(req));
- navi10_fill_i2c_req(&req, true, address, numbytes, data);
-
- mutex_lock(&adev->smu.mutex);
- ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
- mutex_unlock(&adev->smu.mutex);
-
- if (!ret) {
- dev_dbg(adev->dev, "navi10_i2c_write(), address = %x, bytes = %d , data: ",
- (uint16_t)address, numbytes);
-
- print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
- 8, 1, data, numbytes, false);
- /*
- * According to EEPROM spec there is a MAX of 10 ms required for
- * EEPROM to flush internal RX buffer after STOP was issued at the
- * end of write transaction. During this time the EEPROM will not be
- * responsive to any more commands - so wait a bit more.
- */
- msleep(10);
-
- } else
- dev_err(adev->dev, "navi10_i2c_write- error occurred :%x", ret);
-
- return ret;
-}
-
-static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
- struct i2c_msg *msgs, int num)
-{
- uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
- uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
-
- for (i = 0; i < num; i++) {
- /*
- * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
- * once and hence the data needs to be spliced into chunks and sent each
- * chunk separately
- */
- data_size = msgs[i].len - 2;
- data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
- next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
- data_ptr = msgs[i].buf + 2;
-
- for (j = 0; j < data_size / data_chunk_size; j++) {
- /* Insert the EEPROM dest addess, bits 0-15 */
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = navi10_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
-
- memcpy(data_ptr, data_chunk + 2, data_chunk_size);
- } else {
-
- memcpy(data_chunk + 2, data_ptr, data_chunk_size);
-
- ret = navi10_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, MAX_SW_I2C_COMMANDS);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
-
- next_eeprom_addr += data_chunk_size;
- data_ptr += data_chunk_size;
- }
-
- if (data_size % data_chunk_size) {
- data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
- data_chunk[1] = (next_eeprom_addr & 0xff);
-
- if (msgs[i].flags & I2C_M_RD) {
- ret = navi10_i2c_read_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
-
- memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
- } else {
- memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
-
- ret = navi10_i2c_write_data(i2c_adap,
- (uint8_t)msgs[i].addr,
- data_chunk, (data_size % data_chunk_size) + 2);
- }
-
- if (ret) {
- num = -EIO;
- goto fail;
- }
- }
- }
-
-fail:
- return num;
-}
-
-static u32 navi10_i2c_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-
-static const struct i2c_algorithm navi10_i2c_algo = {
- .master_xfer = navi10_i2c_xfer,
- .functionality = navi10_i2c_func,
-};
-
static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
void **table)
{
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 895d89bea7fa..9608745d732f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -127,6 +127,9 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT]
MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0),
MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0),
MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0),
+ MSG_MAP(SetGpoFeaturePMask, PPSMC_MSG_SetGpoFeaturePMask, 0),
+ MSG_MAP(DisallowGpo, PPSMC_MSG_DisallowGpo, 0),
+ MSG_MAP(Enable2ndUSB20Port, PPSMC_MSG_Enable2ndUSB20Port, 0),
};
static struct cmn2asic_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = {
@@ -217,7 +220,7 @@ static struct cmn2asic_mapping sienna_cichlid_workload_map[PP_SMC_POWER_PROFILE_
WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT),
WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT),
WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT),
- WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_CUSTOM_BIT),
+ WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT),
WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT),
};
@@ -301,6 +304,9 @@ static int sienna_cichlid_check_powerplay_table(struct smu_context *smu)
table_context->power_play_table;
struct smu_baco_context *smu_baco = &smu->smu_baco;
+ if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_HARDWAREDC)
+ smu->dc_controlled_by_gpio = true;
+
if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO ||
powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_MACO)
smu_baco->platform_support = true;
@@ -376,7 +382,7 @@ static int sienna_cichlid_tables_init(struct smu_context *smu)
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
- SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
@@ -385,10 +391,10 @@ static int sienna_cichlid_tables_init(struct smu_context *smu)
SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE,
+ sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE,
AMDGPU_GEM_DOMAIN_VRAM);
- smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
+ smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL);
if (!smu_table->metrics_table)
goto err0_out;
smu_table->metrics_time = 0;
@@ -417,7 +423,8 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu,
uint32_t *value)
{
struct smu_table_context *smu_table= &smu->smu_table;
- SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
+ SmuMetrics_t *metrics =
+ &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics);
int ret = 0;
mutex_lock(&smu->metrics_lock);
@@ -1064,12 +1071,18 @@ static int sienna_cichlid_populate_umd_state_clk(struct smu_context *smu)
pstate_table->gfxclk_pstate.min = gfx_table->min;
pstate_table->gfxclk_pstate.peak = gfx_table->max;
+ if (gfx_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK)
+ pstate_table->gfxclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK;
pstate_table->uclk_pstate.min = mem_table->min;
pstate_table->uclk_pstate.peak = mem_table->max;
+ if (mem_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK)
+ pstate_table->uclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK;
pstate_table->socclk_pstate.min = soc_table->min;
pstate_table->socclk_pstate.peak = soc_table->max;
+ if (soc_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK)
+ pstate_table->socclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK;
return 0;
}
@@ -1118,44 +1131,6 @@ static int sienna_cichlid_display_config_changed(struct smu_context *smu)
return ret;
}
-static int sienna_cichlid_get_gpu_power(struct smu_context *smu, uint32_t *value)
-{
- if (!value)
- return -EINVAL;
-
- return sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_AVERAGE_SOCKETPOWER,
- value);
-}
-
-static int sienna_cichlid_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_AVERAGE_GFXACTIVITY,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_LOAD:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_AVERAGE_MEMACTIVITY,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static bool sienna_cichlid_is_dpm_running(struct smu_context *smu)
{
int ret = 0;
@@ -1193,7 +1168,9 @@ static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *buf)
{
- DpmActivityMonitorCoeffInt_t activity_monitor;
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
+ DpmActivityMonitorCoeffInt_t *activity_monitor =
+ &(activity_monitor_external.DpmActivityMonitorCoeffInt);
uint32_t i, size = 0;
int16_t workload_type = 0;
static const char *profile_name[] = {
@@ -1235,7 +1212,7 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
result = smu_cmn_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type,
- (void *)(&activity_monitor), false);
+ (void *)(&activity_monitor_external), false);
if (result) {
dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
return result;
@@ -1248,43 +1225,43 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
" ",
0,
"GFXCLK",
- activity_monitor.Gfx_FPS,
- activity_monitor.Gfx_MinFreqStep,
- activity_monitor.Gfx_MinActiveFreqType,
- activity_monitor.Gfx_MinActiveFreq,
- activity_monitor.Gfx_BoosterFreqType,
- activity_monitor.Gfx_BoosterFreq,
- activity_monitor.Gfx_PD_Data_limit_c,
- activity_monitor.Gfx_PD_Data_error_coeff,
- activity_monitor.Gfx_PD_Data_error_rate_coeff);
+ activity_monitor->Gfx_FPS,
+ activity_monitor->Gfx_MinFreqStep,
+ activity_monitor->Gfx_MinActiveFreqType,
+ activity_monitor->Gfx_MinActiveFreq,
+ activity_monitor->Gfx_BoosterFreqType,
+ activity_monitor->Gfx_BoosterFreq,
+ activity_monitor->Gfx_PD_Data_limit_c,
+ activity_monitor->Gfx_PD_Data_error_coeff,
+ activity_monitor->Gfx_PD_Data_error_rate_coeff);
size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
1,
"SOCCLK",
- activity_monitor.Fclk_FPS,
- activity_monitor.Fclk_MinFreqStep,
- activity_monitor.Fclk_MinActiveFreqType,
- activity_monitor.Fclk_MinActiveFreq,
- activity_monitor.Fclk_BoosterFreqType,
- activity_monitor.Fclk_BoosterFreq,
- activity_monitor.Fclk_PD_Data_limit_c,
- activity_monitor.Fclk_PD_Data_error_coeff,
- activity_monitor.Fclk_PD_Data_error_rate_coeff);
+ activity_monitor->Fclk_FPS,
+ activity_monitor->Fclk_MinFreqStep,
+ activity_monitor->Fclk_MinActiveFreqType,
+ activity_monitor->Fclk_MinActiveFreq,
+ activity_monitor->Fclk_BoosterFreqType,
+ activity_monitor->Fclk_BoosterFreq,
+ activity_monitor->Fclk_PD_Data_limit_c,
+ activity_monitor->Fclk_PD_Data_error_coeff,
+ activity_monitor->Fclk_PD_Data_error_rate_coeff);
size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
" ",
2,
"MEMLK",
- activity_monitor.Mem_FPS,
- activity_monitor.Mem_MinFreqStep,
- activity_monitor.Mem_MinActiveFreqType,
- activity_monitor.Mem_MinActiveFreq,
- activity_monitor.Mem_BoosterFreqType,
- activity_monitor.Mem_BoosterFreq,
- activity_monitor.Mem_PD_Data_limit_c,
- activity_monitor.Mem_PD_Data_error_coeff,
- activity_monitor.Mem_PD_Data_error_rate_coeff);
+ activity_monitor->Mem_FPS,
+ activity_monitor->Mem_MinFreqStep,
+ activity_monitor->Mem_MinActiveFreqType,
+ activity_monitor->Mem_MinActiveFreq,
+ activity_monitor->Mem_BoosterFreqType,
+ activity_monitor->Mem_BoosterFreq,
+ activity_monitor->Mem_PD_Data_limit_c,
+ activity_monitor->Mem_PD_Data_error_coeff,
+ activity_monitor->Mem_PD_Data_error_rate_coeff);
}
return size;
@@ -1292,7 +1269,10 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
{
- DpmActivityMonitorCoeffInt_t activity_monitor;
+
+ DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
+ DpmActivityMonitorCoeffInt_t *activity_monitor =
+ &(activity_monitor_external.DpmActivityMonitorCoeffInt);
int workload_type, ret = 0;
smu->power_profile_mode = input[size];
@@ -1306,7 +1286,7 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *
ret = smu_cmn_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor), false);
+ (void *)(&activity_monitor_external), false);
if (ret) {
dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
return ret;
@@ -1314,43 +1294,43 @@ static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *
switch (input[0]) {
case 0: /* Gfxclk */
- activity_monitor.Gfx_FPS = input[1];
- activity_monitor.Gfx_MinFreqStep = input[2];
- activity_monitor.Gfx_MinActiveFreqType = input[3];
- activity_monitor.Gfx_MinActiveFreq = input[4];
- activity_monitor.Gfx_BoosterFreqType = input[5];
- activity_monitor.Gfx_BoosterFreq = input[6];
- activity_monitor.Gfx_PD_Data_limit_c = input[7];
- activity_monitor.Gfx_PD_Data_error_coeff = input[8];
- activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
+ activity_monitor->Gfx_FPS = input[1];
+ activity_monitor->Gfx_MinFreqStep = input[2];
+ activity_monitor->Gfx_MinActiveFreqType = input[3];
+ activity_monitor->Gfx_MinActiveFreq = input[4];
+ activity_monitor->Gfx_BoosterFreqType = input[5];
+ activity_monitor->Gfx_BoosterFreq = input[6];
+ activity_monitor->Gfx_PD_Data_limit_c = input[7];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[8];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[9];
break;
case 1: /* Socclk */
- activity_monitor.Fclk_FPS = input[1];
- activity_monitor.Fclk_MinFreqStep = input[2];
- activity_monitor.Fclk_MinActiveFreqType = input[3];
- activity_monitor.Fclk_MinActiveFreq = input[4];
- activity_monitor.Fclk_BoosterFreqType = input[5];
- activity_monitor.Fclk_BoosterFreq = input[6];
- activity_monitor.Fclk_PD_Data_limit_c = input[7];
- activity_monitor.Fclk_PD_Data_error_coeff = input[8];
- activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9];
+ activity_monitor->Fclk_FPS = input[1];
+ activity_monitor->Fclk_MinFreqStep = input[2];
+ activity_monitor->Fclk_MinActiveFreqType = input[3];
+ activity_monitor->Fclk_MinActiveFreq = input[4];
+ activity_monitor->Fclk_BoosterFreqType = input[5];
+ activity_monitor->Fclk_BoosterFreq = input[6];
+ activity_monitor->Fclk_PD_Data_limit_c = input[7];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[8];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[9];
break;
case 2: /* Memlk */
- activity_monitor.Mem_FPS = input[1];
- activity_monitor.Mem_MinFreqStep = input[2];
- activity_monitor.Mem_MinActiveFreqType = input[3];
- activity_monitor.Mem_MinActiveFreq = input[4];
- activity_monitor.Mem_BoosterFreqType = input[5];
- activity_monitor.Mem_BoosterFreq = input[6];
- activity_monitor.Mem_PD_Data_limit_c = input[7];
- activity_monitor.Mem_PD_Data_error_coeff = input[8];
- activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
+ activity_monitor->Mem_FPS = input[1];
+ activity_monitor->Mem_MinFreqStep = input[2];
+ activity_monitor->Mem_MinActiveFreqType = input[3];
+ activity_monitor->Mem_MinActiveFreq = input[4];
+ activity_monitor->Mem_BoosterFreqType = input[5];
+ activity_monitor->Mem_BoosterFreq = input[6];
+ activity_monitor->Mem_PD_Data_limit_c = input[7];
+ activity_monitor->Mem_PD_Data_error_coeff = input[8];
+ activity_monitor->Mem_PD_Data_error_rate_coeff = input[9];
break;
}
ret = smu_cmn_update_table(smu,
SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor), true);
+ (void *)(&activity_monitor_external), true);
if (ret) {
dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
return ret;
@@ -1467,39 +1447,6 @@ static int sienna_cichlid_set_watermarks_table(struct smu_context *smu,
return 0;
}
-static int sienna_cichlid_thermal_get_temperature(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
-
- if (!value)
- return -EINVAL;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_HOTSPOT,
- value);
- break;
- case AMDGPU_PP_SENSOR_EDGE_TEMP:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_EDGE,
- value);
- break;
- case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = sienna_cichlid_get_smu_metrics_data(smu,
- METRICS_TEMPERATURE_MEM,
- value);
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n");
- return -EINVAL;
- }
-
- return ret;
-}
-
static int sienna_cichlid_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1518,18 +1465,39 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
*size = 4;
break;
case AMDGPU_PP_SENSOR_MEM_LOAD:
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_MEMACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = sienna_cichlid_get_current_activity_percent(smu, sensor, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = sienna_cichlid_get_gpu_power(smu, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
case AMDGPU_PP_SENSOR_MEM_TEMP:
- ret = sienna_cichlid_thermal_get_temperature(smu, sensor, (uint32_t *)data);
+ ret = sienna_cichlid_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_MEM,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
@@ -1804,11 +1772,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
dev_info(smu->adev->dev, "SmnclkDpmFreq[%d] = 0x%x\n", i, pptable->SmnclkDpmFreq[i]);
dev_info(smu->adev->dev, "SmnclkDpmVoltage[%d] = 0x%x\n", i, pptable->SmnclkDpmVoltage[i]);
}
- dev_info(smu->adev->dev, "PaddingAPCC[0] = 0x%x\n", pptable->PaddingAPCC[0]);
- dev_info(smu->adev->dev, "PaddingAPCC[1] = 0x%x\n", pptable->PaddingAPCC[1]);
- dev_info(smu->adev->dev, "PaddingAPCC[2] = 0x%x\n", pptable->PaddingAPCC[2]);
- dev_info(smu->adev->dev, "PaddingAPCC[3] = 0x%x\n", pptable->PaddingAPCC[3]);
-
dev_info(smu->adev->dev, "ThrottlerControlMask = 0x%x\n", pptable->ThrottlerControlMask);
dev_info(smu->adev->dev, "FwDStateMask = 0x%x\n", pptable->FwDStateMask);
@@ -2035,23 +1998,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++)
dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableFclk[i]);
- dev_info(smu->adev->dev, "Paddingclks[0] = 0x%x\n", pptable->Paddingclks[0]);
- dev_info(smu->adev->dev, "Paddingclks[1] = 0x%x\n", pptable->Paddingclks[1]);
- dev_info(smu->adev->dev, "Paddingclks[2] = 0x%x\n", pptable->Paddingclks[2]);
- dev_info(smu->adev->dev, "Paddingclks[3] = 0x%x\n", pptable->Paddingclks[3]);
- dev_info(smu->adev->dev, "Paddingclks[4] = 0x%x\n", pptable->Paddingclks[4]);
- dev_info(smu->adev->dev, "Paddingclks[5] = 0x%x\n", pptable->Paddingclks[5]);
- dev_info(smu->adev->dev, "Paddingclks[6] = 0x%x\n", pptable->Paddingclks[6]);
- dev_info(smu->adev->dev, "Paddingclks[7] = 0x%x\n", pptable->Paddingclks[7]);
- dev_info(smu->adev->dev, "Paddingclks[8] = 0x%x\n", pptable->Paddingclks[8]);
- dev_info(smu->adev->dev, "Paddingclks[9] = 0x%x\n", pptable->Paddingclks[9]);
- dev_info(smu->adev->dev, "Paddingclks[10] = 0x%x\n", pptable->Paddingclks[10]);
- dev_info(smu->adev->dev, "Paddingclks[11] = 0x%x\n", pptable->Paddingclks[11]);
- dev_info(smu->adev->dev, "Paddingclks[12] = 0x%x\n", pptable->Paddingclks[12]);
- dev_info(smu->adev->dev, "Paddingclks[13] = 0x%x\n", pptable->Paddingclks[13]);
- dev_info(smu->adev->dev, "Paddingclks[14] = 0x%x\n", pptable->Paddingclks[14]);
- dev_info(smu->adev->dev, "Paddingclks[15] = 0x%x\n", pptable->Paddingclks[15]);
-
dev_info(smu->adev->dev, "DcModeMaxFreq\n");
dev_info(smu->adev->dev, " .PPCLK_GFXCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]);
dev_info(smu->adev->dev, " .PPCLK_SOCCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]);
@@ -2278,7 +2224,6 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
dev_info(smu->adev->dev, "SkuReserved[5] = 0x%x\n", pptable->SkuReserved[5]);
dev_info(smu->adev->dev, "SkuReserved[6] = 0x%x\n", pptable->SkuReserved[6]);
dev_info(smu->adev->dev, "SkuReserved[7] = 0x%x\n", pptable->SkuReserved[7]);
- dev_info(smu->adev->dev, "SkuReserved[8] = 0x%x\n", pptable->SkuReserved[8]);
dev_info(smu->adev->dev, "GamingClk[0] = 0x%x\n", pptable->GamingClk[0]);
dev_info(smu->adev->dev, "GamingClk[1] = 0x%x\n", pptable->GamingClk[1]);
@@ -2654,52 +2599,54 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
struct smu_table_context *smu_table = &smu->smu_table;
struct gpu_metrics_v1_0 *gpu_metrics =
(struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table;
- SmuMetrics_t metrics;
+ SmuMetricsExternal_t metrics_external;
+ SmuMetrics_t *metrics =
+ &(metrics_external.SmuMetrics);
int ret = 0;
ret = smu_cmn_get_metrics_table(smu,
- &metrics,
+ &metrics_external,
true);
if (ret)
return ret;
smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics);
- gpu_metrics->temperature_edge = metrics.TemperatureEdge;
- gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot;
- gpu_metrics->temperature_mem = metrics.TemperatureMem;
- gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx;
- gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc;
- gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0;
+ gpu_metrics->temperature_edge = metrics->TemperatureEdge;
+ gpu_metrics->temperature_hotspot = metrics->TemperatureHotspot;
+ gpu_metrics->temperature_mem = metrics->TemperatureMem;
+ gpu_metrics->temperature_vrgfx = metrics->TemperatureVrGfx;
+ gpu_metrics->temperature_vrsoc = metrics->TemperatureVrSoc;
+ gpu_metrics->temperature_vrmem = metrics->TemperatureVrMem0;
- gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity;
- gpu_metrics->average_umc_activity = metrics.AverageUclkActivity;
- gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage;
+ gpu_metrics->average_gfx_activity = metrics->AverageGfxActivity;
+ gpu_metrics->average_umc_activity = metrics->AverageUclkActivity;
+ gpu_metrics->average_mm_activity = metrics->VcnActivityPercentage;
- gpu_metrics->average_socket_power = metrics.AverageSocketPower;
- gpu_metrics->energy_accumulator = metrics.EnergyAccumulator;
+ gpu_metrics->average_socket_power = metrics->AverageSocketPower;
+ gpu_metrics->energy_accumulator = metrics->EnergyAccumulator;
- if (metrics.AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
- gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPostDs;
+ if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD)
+ gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPostDs;
else
- gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPreDs;
- gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequencyPostDs;
- gpu_metrics->average_vclk0_frequency = metrics.AverageVclk0Frequency;
- gpu_metrics->average_dclk0_frequency = metrics.AverageDclk0Frequency;
- gpu_metrics->average_vclk1_frequency = metrics.AverageVclk1Frequency;
- gpu_metrics->average_dclk1_frequency = metrics.AverageDclk1Frequency;
+ gpu_metrics->average_gfxclk_frequency = metrics->AverageGfxclkFrequencyPreDs;
+ gpu_metrics->average_uclk_frequency = metrics->AverageUclkFrequencyPostDs;
+ gpu_metrics->average_vclk0_frequency = metrics->AverageVclk0Frequency;
+ gpu_metrics->average_dclk0_frequency = metrics->AverageDclk0Frequency;
+ gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
+ gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
- gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK];
- gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK];
- gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK];
- gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK_0];
- gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK_0];
- gpu_metrics->current_vclk1 = metrics.CurrClock[PPCLK_VCLK_1];
- gpu_metrics->current_dclk1 = metrics.CurrClock[PPCLK_DCLK_1];
+ gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
+ gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
+ gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
+ gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
+ gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
+ gpu_metrics->current_dclk1 = metrics->CurrClock[PPCLK_DCLK_1];
- gpu_metrics->throttle_status = metrics.ThrottlerStatus;
+ gpu_metrics->throttle_status = metrics->ThrottlerStatus;
- gpu_metrics->current_fan_speed = metrics.CurrFanSpeed;
+ gpu_metrics->current_fan_speed = metrics->CurrFanSpeed;
gpu_metrics->pcie_link_width =
smu_v11_0_get_current_pcie_link_width(smu);
@@ -2719,6 +2666,85 @@ static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu)
NULL);
}
+static int sienna_cichlid_gpo_control(struct smu_context *smu,
+ bool enablement)
+{
+ uint32_t smu_version;
+ int ret = 0;
+
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_GFX_GPO_BIT)) {
+ ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
+ if (ret)
+ return ret;
+
+ if (enablement) {
+ if (smu_version < 0x003a2500) {
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetGpoFeaturePMask,
+ GFX_GPO_PACE_MASK | GFX_GPO_DEM_MASK,
+ NULL);
+ } else {
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_DisallowGpo,
+ 0,
+ NULL);
+ }
+ } else {
+ if (smu_version < 0x003a2500) {
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetGpoFeaturePMask,
+ 0,
+ NULL);
+ } else {
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_DisallowGpo,
+ 1,
+ NULL);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int sienna_cichlid_notify_2nd_usb20_port(struct smu_context *smu)
+{
+ uint32_t smu_version;
+ int ret = 0;
+
+ ret = smu_cmn_get_smc_version(smu, NULL, &smu_version);
+ if (ret)
+ return ret;
+
+ /*
+ * Message SMU_MSG_Enable2ndUSB20Port is supported by 58.45
+ * onwards PMFWs.
+ */
+ if (smu_version < 0x003A2D00)
+ return 0;
+
+ return smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_Enable2ndUSB20Port,
+ smu->smu_table.boot_values.firmware_caps & ATOM_FIRMWARE_CAP_ENABLE_2ND_USB20PORT ?
+ 1 : 0,
+ NULL);
+}
+
+static int sienna_cichlid_system_features_control(struct smu_context *smu,
+ bool en)
+{
+ int ret = 0;
+
+ if (en) {
+ ret = sienna_cichlid_notify_2nd_usb20_port(smu);
+ if (ret)
+ return ret;
+ }
+
+ return smu_v11_0_system_features_control(smu, en);
+}
+
static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask,
.set_default_dpm_table = sienna_cichlid_set_default_dpm_table,
@@ -2759,7 +2785,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.set_driver_table_location = smu_v11_0_set_driver_table_location,
.set_tool_table_location = smu_v11_0_set_tool_table_location,
.notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
- .system_features_control = smu_v11_0_system_features_control,
+ .system_features_control = sienna_cichlid_system_features_control,
.send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
.send_smc_msg = smu_cmn_send_smc_msg,
.init_display_count = NULL,
@@ -2792,6 +2818,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq,
.set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range,
.run_btc = sienna_cichlid_run_btc,
+ .set_power_source = smu_v11_0_set_power_source,
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
.get_gpu_metrics = sienna_cichlid_get_gpu_metrics,
@@ -2800,6 +2827,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
.deep_sleep_control = smu_v11_0_deep_sleep_control,
.get_fan_parameters = sienna_cichlid_get_fan_parameters,
.interrupt_work = smu_v11_0_interrupt_work,
+ .gpo_control = sienna_cichlid_gpo_control,
};
void sienna_cichlid_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h
index 57e120c440ea..38cd0ece24f6 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h
@@ -29,6 +29,10 @@ typedef enum {
POWER_SOURCE_COUNT,
} POWER_SOURCE_e;
+#define SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK 1825
+#define SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK 960
+#define SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK 1000
+
extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu);
#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index 2380759ddf48..b279dbbbce6b 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -62,6 +62,7 @@ MODULE_FIRMWARE("amdgpu/navi14_smc.bin");
MODULE_FIRMWARE("amdgpu/navi12_smc.bin");
MODULE_FIRMWARE("amdgpu/sienna_cichlid_smc.bin");
MODULE_FIRMWARE("amdgpu/navy_flounder_smc.bin");
+MODULE_FIRMWARE("amdgpu/dimgrey_cavefish_smc.bin");
#define SMU11_VOLTAGE_SCALE 4
@@ -84,12 +85,17 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
const char *chip_name;
- char fw_name[30];
+ char fw_name[SMU_FW_NAME_LEN];
int err = 0;
const struct smc_firmware_header_v1_0 *hdr;
const struct common_firmware_header *header;
struct amdgpu_firmware_info *ucode = NULL;
+ if (amdgpu_sriov_vf(adev) &&
+ ((adev->asic_type == CHIP_NAVI12) ||
+ (adev->asic_type == CHIP_SIENNA_CICHLID)))
+ return 0;
+
switch (adev->asic_type) {
case CHIP_ARCTURUS:
chip_name = "arcturus";
@@ -109,6 +115,9 @@ int smu_v11_0_init_microcode(struct smu_context *smu)
case CHIP_NAVY_FLOUNDER:
chip_name = "navy_flounder";
break;
+ case CHIP_DIMGREY_CAVEFISH:
+ chip_name = "dimgrey_cavefish";
+ break;
default:
dev_err(adev->dev, "Unsupported ASIC type %d\n", adev->asic_type);
return -EINVAL;
@@ -212,6 +221,7 @@ int smu_v11_0_check_fw_status(struct smu_context *smu)
int smu_v11_0_check_fw_version(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
uint32_t if_version = 0xff, smu_version = 0xff;
uint16_t smu_major;
uint8_t smu_minor, smu_debug;
@@ -224,6 +234,8 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
smu_major = (smu_version >> 16) & 0xffff;
smu_minor = (smu_version >> 8) & 0xff;
smu_debug = (smu_version >> 0) & 0xff;
+ if (smu->is_apu)
+ adev->pm.fw_version = smu_version;
switch (smu->adev->asic_type) {
case CHIP_ARCTURUS:
@@ -244,6 +256,12 @@ int smu_v11_0_check_fw_version(struct smu_context *smu)
case CHIP_NAVY_FLOUNDER:
smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder;
break;
+ case CHIP_VANGOGH:
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_VANGOGH;
+ break;
+ case CHIP_DIMGREY_CAVEFISH:
+ smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish;
+ break;
default:
dev_err(smu->adev->dev, "smu unsupported asic type:%d.\n", smu->adev->asic_type);
smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV;
@@ -326,8 +344,7 @@ int smu_v11_0_setup_pptable(struct smu_context *smu)
hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
version_major = le16_to_cpu(hdr->header.header_version_major);
version_minor = le16_to_cpu(hdr->header.header_version_minor);
- if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) ||
- adev->asic_type == CHIP_NAVY_FLOUNDER) {
+ if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) {
dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id);
switch (version_minor) {
case 0:
@@ -425,11 +442,13 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
kfree(smu_table->overdrive_table);
kfree(smu_table->max_sustainable_clocks);
kfree(smu_table->driver_pptable);
+ kfree(smu_table->clocks_table);
smu_table->gpu_metrics_table = NULL;
smu_table->boot_overdrive_table = NULL;
smu_table->overdrive_table = NULL;
smu_table->max_sustainable_clocks = NULL;
smu_table->driver_pptable = NULL;
+ smu_table->clocks_table = NULL;
kfree(smu_table->hardcode_pptable);
smu_table->hardcode_pptable = NULL;
@@ -456,11 +475,11 @@ int smu_v11_0_init_power(struct smu_context *smu)
{
struct smu_power_context *smu_power = &smu->smu_power;
- smu_power->power_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
+ smu_power->power_context = kzalloc(sizeof(struct smu_11_0_power_context),
GFP_KERNEL);
if (!smu_power->power_context)
return -ENOMEM;
- smu_power->power_context_size = sizeof(struct smu_11_0_dpm_context);
+ smu_power->power_context_size = sizeof(struct smu_11_0_power_context);
return 0;
}
@@ -540,6 +559,7 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
smu->smu_table.boot_values.vdd_gfx = v_3_1->bootup_vddgfx_mv;
smu->smu_table.boot_values.cooling_id = v_3_1->coolingsolution_id;
smu->smu_table.boot_values.pp_table_id = 0;
+ smu->smu_table.boot_values.firmware_caps = v_3_1->firmware_capability;
break;
case 3:
default:
@@ -555,6 +575,7 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
smu->smu_table.boot_values.vdd_gfx = v_3_3->bootup_vddgfx_mv;
smu->smu_table.boot_values.cooling_id = v_3_3->coolingsolution_id;
smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id;
+ smu->smu_table.boot_values.firmware_caps = v_3_3->firmware_capability;
}
smu->smu_table.boot_values.format_revision = header->format_revision;
@@ -592,6 +613,11 @@ int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
(uint8_t)SMU11_SYSPLL1_2_ID,
&smu->smu_table.boot_values.fclk);
+ smu_v11_0_atom_get_smu_clockinfo(smu->adev,
+ (uint8_t)SMU11_SYSPLL3_1_LCLK_ID,
+ (uint8_t)SMU11_SYSPLL3_1_ID,
+ &smu->smu_table.boot_values.lclk);
+
return 0;
}
@@ -699,8 +725,11 @@ int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count)
{
struct amdgpu_device *adev = smu->adev;
- /* Navy_Flounder do not support to change display num currently */
- if (adev->asic_type == CHIP_NAVY_FLOUNDER)
+ /* Navy_Flounder/Dimgrey_Cavefish do not support to change
+ * display num currently
+ */
+ if (adev->asic_type >= CHIP_NAVY_FLOUNDER &&
+ adev->asic_type <= CHIP_DIMGREY_CAVEFISH)
return 0;
return smu_cmn_send_smc_msg_with_param(smu,
@@ -907,9 +936,13 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu,
if (power_src < 0)
return -EINVAL;
+ /*
+ * BIT 24-31: ControllerId (only PPT0 is supported for now)
+ * BIT 16-23: PowerSource
+ */
ret = smu_cmn_send_smc_msg_with_param(smu,
SMU_MSG_GetPptLimit,
- power_src << 16,
+ (0 << 24) | (power_src << 16),
power_limit);
if (ret)
dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
@@ -919,6 +952,7 @@ int smu_v11_0_get_current_power_limit(struct smu_context *smu,
int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
{
+ int power_src;
int ret = 0;
if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
@@ -926,6 +960,22 @@ int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n)
return -EOPNOTSUPP;
}
+ power_src = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_PWR,
+ smu->adev->pm.ac_power ?
+ SMU_POWER_SOURCE_AC :
+ SMU_POWER_SOURCE_DC);
+ if (power_src < 0)
+ return -EINVAL;
+
+ /*
+ * BIT 24-31: ControllerId (only PPT0 is supported for now)
+ * BIT 16-23: PowerSource
+ * BIT 0-15: PowerLimit
+ */
+ n &= 0xFFFF;
+ n |= 0 << 24;
+ n |= (power_src) << 16;
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n, NULL);
if (ret) {
dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
@@ -1068,6 +1118,7 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
case CHIP_NAVI12:
case CHIP_SIENNA_CICHLID:
case CHIP_NAVY_FLOUNDER:
+ case CHIP_DIMGREY_CAVEFISH:
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
return 0;
if (enable)
@@ -1164,7 +1215,12 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
if (ret)
return ret;
- crystal_clock_freq = amdgpu_asic_get_xclk(adev);
+ /*
+ * crystal_clock_freq div by 4 is required since the fan control
+ * module refers to 25MHz
+ */
+
+ crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
@@ -1462,6 +1518,9 @@ enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
return baco_state;
}
+#define D3HOT_BACO_SEQUENCE 0
+#define D3HOT_BAMACO_SEQUENCE 2
+
int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
{
struct smu_baco_context *smu_baco = &smu->smu_baco;
@@ -1476,15 +1535,34 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
mutex_lock(&smu_baco->mutex);
if (state == SMU_BACO_STATE_ENTER) {
- if (!ras || !ras->supported) {
- data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
- data |= 0x80000000;
- WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
-
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
- } else {
- ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL);
+ switch (adev->asic_type) {
+ case CHIP_SIENNA_CICHLID:
+ case CHIP_NAVY_FLOUNDER:
+ case CHIP_DIMGREY_CAVEFISH:
+ if (amdgpu_runtime_pm == 2)
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_EnterBaco,
+ D3HOT_BAMACO_SEQUENCE,
+ NULL);
+ else
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_EnterBaco,
+ D3HOT_BACO_SEQUENCE,
+ NULL);
+ break;
+ default:
+ if (!ras || !ras->supported) {
+ data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+ data |= 0x80000000;
+ WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
+ } else {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL);
+ }
+ break;
}
+
} else {
ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL);
if (ret)
@@ -1977,6 +2055,18 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics)
gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
}
+void smu_v11_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics)
+{
+ memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0));
+
+ gpu_metrics->common_header.structure_size =
+ sizeof(struct gpu_metrics_v2_0);
+ gpu_metrics->common_header.format_revision = 2;
+ gpu_metrics->common_header.content_revision = 0;
+
+ gpu_metrics->system_clock_counter = ktime_get_boottime_ns();
+}
+
int smu_v11_0_gfx_ulv_control(struct smu_context *smu,
bool enablement)
{
@@ -2002,6 +2092,22 @@ int smu_v11_0_deep_sleep_control(struct smu_context *smu,
}
}
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_UCLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_UCLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s UCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
+ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_FCLK_BIT)) {
+ ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_FCLK_BIT, enablement);
+ if (ret) {
+ dev_err(adev->dev, "Failed to %s FCLK DS!\n", enablement ? "enable" : "disable");
+ return ret;
+ }
+ }
+
if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_SOCCLK_BIT)) {
ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_SOCCLK_BIT, enablement);
if (ret) {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
new file mode 100644
index 000000000000..8cb4fcee9a2c
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#define SWSMU_CODE_LAYER_L2
+
+#include "amdgpu.h"
+#include "amdgpu_smu.h"
+#include "smu_v11_0.h"
+#include "smu11_driver_if_vangogh.h"
+#include "vangogh_ppt.h"
+#include "smu_v11_5_ppsmc.h"
+#include "smu_v11_5_pmfw.h"
+#include "smu_cmn.h"
+
+/*
+ * DO NOT use these for err/warn/info/debug messages.
+ * Use dev_err, dev_warn, dev_info and dev_dbg instead.
+ * They are more MGPU friendly.
+ */
+#undef pr_err
+#undef pr_warn
+#undef pr_info
+#undef pr_debug
+
+#define FEATURE_MASK(feature) (1ULL << feature)
+#define SMC_DPM_FEATURE ( \
+ FEATURE_MASK(FEATURE_CCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_VCN_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_LCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_SHUBCLK_DPM_BIT) | \
+ FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT)| \
+ FEATURE_MASK(FEATURE_GFX_DPM_BIT))
+
+static struct cmn2asic_msg_mapping vangogh_message_map[SMU_MSG_MAX_COUNT] = {
+ MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0),
+ MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0),
+ MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 0),
+ MSG_MAP(EnableGfxOff, PPSMC_MSG_EnableGfxOff, 0),
+ MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisableGfxOff, 0),
+ MSG_MAP(PowerDownIspByTile, PPSMC_MSG_PowerDownIspByTile, 0),
+ MSG_MAP(PowerUpIspByTile, PPSMC_MSG_PowerUpIspByTile, 0),
+ MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0),
+ MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0),
+ MSG_MAP(RlcPowerNotify, PPSMC_MSG_RlcPowerNotify, 0),
+ MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 0),
+ MSG_MAP(SetSoftMinGfxclk, PPSMC_MSG_SetSoftMinGfxclk, 0),
+ MSG_MAP(ActiveProcessNotify, PPSMC_MSG_ActiveProcessNotify, 0),
+ MSG_MAP(SetHardMinIspiclkByFreq, PPSMC_MSG_SetHardMinIspiclkByFreq, 0),
+ MSG_MAP(SetHardMinIspxclkByFreq, PPSMC_MSG_SetHardMinIspxclkByFreq, 0),
+ MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0),
+ MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0),
+ MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0),
+ MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0),
+ MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 0),
+ MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0),
+ MSG_MAP(Spare1, PPSMC_MSG_spare1, 0),
+ MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 0),
+ MSG_MAP(SetSoftMinFclk, PPSMC_MSG_SetSoftMinFclk, 0),
+ MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 0),
+ MSG_MAP(EnablePostCode, PPSMC_MSG_EnablePostCode, 0),
+ MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 0),
+ MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 0),
+ MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 0),
+ MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 0),
+ MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 0),
+ MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 0),
+ MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 0),
+ MSG_MAP(Spare2, PPSMC_MSG_spare2, 0),
+ MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 0),
+ MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0),
+ MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0),
+ MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 0),
+ MSG_MAP(SetSoftMinSocclkByFreq, PPSMC_MSG_SetSoftMinSocclkByFreq, 0),
+ MSG_MAP(PowerUpCvip, PPSMC_MSG_PowerUpCvip, 0),
+ MSG_MAP(PowerDownCvip, PPSMC_MSG_PowerDownCvip, 0),
+ MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0),
+ MSG_MAP(GetThermalLimit, PPSMC_MSG_GetThermalLimit, 0),
+ MSG_MAP(GetCurrentTemperature, PPSMC_MSG_GetCurrentTemperature, 0),
+ MSG_MAP(GetCurrentPower, PPSMC_MSG_GetCurrentPower, 0),
+ MSG_MAP(GetCurrentVoltage, PPSMC_MSG_GetCurrentVoltage, 0),
+ MSG_MAP(GetCurrentCurrent, PPSMC_MSG_GetCurrentCurrent, 0),
+ MSG_MAP(GetAverageCpuActivity, PPSMC_MSG_GetAverageCpuActivity, 0),
+ MSG_MAP(GetAverageGfxActivity, PPSMC_MSG_GetAverageGfxActivity, 0),
+ MSG_MAP(GetAveragePower, PPSMC_MSG_GetAveragePower, 0),
+ MSG_MAP(GetAverageTemperature, PPSMC_MSG_GetAverageTemperature, 0),
+ MSG_MAP(SetAveragePowerTimeConstant, PPSMC_MSG_SetAveragePowerTimeConstant, 0),
+ MSG_MAP(SetAverageActivityTimeConstant, PPSMC_MSG_SetAverageActivityTimeConstant, 0),
+ MSG_MAP(SetAverageTemperatureTimeConstant, PPSMC_MSG_SetAverageTemperatureTimeConstant, 0),
+ MSG_MAP(SetMitigationEndHysteresis, PPSMC_MSG_SetMitigationEndHysteresis, 0),
+ MSG_MAP(GetCurrentFreq, PPSMC_MSG_GetCurrentFreq, 0),
+ MSG_MAP(SetReducedPptLimit, PPSMC_MSG_SetReducedPptLimit, 0),
+ MSG_MAP(SetReducedThermalLimit, PPSMC_MSG_SetReducedThermalLimit, 0),
+ MSG_MAP(DramLogSetDramAddr, PPSMC_MSG_DramLogSetDramAddr, 0),
+ MSG_MAP(StartDramLogging, PPSMC_MSG_StartDramLogging, 0),
+ MSG_MAP(StopDramLogging, PPSMC_MSG_StopDramLogging, 0),
+ MSG_MAP(SetSoftMinCclk, PPSMC_MSG_SetSoftMinCclk, 0),
+ MSG_MAP(SetSoftMaxCclk, PPSMC_MSG_SetSoftMaxCclk, 0),
+};
+
+static struct cmn2asic_mapping vangogh_feature_mask_map[SMU_FEATURE_COUNT] = {
+ FEA_MAP(PPT),
+ FEA_MAP(TDC),
+ FEA_MAP(THERMAL),
+ FEA_MAP(DS_GFXCLK),
+ FEA_MAP(DS_SOCCLK),
+ FEA_MAP(DS_LCLK),
+ FEA_MAP(DS_FCLK),
+ FEA_MAP(DS_MP1CLK),
+ FEA_MAP(DS_MP0CLK),
+ FEA_MAP(ATHUB_PG),
+ FEA_MAP(CCLK_DPM),
+ FEA_MAP(FAN_CONTROLLER),
+ FEA_MAP(ULV),
+ FEA_MAP(VCN_DPM),
+ FEA_MAP(LCLK_DPM),
+ FEA_MAP(SHUBCLK_DPM),
+ FEA_MAP(DCFCLK_DPM),
+ FEA_MAP(DS_DCFCLK),
+ FEA_MAP(S0I2),
+ FEA_MAP(SMU_LOW_POWER),
+ FEA_MAP(GFX_DEM),
+ FEA_MAP(PSI),
+ FEA_MAP(PROCHOT),
+ FEA_MAP(CPUOFF),
+ FEA_MAP(STAPM),
+ FEA_MAP(S0I3),
+ FEA_MAP(DF_CSTATES),
+ FEA_MAP(PERF_LIMIT),
+ FEA_MAP(CORE_DLDO),
+ FEA_MAP(RSMU_LOW_POWER),
+ FEA_MAP(SMN_LOW_POWER),
+ FEA_MAP(THM_LOW_POWER),
+ FEA_MAP(SMUIO_LOW_POWER),
+ FEA_MAP(MP1_LOW_POWER),
+ FEA_MAP(DS_VCN),
+ FEA_MAP(CPPC),
+ FEA_MAP(OS_CSTATES),
+ FEA_MAP(ISP_DPM),
+ FEA_MAP(A55_DPM),
+ FEA_MAP(CVIP_DSP_DPM),
+ FEA_MAP(MSMU_LOW_POWER),
+};
+
+static struct cmn2asic_mapping vangogh_table_map[SMU_TABLE_COUNT] = {
+ TAB_MAP_VALID(WATERMARKS),
+ TAB_MAP_VALID(SMU_METRICS),
+ TAB_MAP_VALID(CUSTOM_DPM),
+ TAB_MAP_VALID(DPMCLOCKS),
+};
+
+static int vangogh_tables_init(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct smu_table *tables = smu_table->tables;
+
+ SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, sizeof(DpmActivityMonitorCoeffExt_t),
+ PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+ smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL);
+ if (!smu_table->metrics_table)
+ goto err0_out;
+ smu_table->metrics_time = 0;
+
+ smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0);
+ smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
+ if (!smu_table->gpu_metrics_table)
+ goto err1_out;
+
+ smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL);
+ if (!smu_table->watermarks_table)
+ goto err2_out;
+
+ smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
+ if (!smu_table->clocks_table)
+ goto err3_out;
+
+ return 0;
+
+err3_out:
+ kfree(smu_table->clocks_table);
+err2_out:
+ kfree(smu_table->gpu_metrics_table);
+err1_out:
+ kfree(smu_table->metrics_table);
+err0_out:
+ return -ENOMEM;
+}
+
+static int vangogh_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
+ int ret = 0;
+
+ mutex_lock(&smu->metrics_lock);
+
+ ret = smu_cmn_get_metrics_table_locked(smu,
+ NULL,
+ false);
+ if (ret) {
+ mutex_unlock(&smu->metrics_lock);
+ return ret;
+ }
+
+ switch (member) {
+ case METRICS_AVERAGE_GFXCLK:
+ *value = metrics->GfxclkFrequency;
+ break;
+ case METRICS_AVERAGE_SOCCLK:
+ *value = metrics->SocclkFrequency;
+ break;
+ case METRICS_AVERAGE_UCLK:
+ *value = metrics->MemclkFrequency;
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = metrics->GfxActivity / 100;
+ break;
+ case METRICS_AVERAGE_VCNACTIVITY:
+ *value = metrics->UvdActivity;
+ break;
+ case METRICS_AVERAGE_SOCKETPOWER:
+ *value = metrics->CurrentSocketPower;
+ break;
+ case METRICS_TEMPERATURE_EDGE:
+ *value = metrics->GfxTemperature / 100 *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = metrics->SocTemperature / 100 *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_THROTTLER_STATUS:
+ *value = metrics->ThrottlerStatus;
+ break;
+ case METRICS_VOLTAGE_VDDGFX:
+ *value = metrics->Voltage[2];
+ break;
+ case METRICS_VOLTAGE_VDDSOC:
+ *value = metrics->Voltage[1];
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ mutex_unlock(&smu->metrics_lock);
+
+ return ret;
+}
+
+static int vangogh_allocate_dpm_context(struct smu_context *smu)
+{
+ struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+
+ smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context),
+ GFP_KERNEL);
+ if (!smu_dpm->dpm_context)
+ return -ENOMEM;
+
+ smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context);
+
+ return 0;
+}
+
+static int vangogh_init_smc_tables(struct smu_context *smu)
+{
+ int ret = 0;
+
+ ret = vangogh_tables_init(smu);
+ if (ret)
+ return ret;
+
+ ret = vangogh_allocate_dpm_context(smu);
+ if (ret)
+ return ret;
+
+ return smu_v11_0_init_smc_tables(smu);
+}
+
+static int vangogh_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
+{
+ int ret = 0;
+
+ if (enable) {
+ /* vcn dpm on is a prerequisite for vcn power gate messages */
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL);
+ if (ret)
+ return ret;
+ }
+ } else {
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
+{
+ int ret = 0;
+
+ if (enable) {
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL);
+ if (ret)
+ return ret;
+ }
+ } else {
+ if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int vangogh_get_allowed_feature_mask(struct smu_context *smu,
+ uint32_t *feature_mask,
+ uint32_t num)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ if (num > 2)
+ return -EINVAL;
+
+ memset(feature_mask, 0, sizeof(uint32_t) * num);
+
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_DPM_BIT)
+ | FEATURE_MASK(FEATURE_MP0CLK_DPM_BIT)
+ | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT)
+ | FEATURE_MASK(FEATURE_PPT_BIT)
+ | FEATURE_MASK(FEATURE_TDC_BIT)
+ | FEATURE_MASK(FEATURE_FAN_CONTROLLER_BIT)
+ | FEATURE_MASK(FEATURE_DS_LCLK_BIT)
+ | FEATURE_MASK(FEATURE_DS_DCFCLK_BIT);
+
+ if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_SOCCLK_DPM_BIT);
+
+ if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DCFCLK_DPM_BIT);
+
+ if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB)
+ *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT);
+
+ return 0;
+}
+
+static bool vangogh_is_dpm_running(struct smu_context *smu)
+{
+ int ret = 0;
+ uint32_t feature_mask[2];
+ uint64_t feature_enabled;
+
+ ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2);
+
+ if (ret)
+ return false;
+
+ feature_enabled = (unsigned long)((uint64_t)feature_mask[0] |
+ ((uint64_t)feature_mask[1] << 32));
+
+ return !!(feature_enabled & SMC_DPM_FEATURE);
+}
+
+static int vangogh_print_fine_grain_clk(struct smu_context *smu,
+ enum smu_clk_type clk_type, char *buf)
+{
+ int size = 0;
+
+ switch (clk_type) {
+ case SMU_OD_SCLK:
+ if (smu->od_enabled) {
+ size = sprintf(buf, "%s:\n", "OD_SCLK");
+ size += sprintf(buf + size, "0: %10uMhz\n",
+ (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
+ size += sprintf(buf + size, "1: %10uMhz\n",
+ (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
+ }
+ break;
+ case SMU_OD_RANGE:
+ if (smu->od_enabled) {
+ size = sprintf(buf, "%s:\n", "OD_RANGE");
+ size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+ smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return size;
+}
+
+static int vangogh_read_sensor(struct smu_context *smu,
+ enum amd_pp_sensors sensor,
+ void *data, uint32_t *size)
+{
+ int ret = 0;
+
+ if (!data || !size)
+ return -EINVAL;
+
+ mutex_lock(&smu->sensor_lock);
+ switch (sensor) {
+ case AMDGPU_PP_SENSOR_GPU_LOAD:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GPU_POWER:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_MCLK:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_UCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_GFX_SCLK:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
+ *(uint32_t *)data *= 100;
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDGFX:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDGFX,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_VDDNB:
+ ret = vangogh_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDSOC,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ mutex_unlock(&smu->sensor_lock);
+
+ return ret;
+}
+
+static int vangogh_set_watermarks_table(struct smu_context *smu,
+ struct pp_smu_wm_range_sets *clock_ranges)
+{
+ int i;
+ int ret = 0;
+ Watermarks_t *table = smu->smu_table.watermarks_table;
+
+ if (!table || !clock_ranges)
+ return -EINVAL;
+
+ if (clock_ranges) {
+ if (clock_ranges->num_reader_wm_sets > NUM_WM_RANGES ||
+ clock_ranges->num_writer_wm_sets > NUM_WM_RANGES)
+ return -EINVAL;
+
+ for (i = 0; i < clock_ranges->num_reader_wm_sets; i++) {
+ table->WatermarkRow[WM_DCFCLK][i].MinClock =
+ clock_ranges->reader_wm_sets[i].min_drain_clk_mhz;
+ table->WatermarkRow[WM_DCFCLK][i].MaxClock =
+ clock_ranges->reader_wm_sets[i].max_drain_clk_mhz;
+ table->WatermarkRow[WM_DCFCLK][i].MinMclk =
+ clock_ranges->reader_wm_sets[i].min_fill_clk_mhz;
+ table->WatermarkRow[WM_DCFCLK][i].MaxMclk =
+ clock_ranges->reader_wm_sets[i].max_fill_clk_mhz;
+
+ table->WatermarkRow[WM_DCFCLK][i].WmSetting =
+ clock_ranges->reader_wm_sets[i].wm_inst;
+ }
+
+ for (i = 0; i < clock_ranges->num_writer_wm_sets; i++) {
+ table->WatermarkRow[WM_SOCCLK][i].MinClock =
+ clock_ranges->writer_wm_sets[i].min_fill_clk_mhz;
+ table->WatermarkRow[WM_SOCCLK][i].MaxClock =
+ clock_ranges->writer_wm_sets[i].max_fill_clk_mhz;
+ table->WatermarkRow[WM_SOCCLK][i].MinMclk =
+ clock_ranges->writer_wm_sets[i].min_drain_clk_mhz;
+ table->WatermarkRow[WM_SOCCLK][i].MaxMclk =
+ clock_ranges->writer_wm_sets[i].max_drain_clk_mhz;
+
+ table->WatermarkRow[WM_SOCCLK][i].WmSetting =
+ clock_ranges->writer_wm_sets[i].wm_inst;
+ }
+
+ smu->watermarks_bitmap |= WATERMARKS_EXIST;
+ }
+
+ /* pass data to smu controller */
+ if ((smu->watermarks_bitmap & WATERMARKS_EXIST) &&
+ !(smu->watermarks_bitmap & WATERMARKS_LOADED)) {
+ ret = smu_cmn_write_watermarks_table(smu);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to update WMTABLE!");
+ return ret;
+ }
+ smu->watermarks_bitmap |= WATERMARKS_LOADED;
+ }
+
+ return 0;
+}
+
+static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
+ void **table)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+ struct gpu_metrics_v2_0 *gpu_metrics =
+ (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table;
+ SmuMetrics_t metrics;
+ int ret = 0;
+
+ ret = smu_cmn_get_metrics_table(smu, &metrics, true);
+ if (ret)
+ return ret;
+
+ smu_v11_0_init_gpu_metrics_v2_0(gpu_metrics);
+
+ gpu_metrics->temperature_gfx = metrics.GfxTemperature;
+ gpu_metrics->temperature_soc = metrics.SocTemperature;
+ memcpy(&gpu_metrics->temperature_core[0],
+ &metrics.CoreTemperature[0],
+ sizeof(uint16_t) * 8);
+ gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0];
+ gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1];
+
+ gpu_metrics->average_gfx_activity = metrics.GfxActivity;
+ gpu_metrics->average_mm_activity = metrics.UvdActivity;
+
+ gpu_metrics->average_socket_power = metrics.CurrentSocketPower;
+ gpu_metrics->average_cpu_power = metrics.Power[0];
+ gpu_metrics->average_soc_power = metrics.Power[1];
+ memcpy(&gpu_metrics->average_core_power[0],
+ &metrics.CorePower[0],
+ sizeof(uint16_t) * 8);
+
+ gpu_metrics->average_gfxclk_frequency = metrics.GfxclkFrequency;
+ gpu_metrics->average_socclk_frequency = metrics.SocclkFrequency;
+ gpu_metrics->average_fclk_frequency = metrics.MemclkFrequency;
+ gpu_metrics->average_vclk_frequency = metrics.VclkFrequency;
+
+ memcpy(&gpu_metrics->current_coreclk[0],
+ &metrics.CoreFrequency[0],
+ sizeof(uint16_t) * 8);
+ gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0];
+ gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1];
+
+ gpu_metrics->throttle_status = metrics.ThrottlerStatus;
+
+ *table = (void *)gpu_metrics;
+
+ return sizeof(struct gpu_metrics_v2_0);
+}
+
+static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
+ long input[], uint32_t size)
+{
+ int ret = 0;
+
+ if (!smu->od_enabled) {
+ dev_warn(smu->adev->dev, "Fine grain is not enabled!\n");
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case PP_OD_EDIT_SCLK_VDDC_TABLE:
+ if (size != 2) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ }
+
+ if (input[0] == 0) {
+ if (input[1] < smu->gfx_default_hard_min_freq) {
+ dev_warn(smu->adev->dev, "Fine grain setting minimum sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
+ input[1], smu->gfx_default_hard_min_freq);
+ return -EINVAL;
+ }
+ smu->gfx_actual_hard_min_freq = input[1];
+ } else if (input[0] == 1) {
+ if (input[1] > smu->gfx_default_soft_max_freq) {
+ dev_warn(smu->adev->dev, "Fine grain setting maximum sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
+ input[1], smu->gfx_default_soft_max_freq);
+ return -EINVAL;
+ }
+ smu->gfx_actual_soft_max_freq = input[1];
+ } else {
+ return -EINVAL;
+ }
+ break;
+ case PP_OD_RESTORE_DEFAULT_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ } else {
+ smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
+ smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
+ smu->gfx_actual_hard_min_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Restore the default hard min sclk failed!");
+ return ret;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ smu->gfx_actual_soft_max_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Restore the default soft max sclk failed!");
+ return ret;
+ }
+ }
+ break;
+ case PP_OD_COMMIT_DPM_TABLE:
+ if (size != 0) {
+ dev_err(smu->adev->dev, "Input parameter number not correct\n");
+ return -EINVAL;
+ } else {
+ if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
+ dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
+ smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq);
+ return -EINVAL;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
+ smu->gfx_actual_hard_min_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Set hard min sclk failed!");
+ return ret;
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+ smu->gfx_actual_soft_max_freq, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Set soft max sclk failed!");
+ return ret;
+ }
+ }
+ break;
+ default:
+ return -ENOSYS;
+ }
+
+ return ret;
+}
+
+static int vangogh_set_default_dpm_tables(struct smu_context *smu)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
+}
+
+static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
+{
+ DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+
+ smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
+ smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
+ smu->gfx_actual_hard_min_freq = 0;
+ smu->gfx_actual_soft_max_freq = 0;
+
+ return 0;
+}
+
+static int vangogh_system_features_control(struct smu_context *smu, bool en)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ if (adev->pm.fw_version >= 0x43f1700)
+ return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RlcPowerNotify,
+ en ? RLC_STATUS_NORMAL : RLC_STATUS_OFF, NULL);
+ else
+ return 0;
+}
+
+static const struct pptable_funcs vangogh_ppt_funcs = {
+
+ .check_fw_status = smu_v11_0_check_fw_status,
+ .check_fw_version = smu_v11_0_check_fw_version,
+ .init_smc_tables = vangogh_init_smc_tables,
+ .fini_smc_tables = smu_v11_0_fini_smc_tables,
+ .init_power = smu_v11_0_init_power,
+ .fini_power = smu_v11_0_fini_power,
+ .register_irq_handler = smu_v11_0_register_irq_handler,
+ .get_allowed_feature_mask = vangogh_get_allowed_feature_mask,
+ .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location,
+ .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param,
+ .send_smc_msg = smu_cmn_send_smc_msg,
+ .dpm_set_vcn_enable = vangogh_dpm_set_vcn_enable,
+ .dpm_set_jpeg_enable = vangogh_dpm_set_jpeg_enable,
+ .is_dpm_running = vangogh_is_dpm_running,
+ .read_sensor = vangogh_read_sensor,
+ .get_enabled_mask = smu_cmn_get_enabled_32_bits_mask,
+ .get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
+ .set_watermarks_table = vangogh_set_watermarks_table,
+ .set_driver_table_location = smu_v11_0_set_driver_table_location,
+ .interrupt_work = smu_v11_0_interrupt_work,
+ .get_gpu_metrics = vangogh_get_gpu_metrics,
+ .od_edit_dpm_table = vangogh_od_edit_dpm_table,
+ .print_clk_levels = vangogh_print_fine_grain_clk,
+ .set_default_dpm_table = vangogh_set_default_dpm_tables,
+ .set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
+ .system_features_control = vangogh_system_features_control,
+};
+
+void vangogh_set_ppt_funcs(struct smu_context *smu)
+{
+ smu->ppt_funcs = &vangogh_ppt_funcs;
+ smu->message_map = vangogh_message_map;
+ smu->feature_map = vangogh_feature_mask_map;
+ smu->table_map = vangogh_table_map;
+ smu->is_apu = true;
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.h
new file mode 100644
index 000000000000..eab455493076
--- /dev/null
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __VANGOGH_PPT_H__
+#define __VANGOGH_PPT_H__
+
+
+extern void vangogh_set_ppt_funcs(struct smu_context *smu);
+
+/* UMD PState Vangogh Msg Parameters in MHz */
+#define VANGOGH_UMD_PSTATE_GFXCLK 700
+#define VANGOGH_UMD_PSTATE_SOCCLK 678
+#define VANGOGH_UMD_PSTATE_FCLK 800
+
+/* RLC Power Status */
+#define RLC_STATUS_OFF 0
+#define RLC_STATUS_NORMAL 1
+
+#endif
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index 66c1026489be..dc75db8af371 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -170,7 +170,7 @@ err0_out:
return -ENOMEM;
}
-/**
+/*
* This interface just for getting uclk ultimate freq and should't introduce
* other likewise function result in overmuch callback.
*/
@@ -492,28 +492,6 @@ static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable)
return ret;
}
-static int renoir_get_current_clk_freq_by_table(struct smu_context *smu,
- enum smu_clk_type clk_type,
- uint32_t *value)
-{
- int ret = 0, clk_id = 0;
- SmuMetrics_t metrics;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- clk_id = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_CLK,
- clk_type);
- if (clk_id < 0)
- return clk_id;
-
- *value = metrics.ClockFrequency[clk_id];
-
- return ret;
-}
-
static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest)
{
int ret = 0, i = 0;
@@ -574,89 +552,7 @@ static int renoir_unforce_dpm_levels(struct smu_context *smu) {
return ret;
}
-static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value)
-{
- int ret = 0;
- SmuMetrics_t metrics;
-
- if (!value)
- return -EINVAL;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- *value = (metrics.GfxTemperature / 100) *
- SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
-
- return 0;
-}
-
-static int renoir_get_current_activity_percent(struct smu_context *smu,
- enum amd_pp_sensors sensor,
- uint32_t *value)
-{
- int ret = 0;
- SmuMetrics_t metrics;
-
- if (!value)
- return -EINVAL;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- switch (sensor) {
- case AMDGPU_PP_SENSOR_GPU_LOAD:
- *value = metrics.AverageGfxActivity / 100;
- break;
- default:
- dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int renoir_get_vddc(struct smu_context *smu, uint32_t *value,
- unsigned int index)
-{
- int ret = 0;
- SmuMetrics_t metrics;
-
- if (index >= 2)
- return -EINVAL;
-
- if (!value)
- return -EINVAL;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- *value = metrics.Voltage[index];
-
- return 0;
-}
-
-static int renoir_get_power(struct smu_context *smu, uint32_t *value)
-{
- int ret = 0;
- SmuMetrics_t metrics;
-
- if (!value)
- return -EINVAL;
-
- ret = smu_cmn_get_metrics_table(smu, &metrics, false);
- if (ret)
- return ret;
-
- *value = metrics.CurrentSocketPower << 8;
-
- return 0;
-}
-
-/**
+/*
* This interface get dpm clock table for dc
*/
static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table)
@@ -1011,6 +907,71 @@ static int renoir_get_power_profile_mode(struct smu_context *smu,
return size;
}
+static int renoir_get_smu_metrics_data(struct smu_context *smu,
+ MetricsMember_t member,
+ uint32_t *value)
+{
+ struct smu_table_context *smu_table = &smu->smu_table;
+
+ SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table;
+ int ret = 0;
+
+ mutex_lock(&smu->metrics_lock);
+
+ ret = smu_cmn_get_metrics_table_locked(smu,
+ NULL,
+ false);
+ if (ret) {
+ mutex_unlock(&smu->metrics_lock);
+ return ret;
+ }
+
+ switch (member) {
+ case METRICS_AVERAGE_GFXCLK:
+ *value = metrics->ClockFrequency[CLOCK_GFXCLK];
+ break;
+ case METRICS_AVERAGE_SOCCLK:
+ *value = metrics->ClockFrequency[CLOCK_SOCCLK];
+ break;
+ case METRICS_AVERAGE_UCLK:
+ *value = metrics->ClockFrequency[CLOCK_FCLK];
+ break;
+ case METRICS_AVERAGE_GFXACTIVITY:
+ *value = metrics->AverageGfxActivity / 100;
+ break;
+ case METRICS_AVERAGE_VCNACTIVITY:
+ *value = metrics->AverageUvdActivity / 100;
+ break;
+ case METRICS_AVERAGE_SOCKETPOWER:
+ *value = metrics->CurrentSocketPower << 8;
+ break;
+ case METRICS_TEMPERATURE_EDGE:
+ *value = (metrics->GfxTemperature / 100) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_TEMPERATURE_HOTSPOT:
+ *value = (metrics->SocTemperature / 100) *
+ SMU_TEMPERATURE_UNITS_PER_CENTIGRADES;
+ break;
+ case METRICS_THROTTLER_STATUS:
+ *value = metrics->ThrottlerStatus;
+ break;
+ case METRICS_VOLTAGE_VDDGFX:
+ *value = metrics->Voltage[0];
+ break;
+ case METRICS_VOLTAGE_VDDSOC:
+ *value = metrics->Voltage[1];
+ break;
+ default:
+ *value = UINT_MAX;
+ break;
+ }
+
+ mutex_unlock(&smu->metrics_lock);
+
+ return ret;
+}
+
static int renoir_read_sensor(struct smu_context *smu,
enum amd_pp_sensors sensor,
void *data, uint32_t *size)
@@ -1023,33 +984,53 @@ static int renoir_read_sensor(struct smu_context *smu,
mutex_lock(&smu->sensor_lock);
switch (sensor) {
case AMDGPU_PP_SENSOR_GPU_LOAD:
- ret = renoir_get_current_activity_percent(smu, sensor, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXACTIVITY,
+ (uint32_t *)data);
+ *size = 4;
+ break;
+ case AMDGPU_PP_SENSOR_EDGE_TEMP:
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_EDGE,
+ (uint32_t *)data);
*size = 4;
break;
- case AMDGPU_PP_SENSOR_GPU_TEMP:
- ret = renoir_get_gpu_temperature(smu, (uint32_t *)data);
+ case AMDGPU_PP_SENSOR_HOTSPOT_TEMP:
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_TEMPERATURE_HOTSPOT,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_MCLK:
- ret = renoir_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_UCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_GFX_SCLK:
- ret = renoir_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_GFXCLK,
+ (uint32_t *)data);
*(uint32_t *)data *= 100;
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDGFX:
- ret = renoir_get_vddc(smu, (uint32_t *)data, 0);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDGFX,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_VDDNB:
- ret = renoir_get_vddc(smu, (uint32_t *)data, 1);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_VOLTAGE_VDDSOC,
+ (uint32_t *)data);
*size = 4;
break;
case AMDGPU_PP_SENSOR_GPU_POWER:
- ret = renoir_get_power(smu, (uint32_t *)data);
+ ret = renoir_get_smu_metrics_data(smu,
+ METRICS_AVERAGE_SOCKETPOWER,
+ (uint32_t *)data);
*size = 4;
break;
default:
@@ -1136,6 +1117,12 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu,
return sizeof(struct gpu_metrics_v2_0);
}
+static int renoir_gfx_state_change_set(struct smu_context *smu, uint32_t state)
+{
+
+ return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GpuChangeState, state, NULL);
+}
+
static const struct pptable_funcs renoir_ppt_funcs = {
.set_power_state = NULL,
.print_clk_levels = renoir_print_clk_levels,
@@ -1171,6 +1158,7 @@ static const struct pptable_funcs renoir_ppt_funcs = {
.get_pp_feature_mask = smu_cmn_get_pp_feature_mask,
.set_pp_feature_mask = smu_cmn_set_pp_feature_mask,
.get_gpu_metrics = renoir_get_gpu_metrics,
+ .gfx_state_change_set = renoir_gfx_state_change_set,
};
void renoir_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
index 660f403d5770..522d55004655 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
@@ -71,6 +71,7 @@ int smu_v12_0_check_fw_status(struct smu_context *smu)
int smu_v12_0_check_fw_version(struct smu_context *smu)
{
+ struct amdgpu_device *adev = smu->adev;
uint32_t if_version = 0xff, smu_version = 0xff;
uint16_t smu_major;
uint8_t smu_minor, smu_debug;
@@ -83,6 +84,8 @@ int smu_v12_0_check_fw_version(struct smu_context *smu)
smu_major = (smu_version >> 16) & 0xffff;
smu_minor = (smu_version >> 8) & 0xff;
smu_debug = (smu_version >> 0) & 0xff;
+ if (smu->is_apu)
+ adev->pm.fw_version = smu_version;
/*
* 1. if_version mismatch is not critical as our fw is designed
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index 92b2ea4c197b..f8260769061c 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -346,6 +346,43 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu,
return ret;
}
+int smu_cmn_get_enabled_32_bits_mask(struct smu_context *smu,
+ uint32_t *feature_mask,
+ uint32_t num)
+{
+ uint32_t feature_mask_en_low = 0;
+ uint32_t feature_mask_en_high = 0;
+ struct smu_feature *feature = &smu->smu_feature;
+ int ret = 0;
+
+ if (!feature_mask || num < 2)
+ return -EINVAL;
+
+ if (bitmap_empty(feature->enabled, feature->feature_num)) {
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetEnabledSmuFeatures, 0,
+ &feature_mask_en_low);
+
+ if (ret)
+ return ret;
+
+ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetEnabledSmuFeatures, 1,
+ &feature_mask_en_high);
+
+ if (ret)
+ return ret;
+
+ feature_mask[0] = feature_mask_en_low;
+ feature_mask[1] = feature_mask_en_high;
+
+ } else {
+ bitmap_copy((unsigned long *)feature_mask, feature->enabled,
+ feature->feature_num);
+ }
+
+ return ret;
+
+}
+
int smu_cmn_feature_update_enable_state(struct smu_context *smu,
uint64_t feature_mask,
bool enabled)
@@ -437,11 +474,19 @@ size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu,
size_t size = 0;
int ret = 0, i;
- ret = smu_cmn_get_enabled_mask(smu,
- feature_mask,
- 2);
- if (ret)
- return 0;
+ if (!smu->is_apu) {
+ ret = smu_cmn_get_enabled_mask(smu,
+ feature_mask,
+ 2);
+ if (ret)
+ return 0;
+ } else {
+ ret = smu_cmn_get_enabled_32_bits_mask(smu,
+ feature_mask,
+ 2);
+ if (ret)
+ return 0;
+ }
size = sprintf(buf + size, "features high: 0x%08x low: 0x%08x\n",
feature_mask[1], feature_mask[0]);
@@ -610,7 +655,7 @@ int smu_cmn_update_table(struct smu_context *smu,
return ret;
if (!drv2smu) {
- amdgpu_asic_flush_hdp(adev, NULL);
+ amdgpu_asic_invalidate_hdp(adev, NULL);
memcpy(table_data, table->cpu_addr, table_size);
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index ab577be23c15..01e825d83d8d 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -52,6 +52,10 @@ int smu_cmn_get_enabled_mask(struct smu_context *smu,
uint32_t *feature_mask,
uint32_t num);
+int smu_cmn_get_enabled_32_bits_mask(struct smu_context *smu,
+ uint32_t *feature_mask,
+ uint32_t num);
+
int smu_cmn_feature_update_enable_state(struct smu_context *smu,
uint64_t feature_mask,
bool enabled);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
index c5adbe46ba0d..68d9464ababc 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
@@ -42,7 +42,6 @@
#define smu_check_fw_version(smu) smu_ppt_funcs(check_fw_version, 0, smu)
#define smu_write_pptable(smu) smu_ppt_funcs(write_pptable, 0, smu)
#define smu_set_min_dcef_deep_sleep(smu, clk) smu_ppt_funcs(set_min_dcef_deep_sleep, 0, smu, clk)
-#define smu_set_active_display_count(smu, count) smu_ppt_funcs(set_active_display_count, 0, smu, count)
#define smu_set_driver_table_location(smu) smu_ppt_funcs(set_driver_table_location, 0, smu)
#define smu_set_tool_table_location(smu) smu_ppt_funcs(set_tool_table_location, 0, smu)
#define smu_notify_memory_pool_location(smu) smu_ppt_funcs(notify_memory_pool_location, 0, smu)
@@ -62,7 +61,6 @@
#define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu)
#define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu)
#define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu)
-#define smu_set_default_od8_settings(smu) smu_ppt_funcs(set_default_od8_settings, 0, smu)
#define smu_enable_thermal_alert(smu) smu_ppt_funcs(enable_thermal_alert, 0, smu)
#define smu_disable_thermal_alert(smu) smu_ppt_funcs(disable_thermal_alert, 0, smu)
#define smu_smc_read_sensor(smu, sensor, data, size) smu_ppt_funcs(read_sensor, -EINVAL, smu, sensor, data, size)
@@ -70,13 +68,8 @@
#define smu_display_config_changed(smu) smu_ppt_funcs(display_config_changed, 0 , smu)
#define smu_apply_clocks_adjust_rules(smu) smu_ppt_funcs(apply_clocks_adjust_rules, 0, smu)
#define smu_notify_smc_display_config(smu) smu_ppt_funcs(notify_smc_display_config, 0, smu)
-#define smu_set_cpu_power_state(smu) smu_ppt_funcs(set_cpu_power_state, 0, smu)
#define smu_run_btc(smu) smu_ppt_funcs(run_btc, 0, smu)
#define smu_get_allowed_feature_mask(smu, feature_mask, num) smu_ppt_funcs(get_allowed_feature_mask, 0, smu, feature_mask, num)
-#define smu_store_cc6_data(smu, st, cc6_dis, pst_dis, pst_sw_dis) smu_ppt_funcs(store_cc6_data, 0, smu, st, cc6_dis, pst_dis, pst_sw_dis)
-#define smu_get_dal_power_level(smu, clocks) smu_ppt_funcs(get_dal_power_level, 0, smu, clocks)
-#define smu_get_perf_level(smu, designation, level) smu_ppt_funcs(get_perf_level, 0, smu, designation, level)
-#define smu_get_current_shallow_sleep_clocks(smu, clocks) smu_ppt_funcs(get_current_shallow_sleep_clocks, 0, smu, clocks)
#define smu_set_watermarks_table(smu, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, clock_ranges)
#define smu_thermal_temperature_range_update(smu, range, rw) smu_ppt_funcs(thermal_temperature_range_update, 0, smu, range, rw)
#define smu_register_irq_handler(smu) smu_ppt_funcs(register_irq_handler, 0, smu)
@@ -96,6 +89,8 @@
#define smu_deep_sleep_control(smu, enablement) smu_ppt_funcs(deep_sleep_control, 0, smu, enablement)
#define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu)
#define smu_post_init(smu) smu_ppt_funcs(post_init, 0, smu)
+#define smu_gpo_control(smu, enablement) smu_ppt_funcs(gpo_control, 0, smu, enablement)
+#define smu_set_fine_grain_gfx_freq_parameters(smu) smu_ppt_funcs(set_fine_grain_gfx_freq_parameters, 0, smu)
#endif
#endif