Provides standardized interface to read various sensors. The API is extensible (by adding to the end of the amd_pp_sensors enumeration list.
Support has been added to Carrizo/Tonga/Fiji/Polaris/Iceland (v2) Squashed the two sensor patches into one. Signed-off-by: Tom St Denis <tom.stde...@amd.com> --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 20 +++++ drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | 96 ++++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c | 34 ++++++++ .../gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c | 34 ++++++++ .../gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c | 33 ++++++++ drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c | 33 ++++++++ drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 12 +++ drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 8 files changed, 263 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index b1d19409bf86..ee0368381e82 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -894,6 +894,25 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value) return hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); } +static int pp_dpm_read_sensor(void *handle, int idx, int32_t *value) +{ + struct pp_hwmgr *hwmgr; + + if (!handle) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + PP_CHECK_HW(hwmgr); + + if (hwmgr->hwmgr_func->read_sensor == NULL) { + printk(KERN_INFO "%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value); +} + const struct amd_powerplay_funcs pp_dpm_funcs = { .get_temperature = pp_dpm_get_temperature, .load_firmware = pp_dpm_load_fw, @@ -920,6 +939,7 @@ const struct amd_powerplay_funcs pp_dpm_funcs = { .set_sclk_od = pp_dpm_set_sclk_od, .get_mclk_od = pp_dpm_get_mclk_od, .set_mclk_od = pp_dpm_set_mclk_od, + .read_sensor = pp_dpm_read_sensor, }; static int amd_pp_instance_init(struct amd_pp_init *pp_init, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 5ecef1732e20..9f3c5a8a903c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -1857,6 +1857,101 @@ static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_c return 0; } +static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX), + TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); + uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); + uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); + + uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent; + uint16_t vddnb, vddgfx; + int result; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + if (sclk_index < NUM_SCLK_LEVELS) { + sclk = table->entries[sclk_index].clk; + *value = sclk; + return 0; + } + return -EINVAL; + case AMDGPU_PP_SENSOR_VDDNB: + tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & + CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; + vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp); + *value = vddnb; + return 0; + case AMDGPU_PP_SENSOR_VDDGFX: + tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & + CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; + vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp); + *value = vddgfx; + return 0; + case AMDGPU_PP_SENSOR_UVD_VCLK: + if (!cz_hwmgr->uvd_power_gated) { + if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + return -EINVAL; + } else { + vclk = uvd_table->entries[uvd_index].vclk; + *value = vclk; + return 0; + } + } + *value = 0; + return 0; + case AMDGPU_PP_SENSOR_UVD_DCLK: + if (!cz_hwmgr->uvd_power_gated) { + if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + return -EINVAL; + } else { + dclk = uvd_table->entries[uvd_index].dclk; + *value = dclk; + return 0; + } + } + *value = 0; + return 0; + case AMDGPU_PP_SENSOR_VCE_ECCLK: + if (!cz_hwmgr->vce_power_gated) { + if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + return -EINVAL; + } else { + ecclk = vce_table->entries[vce_index].ecclk; + *value = ecclk; + return 0; + } + } + *value = 0; + return 0; + case AMDGPU_PP_SENSOR_GPU_LOAD: + result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity); + if (0 == result) { + activity_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0); + activity_percent = activity_percent > 100 ? 100 : activity_percent; + } else { + activity_percent = 50; + } + *value = activity_percent; + return 0; + default: + return -EINVAL; + } +} + static const struct pp_hwmgr_func cz_hwmgr_funcs = { .backend_init = cz_hwmgr_backend_init, .backend_fini = cz_hwmgr_backend_fini, @@ -1882,6 +1977,7 @@ static const struct pp_hwmgr_func cz_hwmgr_funcs = { .get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks, .get_clock_by_type = cz_get_clock_by_type, .get_max_high_clocks = cz_get_max_high_clocks, + .read_sensor = cz_read_sensor, }; int cz_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c index 0d4c99b9e3f9..06aacefe5df1 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c @@ -5104,6 +5104,39 @@ static void fiji_print_current_perforce_level( seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en"); } +static int fiji_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) +{ + uint32_t sclk, mclk, activity_percent; + uint32_t offset; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetSclkFrequency)); + sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = sclk; + return 0; + case AMDGPU_PP_SENSOR_GFX_MCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetMclkFrequency)); + mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = mclk; + return 0; + case AMDGPU_PP_SENSOR_GPU_LOAD: + offset = data->soft_regs_start + offsetof(SMU73_SoftRegisters, AverageGraphicsActivity); + activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); + activity_percent += 0x80; + activity_percent >>= 8; + *value = (activity_percent > 100) ? 100 : activity_percent; + return 0; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *value = fiji_thermal_get_temperature(hwmgr); + return 0; + default: + return -EINVAL; + } +} + + static int fiji_program_display_gap(struct pp_hwmgr *hwmgr) { struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); @@ -5590,6 +5623,7 @@ static const struct pp_hwmgr_func fiji_hwmgr_funcs = { .set_sclk_od = fiji_set_sclk_od, .get_mclk_od = fiji_get_mclk_od, .set_mclk_od = fiji_set_mclk_od, + .read_sensor = fiji_read_sensor, }; int fiji_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c index 5abe43360ec0..79b4b47d65f3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/iceland_hwmgr.c @@ -5134,6 +5134,39 @@ iceland_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m) seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en"); } +static int iceland_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) +{ + uint32_t sclk, mclk, activity_percent; + uint32_t offset; + struct iceland_hwmgr *data = (struct iceland_hwmgr *)(hwmgr->backend); + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetSclkFrequency)); + sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = sclk; + return 0; + case AMDGPU_PP_SENSOR_GFX_MCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetMclkFrequency)); + mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = mclk; + return 0; + case AMDGPU_PP_SENSOR_GPU_LOAD: + offset = data->soft_regs_start + offsetof(SMU71_SoftRegisters, AverageGraphicsActivity); + activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); + activity_percent += 0x80; + activity_percent >>= 8; + *value = (activity_percent > 100) ? 100 : activity_percent; + return 0; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *value = iceland_thermal_get_temperature(hwmgr); + return 0; + default: + return -EINVAL; + } +} + + int iceland_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) { uint32_t num_active_displays = 0; @@ -5663,6 +5696,7 @@ static const struct pp_hwmgr_func iceland_hwmgr_funcs = { .set_sclk_od = iceland_set_sclk_od, .get_mclk_od = iceland_get_mclk_od, .set_mclk_od = iceland_set_mclk_od, + .read_sensor = iceland_read_sensor, }; int iceland_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c index 970e3930452d..9e482a1a8009 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris10_hwmgr.c @@ -4009,6 +4009,38 @@ polaris10_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file * seq_printf(m, "vce %sabled\n", data->vce_power_gated ? "dis" : "en"); } +static int polaris10_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) +{ + uint32_t sclk, mclk, activity_percent; + uint32_t offset; + struct polaris10_hwmgr *data = (struct polaris10_hwmgr *)(hwmgr->backend); + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetSclkFrequency)); + sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = sclk; + return 0; + case AMDGPU_PP_SENSOR_GFX_MCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetMclkFrequency)); + mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = mclk; + return 0; + case AMDGPU_PP_SENSOR_GPU_LOAD: + offset = data->soft_regs_start + offsetof(SMU74_SoftRegisters, AverageGraphicsActivity); + activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); + activity_percent += 0x80; + activity_percent >>= 8; + *value = (activity_percent > 100) ? 100 : activity_percent; + return 0; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *value = polaris10_thermal_get_temperature(hwmgr); + return 0; + default: + return -EINVAL; + } +} + static int polaris10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) { const struct phm_set_power_state_input *states = @@ -5278,6 +5310,7 @@ static const struct pp_hwmgr_func polaris10_hwmgr_funcs = { .set_sclk_od = polaris10_set_sclk_od, .get_mclk_od = polaris10_get_mclk_od, .set_mclk_od = polaris10_set_mclk_od, + .read_sensor = polaris10_read_sensor, }; int polaris10_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c index 42783bf7647c..ea92a6bc4945 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -6314,6 +6314,38 @@ static int tonga_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) return 0; } +static int tonga_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) +{ + uint32_t sclk, mclk, activity_percent; + uint32_t offset; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetSclkFrequency)); + sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = sclk; + return 0; + case AMDGPU_PP_SENSOR_GFX_MCLK: + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetMclkFrequency)); + mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + *value = mclk; + return 0; + case AMDGPU_PP_SENSOR_GPU_LOAD: + offset = data->soft_regs_start + offsetof(SMU72_SoftRegisters, AverageGraphicsActivity); + activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); + activity_percent += 0x80; + activity_percent >>= 8; + *value = (activity_percent > 100) ? 100 : activity_percent; + return 0; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *value = tonga_thermal_get_temperature(hwmgr); + return 0; + default: + return -EINVAL; + } +} + static const struct pp_hwmgr_func tonga_hwmgr_funcs = { .backend_init = &tonga_hwmgr_backend_init, .backend_fini = &tonga_hwmgr_backend_fini, @@ -6359,6 +6391,7 @@ static const struct pp_hwmgr_func tonga_hwmgr_funcs = { .set_sclk_od = tonga_set_sclk_od, .get_mclk_od = tonga_get_mclk_od, .set_mclk_od = tonga_set_mclk_od, + .read_sensor = tonga_read_sensor, }; int tonga_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 18f39e89a7aa..39f25e604ff3 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -29,6 +29,17 @@ #include "amd_shared.h" #include "cgs_common.h" +enum amd_pp_sensors { + AMDGPU_PP_SENSOR_GFX_SCLK = 0, + AMDGPU_PP_SENSOR_VDDNB, + AMDGPU_PP_SENSOR_VDDGFX, + AMDGPU_PP_SENSOR_UVD_VCLK, + AMDGPU_PP_SENSOR_UVD_DCLK, + AMDGPU_PP_SENSOR_VCE_ECCLK, + AMDGPU_PP_SENSOR_GPU_LOAD, + AMDGPU_PP_SENSOR_GFX_MCLK, + AMDGPU_PP_SENSOR_GPU_TEMP, +}; enum amd_pp_event { AMD_PP_EVENT_INITIALIZE = 0, @@ -346,6 +357,7 @@ struct amd_powerplay_funcs { int (*set_sclk_od)(void *handle, uint32_t value); int (*get_mclk_od)(void *handle); int (*set_mclk_od)(void *handle, uint32_t value); + int (*read_sensor)(void *handle, int idx, int32_t *value); }; struct amd_powerplay { diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index e98748344801..310ba0ce2934 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -359,6 +359,7 @@ struct pp_hwmgr_func { int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); int (*get_mclk_od)(struct pp_hwmgr *hwmgr); int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); + int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, int32_t *value); }; struct pp_table_func { -- 2.10.0 _______________________________________________ amd-gfx mailing list amd-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx