aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRex Zhu <Rex.Zhu@amd.com>2018-01-16 03:04:43 -0500
committerAlex Deucher <alexander.deucher@amd.com>2018-02-19 14:18:19 -0500
commit5e4d4fbea55730362c2e6a68360a7444cb765c46 (patch)
tree64a62c4aca034a2aa40bdb685c528cf7b58041ff
parentb7e919b9403fe5fb653d274d530d5118a3408f1b (diff)
drm/amd/pp: Implement edit_dpm_table on smu7
v2: - check clk against OverDrive limits from VBIOS - set OD flag when user commit the setting. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Rex Zhu <Rex.Zhu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c165
1 files changed, 164 insertions, 1 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index 4ccc9101f2e3..3ed4b4acf90b 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -4808,6 +4808,169 @@ static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
4808 return 0; 4808 return 0;
4809} 4809}
4810 4810
4811static bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr,
4812 enum PP_OD_DPM_TABLE_COMMAND type,
4813 uint32_t clk,
4814 uint32_t voltage)
4815{
4816 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4817
4818 struct phm_ppt_v1_information *table_info =
4819 (struct phm_ppt_v1_information *)(hwmgr->pptable);
4820 uint32_t min_vddc;
4821 struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table;
4822
4823 if (table_info == NULL)
4824 return -EINVAL;
4825
4826 dep_sclk_table = table_info->vdd_dep_on_sclk;
4827 min_vddc = dep_sclk_table->entries[0].vddc;
4828
4829 if (voltage < min_vddc || voltage > 2000) {
4830 pr_info("OD voltage is out of range [%d - 2000] mV\n", min_vddc);
4831 return false;
4832 }
4833
4834 if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) {
4835 if (data->vbios_boot_state.sclk_bootup_value > clk ||
4836 hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) {
4837 pr_info("OD engine clock is out of range [%d - %d] MHz\n",
4838 data->vbios_boot_state.sclk_bootup_value,
4839 hwmgr->platform_descriptor.overdriveLimit.engineClock / 100);
4840 return false;
4841 }
4842 } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) {
4843 if (data->vbios_boot_state.mclk_bootup_value > clk ||
4844 hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) {
4845 pr_info("OD memory clock is out of range [%d - %d] MHz\n",
4846 data->vbios_boot_state.mclk_bootup_value/100,
4847 hwmgr->platform_descriptor.overdriveLimit.memoryClock / 100);
4848 return false;
4849 }
4850 } else {
4851 return false;
4852 }
4853
4854 return true;
4855}
4856
4857static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr)
4858{
4859 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4860 struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table);
4861 struct phm_ppt_v1_information *table_info =
4862 (struct phm_ppt_v1_information *)(hwmgr->pptable);
4863 uint32_t i;
4864
4865 struct phm_ppt_v1_clock_voltage_dependency_table *dep_table;
4866 struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table;
4867
4868 if (table_info == NULL)
4869 return;
4870
4871 for (i=0; i<data->dpm_table.sclk_table.count; i++) {
4872 if (odn_table->odn_core_clock_dpm_levels.entries[i].clock !=
4873 data->dpm_table.sclk_table.dpm_levels[i].value) {
4874 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
4875 break;
4876 }
4877 }
4878
4879 for (i=0; i<data->dpm_table.sclk_table.count; i++) {
4880 if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock !=
4881 data->dpm_table.mclk_table.dpm_levels[i].value) {
4882 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
4883 break;
4884 }
4885 }
4886
4887 dep_table = table_info->vdd_dep_on_mclk;
4888 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk);
4889
4890 for (i=0; i<dep_table->count; i++) {
4891 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
4892 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
4893 return;
4894 }
4895 }
4896
4897 dep_table = table_info->vdd_dep_on_sclk;
4898 odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk);
4899 for (i=0; i<dep_table->count; i++) {
4900 if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) {
4901 data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
4902 return;
4903 }
4904 }
4905}
4906
4907static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
4908 enum PP_OD_DPM_TABLE_COMMAND type,
4909 long *input, uint32_t size)
4910{
4911 uint32_t i;
4912 struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL;
4913 struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend = NULL;
4914 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
4915
4916 uint32_t input_clk;
4917 uint32_t input_vol;
4918 uint32_t input_level;
4919
4920 PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage",
4921 return -EINVAL);
4922
4923 if (!hwmgr->od_enabled) {
4924 pr_info("OverDrive feature not enabled\n");
4925 return -EINVAL;
4926 }
4927
4928 if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
4929 podn_dpm_table_in_backend = &data->odn_dpm_table.odn_core_clock_dpm_levels;
4930 podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_sclk;
4931 PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),
4932 "Failed to get ODN SCLK and Voltage tables",
4933 return -EINVAL);
4934 } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
4935 podn_dpm_table_in_backend = &data->odn_dpm_table.odn_memory_clock_dpm_levels;
4936 podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_mclk;
4937
4938 PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend),
4939 "Failed to get ODN MCLK and Voltage tables",
4940 return -EINVAL);
4941 } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
4942 smu7_odn_initial_default_setting(hwmgr);
4943 return 0;
4944 } else if (PP_OD_COMMIT_DPM_TABLE == type) {
4945 smu7_check_dpm_table_updated(hwmgr);
4946 return 0;
4947 } else {
4948 return -EINVAL;
4949 }
4950
4951 for (i = 0; i < size; i += 3) {
4952 if (i + 3 > size || input[i] >= podn_dpm_table_in_backend->num_of_pl) {
4953 pr_info("invalid clock voltage input \n");
4954 return 0;
4955 }
4956 input_level = input[i];
4957 input_clk = input[i+1] * 100;
4958 input_vol = input[i+2];
4959
4960 if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) {
4961 podn_dpm_table_in_backend->entries[input_level].clock = input_clk;
4962 podn_vdd_dep_in_backend->entries[input_level].clk = input_clk;
4963 podn_dpm_table_in_backend->entries[input_level].vddc = input_vol;
4964 podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol;
4965 } else {
4966 return -EINVAL;
4967 }
4968 }
4969
4970 return 0;
4971}
4972
4973
4811static const struct pp_hwmgr_func smu7_hwmgr_funcs = { 4974static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
4812 .backend_init = &smu7_hwmgr_backend_init, 4975 .backend_init = &smu7_hwmgr_backend_init,
4813 .backend_fini = &smu7_hwmgr_backend_fini, 4976 .backend_fini = &smu7_hwmgr_backend_fini,
@@ -4862,6 +5025,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
4862 .notify_cac_buffer_info = smu7_notify_cac_buffer_info, 5025 .notify_cac_buffer_info = smu7_notify_cac_buffer_info,
4863 .get_max_high_clocks = smu7_get_max_high_clocks, 5026 .get_max_high_clocks = smu7_get_max_high_clocks,
4864 .get_thermal_temperature_range = smu7_get_thermal_temperature_range, 5027 .get_thermal_temperature_range = smu7_get_thermal_temperature_range,
5028 .odn_edit_dpm_table = smu7_odn_edit_dpm_table,
4865}; 5029};
4866 5030
4867uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, 5031uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
@@ -4893,4 +5057,3 @@ int smu7_init_function_pointers(struct pp_hwmgr *hwmgr)
4893 5057
4894 return ret; 5058 return ret;
4895} 5059}
4896