diff options
author | Rex Zhu <Rex.Zhu@amd.com> | 2018-01-16 03:04:43 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-02-19 14:18:19 -0500 |
commit | 5e4d4fbea55730362c2e6a68360a7444cb765c46 (patch) | |
tree | 64a62c4aca034a2aa40bdb685c528cf7b58041ff | |
parent | b7e919b9403fe5fb653d274d530d5118a3408f1b (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.c | 165 |
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 | ||
4811 | static 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 | |||
4857 | static 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 | |||
4907 | static 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 | |||
4811 | static const struct pp_hwmgr_func smu7_hwmgr_funcs = { | 4974 | static 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 | ||
4867 | uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, | 5031 | uint8_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 | |||