From 00267b5af20fbf9d573ebac9f6d9943f86909487 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 21 May 2018 10:16:41 +0800 Subject: [PATCH 5135/5725] drm/amd/powerplay: initialize vega20 overdrive settings The initialized overdrive settings are taken from vbios and SMU( by PPSMC_MSG_TransferTableSmu2Dram). Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 293 +++++++++++++++++++-- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h | 53 +++- .../amd/powerplay/hwmgr/vega20_processpptables.c | 103 ++++++-- .../gpu/drm/amd/powerplay/inc/hardwaremanager.h | 2 + drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 5 files changed, 403 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 182f25c..51bc05d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -103,7 +103,7 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr) data->registry_data.quick_transition_support = 0; data->registry_data.zrpm_start_temp = 0xffff; data->registry_data.zrpm_stop_temp = 0xffff; - data->registry_data.odn_feature_enable = 1; + data->registry_data.od8_feature_enable = 1; data->registry_data.disable_water_mark = 0; data->registry_data.disable_pp_tuning = 0; data->registry_data.disable_xlpp_tuning = 0; @@ -150,15 +150,9 @@ static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr) phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UnTabledHardwareInterface); - if (data->registry_data.odn_feature_enable) + if (data->registry_data.od8_feature_enable) phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinACSupport); - else { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6inACSupport); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinACSupport); - } + PHM_PlatformCaps_OD8inACSupport); phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ActivityReporting); @@ -166,15 +160,9 @@ static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr) PHM_PlatformCaps_FanSpeedInTableIsRPM); if (data->registry_data.od_state_in_dc_support) { - if (data->registry_data.odn_feature_enable) + if (data->registry_data.od8_feature_enable) phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinDCSupport); - else { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6inDCSupport); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinDCSupport); - } + PHM_PlatformCaps_OD8inDCSupport); } if (data->registry_data.thermal_support && @@ -840,9 +828,276 @@ static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) return 0; } -static int vega20_odn_initialize_default_settings( +static int vega20_od8_set_feature_capabilities( + struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_settings *od_settings = &(data->od8_settings); + + od_settings->overdrive8_capabilities = 0; + + if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { + if (pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_GFXCLKFMAX] > 0 && + pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_GFXCLKFMAX] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_GFXCLKFMIN] > 0 && + pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_GFXCLKFMIN] > 0) + od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS; + + if (pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P1] > 0 && + pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P2] > 0 && + pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P3] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P1] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P2] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P3] > 0 && + pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1] > 0 && + pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2] > 0 && + pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3] > 0) + od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE; + } + + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + if (pptable_information->od_settings_min[ATOM_VEGA20_ODSETTING_UCLKFMAX] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_UCLKFMAX] > 0) + od_settings->overdrive8_capabilities |= OD8_UCLK_MAX; + } + + if (pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE] > 0 && + pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE] <= 100) + od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT; + + if (data->smu_features[GNLD_FAN_CONTROL].enabled) { + if (pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_FANRPMMIN] > 0) + od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN; + + if (pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_FANRPMACOUSTICLIMIT] > 0) + od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK; + } + + if (data->smu_features[GNLD_THERMAL].enabled) { + if (pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_FANTARGETTEMPERATURE] > 0) + od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN; + + if (pptable_information->od_settings_max[ATOM_VEGA20_ODSETTING_OPERATINGTEMPMAX] > 0) + od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM; + } + + return 0; +} + +static int vega20_od8_set_feature_id( + struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_settings *od_settings = &(data->od8_settings); + + if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = + OD8_GFXCLK_LIMITS; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = + OD8_GFXCLK_LIMITS; + } else { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = + 0; + } + + if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = + OD8_GFXCLK_CURVE; + } else { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = + 0; + } + + if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX) + od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX; + else + od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0; + + if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT) + od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT; + else + od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0; + + if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) + od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = + OD8_ACOUSTIC_LIMIT_SCLK; + else + od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = + 0; + + if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) + od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = + OD8_FAN_SPEED_MIN; + else + od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = + 0; + + if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) + od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = + OD8_TEMPERATURE_FAN; + else + od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = + 0; + + if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) + od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = + OD8_TEMPERATURE_SYSTEM; + else + od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = + 0; + + return 0; +} + +static int vega20_od8_initialize_default_settings( struct pp_hwmgr *hwmgr) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_settings *od8_settings = &(data->od8_settings); + OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table); + int i, ret = 0; + + /* Set Feature Capabilities */ + vega20_od8_set_feature_capabilities(hwmgr); + + /* Map FeatureID to individual settings */ + vega20_od8_set_feature_id(hwmgr); + + /* Set default values */ + ret = vega20_copy_table_from_smc(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE); + PP_ASSERT_WITH_CODE(!ret, + "Failed to export over drive table!", + return ret); + + if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = + od_table->GfxclkFmin; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = + od_table->GfxclkFmax; + } else { + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = + 0; + } + + if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = + od_table->GfxclkFreq1; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = + od_table->GfxclkOffsetVolt1; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = + od_table->GfxclkFreq2; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = + od_table->GfxclkOffsetVolt2; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = + od_table->GfxclkFreq3; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = + od_table->GfxclkOffsetVolt3; + } else { + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = + 0; + } + + if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX) + od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = + od_table->UclkFmax; + else + od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT) + od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = + od_table->OverDrivePct; + else + od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) + od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = + od_table->FanMaximumRpm; + else + od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) + od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = + od_table->FanMinimumPwm; + else + od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) + od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = + od_table->FanTargetTemperature; + else + od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) + od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = + od_table->MaxOpTemp; + else + od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = + 0; + + for (i = 0; i < OD8_SETTING_COUNT; i++) { + if (od8_settings->od8_settings_array[i].feature_id) { + od8_settings->od8_settings_array[i].min_value = + pptable_information->od_settings_min[i]; + od8_settings->od8_settings_array[i].max_value = + pptable_information->od_settings_max[i]; + od8_settings->od8_settings_array[i].current_value = + od8_settings->od8_settings_array[i].default_value; + } else { + od8_settings->od8_settings_array[i].min_value = + 0; + od8_settings->od8_settings_array[i].max_value = + 0; + od8_settings->od8_settings_array[i].current_value = + 0; + } + } + return 0; } @@ -1009,7 +1264,7 @@ static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) "[EnableDPMTasks] Failed to power control set level!", return result); - result = vega20_odn_initialize_default_settings(hwmgr); + result = vega20_od8_initialize_default_settings(hwmgr); PP_ASSERT_WITH_CODE(!result, "[EnableDPMTasks] Failed to initialize odn settings!", return result); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h index 59a59bc..130052a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h @@ -306,7 +306,7 @@ struct vega20_registry_data { uint8_t led_dpm_enabled; uint8_t fan_control_support; uint8_t ulv_support; - uint8_t odn_feature_enable; + uint8_t od8_feature_enable; uint8_t disable_water_mark; uint8_t disable_workload_policy; uint32_t force_workload_policy_mask; @@ -377,6 +377,54 @@ struct vega20_odn_data { struct vega20_odn_temp_table odn_temp_table; }; +enum OD8_FEATURE_ID +{ + OD8_GFXCLK_LIMITS = 1 << 0, + OD8_GFXCLK_CURVE = 1 << 1, + OD8_UCLK_MAX = 1 << 2, + OD8_POWER_LIMIT = 1 << 3, + OD8_ACOUSTIC_LIMIT_SCLK = 1 << 4, //FanMaximumRpm + OD8_FAN_SPEED_MIN = 1 << 5, //FanMinimumPwm + OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature + OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp + OD8_MEMORY_TIMING_TUNE = 1 << 8, + OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 +}; + +enum OD8_SETTING_ID +{ + OD8_SETTING_GFXCLK_FMIN = 0, + OD8_SETTING_GFXCLK_FMAX, + OD8_SETTING_GFXCLK_FREQ1, + OD8_SETTING_GFXCLK_VOLTAGE1, + OD8_SETTING_GFXCLK_FREQ2, + OD8_SETTING_GFXCLK_VOLTAGE2, + OD8_SETTING_GFXCLK_FREQ3, + OD8_SETTING_GFXCLK_VOLTAGE3, + OD8_SETTING_UCLK_FMAX, + OD8_SETTING_POWER_PERCENTAGE, + OD8_SETTING_FAN_ACOUSTIC_LIMIT, + OD8_SETTING_FAN_MIN_SPEED, + OD8_SETTING_FAN_TARGET_TEMP, + OD8_SETTING_OPERATING_TEMP_MAX, + OD8_SETTING_AC_TIMING, + OD8_SETTING_FAN_ZERO_RPM_CONTROL, + OD8_SETTING_COUNT +}; + +struct vega20_od8_single_setting { + uint32_t feature_id; + int32_t min_value; + int32_t max_value; + int32_t current_value; + int32_t default_value; +}; + +struct vega20_od8_settings { + uint32_t overdrive8_capabilities; + struct vega20_od8_single_setting od8_settings_array[OD8_SETTING_COUNT]; +}; + struct vega20_hwmgr { struct vega20_dpm_table dpm_table; struct vega20_dpm_table golden_dpm_table; @@ -452,6 +500,9 @@ struct vega20_hwmgr { /* ---- Overdrive next setting ---- */ struct vega20_odn_data odn_data; + /* ---- Overdrive8 Setting ---- */ + struct vega20_od8_settings od8_settings; + /* ---- Workload Mask ---- */ uint32_t workload_mask; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c index 379ac3d..32d24a4 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c @@ -664,18 +664,18 @@ static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) static int copy_clock_limits_array( struct pp_hwmgr *hwmgr, uint32_t **pptable_info_array, - const uint32_t *pptable_array) + const uint32_t *pptable_array, + uint32_t power_saving_clock_count) { uint32_t array_size, i; uint32_t *table; - array_size = sizeof(uint32_t) * ATOM_VEGA20_PPCLOCK_COUNT; - + array_size = sizeof(uint32_t) * power_saving_clock_count; table = kzalloc(array_size, GFP_KERNEL); if (NULL == table) return -ENOMEM; - for (i = 0; i < ATOM_VEGA20_PPCLOCK_COUNT; i++) + for (i = 0; i < power_saving_clock_count; i++) table[i] = pptable_array[i]; *pptable_info_array = table; @@ -686,22 +686,52 @@ static int copy_clock_limits_array( static int copy_overdrive_settings_limits_array( struct pp_hwmgr *hwmgr, uint32_t **pptable_info_array, - const uint32_t *pptable_array) + const uint32_t *pptable_array, + uint32_t od_setting_count) { uint32_t array_size, i; uint32_t *table; - array_size = sizeof(uint32_t) * ATOM_VEGA20_ODSETTING_COUNT; + array_size = sizeof(uint32_t) * od_setting_count; + table = kzalloc(array_size, GFP_KERNEL); + if (NULL == table) + return -ENOMEM; + + for (i = 0; i < od_setting_count; i++) + table[i] = pptable_array[i]; + + *pptable_info_array = table; + + return 0; +} + +static int copy_overdrive_feature_capabilities_array( + struct pp_hwmgr *hwmgr, + uint8_t **pptable_info_array, + const uint8_t *pptable_array, + uint8_t od_feature_count) +{ + uint32_t array_size, i; + uint8_t *table; + bool od_supported = false; + array_size = sizeof(uint8_t) * od_feature_count; table = kzalloc(array_size, GFP_KERNEL); if (NULL == table) return -ENOMEM; - for (i = 0; i < ATOM_VEGA20_ODSETTING_COUNT; i++) + for (i = 0; i < od_feature_count; i++) { table[i] = pptable_array[i]; + if (table[i]) + od_supported = true; + } *pptable_info_array = table; + if (od_supported) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ACOverdriveSupport); + return 0; } @@ -799,6 +829,7 @@ static int init_powerplay_table_information( struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; uint32_t disable_power_control = 0; + uint32_t od_feature_count, od_setting_count, power_saving_clock_count; int result; hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType; @@ -810,22 +841,25 @@ static int init_powerplay_table_information( phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - if (powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_GFXCLKFMAX] > VEGA20_ENGINECLOCK_HARDMAX) - hwmgr->platform_descriptor.overdriveLimit.engineClock = VEGA20_ENGINECLOCK_HARDMAX; - else - hwmgr->platform_descriptor.overdriveLimit.engineClock = powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_GFXCLKFMAX]; - hwmgr->platform_descriptor.overdriveLimit.memoryClock = powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_UCLKFMAX]; - - copy_overdrive_settings_limits_array(hwmgr, &pptable_information->od_settings_max, powerplay_table->OverDrive8Table.ODSettingsMax); - copy_overdrive_settings_limits_array(hwmgr, &pptable_information->od_settings_min, powerplay_table->OverDrive8Table.ODSettingsMin); - - /* hwmgr->platformDescriptor.minOverdriveVDDC = 0; - hwmgr->platformDescriptor.maxOverdriveVDDC = 0; - hwmgr->platformDescriptor.overdriveVDDCStep = 0; */ - - if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 - && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ACOverdriveSupport); + if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) { + od_feature_count = (powerplay_table->OverDrive8Table.ODFeatureCount > ATOM_VEGA20_ODFEATURE_COUNT) ? + ATOM_VEGA20_ODFEATURE_COUNT : powerplay_table->OverDrive8Table.ODFeatureCount; + od_setting_count = (powerplay_table->OverDrive8Table.ODSettingCount > ATOM_VEGA20_ODSETTING_COUNT) ? + ATOM_VEGA20_ODSETTING_COUNT : powerplay_table->OverDrive8Table.ODSettingCount; + + copy_overdrive_feature_capabilities_array(hwmgr, + &pptable_information->od_feature_capabilities, + powerplay_table->OverDrive8Table.ODFeatureCapabilities, + od_feature_count); + copy_overdrive_settings_limits_array(hwmgr, + &pptable_information->od_settings_max, + powerplay_table->OverDrive8Table.ODSettingsMax, + od_setting_count); + copy_overdrive_settings_limits_array(hwmgr, + &pptable_information->od_settings_min, + powerplay_table->OverDrive8Table.ODSettingsMin, + od_setting_count); + } pptable_information->us_small_power_limit1 = powerplay_table->usSmallPowerLimit1; pptable_information->us_small_power_limit2 = powerplay_table->usSmallPowerLimit2; @@ -838,15 +872,23 @@ static int init_powerplay_table_information( hwmgr->platform_descriptor.TDPODLimit = (uint16_t)powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]; disable_power_control = 0; - if (!disable_power_control && hwmgr->platform_descriptor.TDPODLimit) { + if (!disable_power_control && hwmgr->platform_descriptor.TDPODLimit) /* enable TDP overdrive (PowerControl) feature as well if supported */ - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerControl); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerControl); + + if (powerplay_table->PowerSavingClockTable.ucTableRevision == 1) { + power_saving_clock_count = (powerplay_table->PowerSavingClockTable.PowerSavingClockCount >= ATOM_VEGA20_PPCLOCK_COUNT) ? + ATOM_VEGA20_PPCLOCK_COUNT : powerplay_table->PowerSavingClockTable.PowerSavingClockCount; + copy_clock_limits_array(hwmgr, + &pptable_information->power_saving_clock_max, + powerplay_table->PowerSavingClockTable.PowerSavingClockMax, + power_saving_clock_count); + copy_clock_limits_array(hwmgr, + &pptable_information->power_saving_clock_min, + powerplay_table->PowerSavingClockTable.PowerSavingClockMin, + power_saving_clock_count); } - copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockTable.PowerSavingClockMax); - copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockTable.PowerSavingClockMin); - pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; @@ -898,6 +940,9 @@ static int vega20_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) kfree(pp_table_info->power_saving_clock_min); pp_table_info->power_saving_clock_min = NULL; + kfree(pp_table_info->od_feature_capabilities); + pp_table_info->od_feature_capabilities = NULL; + kfree(pp_table_info->od_settings_max); pp_table_info->od_settings_max = NULL; diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h index 429c9c4..54fd012 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -232,6 +232,8 @@ enum phm_platform_caps { PHM_PlatformCaps_UVDClientMCTuning, PHM_PlatformCaps_ODNinACSupport, PHM_PlatformCaps_ODNinDCSupport, + PHM_PlatformCaps_OD8inACSupport, + PHM_PlatformCaps_OD8inDCSupport, PHM_PlatformCaps_UMDPState, PHM_PlatformCaps_AutoWattmanSupport, PHM_PlatformCaps_AutoWattmanEnable_CCCState, diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 7e58a0d..e0cb7d0 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -584,6 +584,7 @@ struct phm_ppt_v3_information uint32_t *power_saving_clock_max; uint32_t *power_saving_clock_min; + uint8_t *od_feature_capabilities; uint32_t *od_settings_max; uint32_t *od_settings_min; -- 2.7.4