On 2018-01-24 04:37 AM, Rex Zhu wrote: > Change-Id: I4533826ef6e18df125ae4445016873be3b5fe0ce > Signed-off-by: Rex Zhu <Rex.Zhu at amd.com> > --- > .../drm/amd/powerplay/smumgr/polaris10_smumgr.c | 104 +++++++++++++++++++++ > 1 file changed, 104 insertions(+) > > diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c > index bfb2c85..559572d 100644 > --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c > +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c > @@ -2575,6 +2575,109 @@ static int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, > array_size, SMC_RAM_END); > } > > +uint32_t polaris10_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size) > +{ > + u32 mask = 0; > + u32 shift = 0; > + > + shift = (offset % 4) << 3; > + if (size == sizeof(uint8_t)) > + mask = 0xFF << shift; > + else if (size == sizeof(uint16_t)) > + mask = 0xFFFF << shift; > + > + original_data &= ~mask; > + original_data |= (field << shift); > + return original_data; > +} > + > +static int polaris10_update_dpm_settings(struct pp_hwmgr *hwmgr, > + void *profile_setting) > +{ > + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *) > + (hwmgr->smu_backend); > + struct profile_mode_setting *setting; > + struct SMU74_Discrete_GraphicsLevel *levels = > + smu_data->smc_state_table.GraphicsLevel; > + uint32_t array = smu_data->smu7_data.dpm_table_start + > + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); > + > + uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + > + offsetof(SMU74_Discrete_DpmTable, MemoryLevel); > + struct SMU74_Discrete_MemoryLevel *mclk_levels = > + smu_data->smc_state_table.MemoryLevel; > + uint32_t i; > + uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; > + > + if (profile_setting == NULL) > + return -EINVAL; > + > + setting = (struct profile_mode_setting *)profile_setting; > + > + if (setting->bupdate_sclk) { > + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { > + if (levels[i].ActivityLevel != > + cpu_to_be16(setting->sclk_activity)) { > + levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); > + > + clk_activity_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) > + + offsetof(SMU74_Discrete_GraphicsLevel, ActivityLevel); > + offset = clk_activity_offset & ~0x3; > + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); > + tmp = polaris10_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); > + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); > + > + } > + if (levels[i].UpHyst != setting->sclk_up_hyst || > + levels[i].DownHyst != setting->sclk_down_hyst) { > + levels[i].UpHyst = setting->sclk_up_hyst; > + levels[i].DownHyst = setting->sclk_down_hyst; > + up_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) > + + offsetof(SMU74_Discrete_GraphicsLevel, UpHyst); > + down_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) > + + offsetof(SMU74_Discrete_GraphicsLevel, DownHyst); > + offset = up_hyst_offset & ~0x3; > + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); > + tmp = polaris10_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); > + tmp = polaris10_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); > + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); > + } > + } > + } > + > + if (setting->bupdate_mclk) { > + for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { > + if (mclk_levels[i].ActivityLevel != > + cpu_to_be16(setting->mclk_activity)) { > + mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); > + > + clk_activity_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) > + + offsetof(SMU74_Discrete_MemoryLevel, ActivityLevel); > + offset = clk_activity_offset & ~0x3; > + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); > + tmp = polaris10_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); > + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); > + > + } > + if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || > + mclk_levels[i].DownHyst != setting->mclk_down_hyst) { > + mclk_levels[i].UpHyst = setting->mclk_up_hyst; > + mclk_levels[i].DownHyst = setting->mclk_down_hyst; > + up_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) > + + offsetof(SMU74_Discrete_MemoryLevel, UpHyst); > + down_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) > + + offsetof(SMU74_Discrete_MemoryLevel, DownHyst); > + offset = up_hyst_offset & ~0x3; > + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); > + tmp = polaris10_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); > + tmp = polaris10_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); > + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); We have to call smu7_freeze/unfreeze_sclk_mclk_dpm functions before/after updating smc tables. Regards, Eric > + } > + } > + } > + return 0; > +} > + > const struct pp_smumgr_func polaris10_smu_funcs = { > .smu_init = polaris10_smu_init, > .smu_fini = smu7_smu_fini, > @@ -2599,4 +2702,5 @@ static int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, > .is_dpm_running = polaris10_is_dpm_running, > .populate_requested_graphic_levels = polaris10_populate_requested_graphic_levels, > .is_hw_avfs_present = polaris10_is_hw_avfs_present, > + .update_dpm_settings = polaris10_update_dpm_settings, > };