Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amd/powerplay: add hardware manager sub-component

The hwmgr handles all hardware related calls, including clock/power
gating control, DPM, read and parse PPTable, etc.

v5: squash in fixes
v4: implement acpi's atcs function use cgs interface
v3: fix code style error and add big-endian mode support.
v2: use cgs interface directly in hwmgr sub-module

Signed-off-by: Rex Zhu <Rex.Zhu@amd.com>
Signed-off-by: Jammy Zhou <Jammy.Zhou@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Jammy Zhou and committed by
Alex Deucher
3bace359 ac885b3a

+3439 -6
+1 -1
drivers/gpu/drm/amd/powerplay/Makefile
··· 6 6 7 7 AMD_PP_PATH = ../powerplay 8 8 9 - PP_LIBS = smumgr 9 + PP_LIBS = smumgr hwmgr 10 10 11 11 AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix drivers/gpu/drm/amd/powerplay/,$(PP_LIBS))) 12 12
+52 -3
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
··· 35 35 36 36 static int pp_sw_init(void *handle) 37 37 { 38 - return 0; 38 + struct pp_instance *pp_handle; 39 + struct pp_hwmgr *hwmgr; 40 + int ret = 0; 41 + 42 + if (handle == NULL) 43 + return -EINVAL; 44 + 45 + pp_handle = (struct pp_instance *)handle; 46 + hwmgr = pp_handle->hwmgr; 47 + 48 + if (hwmgr == NULL || hwmgr->pptable_func == NULL || 49 + hwmgr->hwmgr_func == NULL || 50 + hwmgr->pptable_func->pptable_init == NULL || 51 + hwmgr->hwmgr_func->backend_init == NULL) 52 + return -EINVAL; 53 + 54 + ret = hwmgr->pptable_func->pptable_init(hwmgr); 55 + if (ret == 0) 56 + ret = hwmgr->hwmgr_func->backend_init(hwmgr); 57 + 58 + return ret; 39 59 } 40 60 41 61 static int pp_sw_fini(void *handle) 42 62 { 43 - return 0; 63 + struct pp_instance *pp_handle; 64 + struct pp_hwmgr *hwmgr; 65 + int ret = 0; 66 + 67 + if (handle == NULL) 68 + return -EINVAL; 69 + 70 + pp_handle = (struct pp_instance *)handle; 71 + hwmgr = pp_handle->hwmgr; 72 + 73 + if (hwmgr != NULL || hwmgr->hwmgr_func != NULL || 74 + hwmgr->hwmgr_func->backend_fini != NULL) 75 + ret = hwmgr->hwmgr_func->backend_fini(hwmgr); 76 + 77 + return ret; 44 78 } 45 79 46 80 static int pp_hw_init(void *handle) ··· 106 72 smumgr->smumgr_funcs->smu_fini(smumgr); 107 73 return ret; 108 74 } 75 + hw_init_power_state_table(pp_handle->hwmgr); 76 + 109 77 return 0; 110 78 } 111 79 ··· 239 203 { 240 204 return; 241 205 } 206 + 242 207 const struct amd_powerplay_funcs pp_dpm_funcs = { 243 208 .get_temperature = NULL, 244 209 .load_firmware = pp_dpm_load_fw, ··· 267 230 268 231 ret = smum_init(pp_init, handle); 269 232 if (ret) 270 - return ret; 233 + goto fail_smum; 234 + 235 + ret = hwmgr_init(pp_init, handle); 236 + if (ret) 237 + goto fail_hwmgr; 271 238 272 239 amd_pp->pp_handle = handle; 273 240 return 0; 241 + 242 + fail_hwmgr: 243 + smum_fini(handle->smu_mgr); 244 + fail_smum: 245 + kfree(handle); 246 + return ret; 274 247 } 275 248 276 249 static int amd_pp_instance_fini(void *handle) ··· 288 241 struct pp_instance *instance = (struct pp_instance *)handle; 289 242 if (instance == NULL) 290 243 return -EINVAL; 244 + 245 + hwmgr_fini(instance->hwmgr); 291 246 292 247 smum_fini(instance->smu_mgr); 293 248
+10
drivers/gpu/drm/amd/powerplay/hwmgr/Makefile
··· 1 + # 2 + # Makefile for the 'hw manager' sub-component of powerplay. 3 + # It provides the hardware management services for the driver. 4 + 5 + HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \ 6 + hardwaremanager.o pp_acpi.o 7 + 8 + AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR)) 9 + 10 + AMD_POWERPLAY_FILES += $(AMD_PP_HWMGR)
+154
drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #include <linux/types.h> 24 + #include <linux/kernel.h> 25 + #include <linux/slab.h> 26 + #include "hwmgr.h" 27 + 28 + static int phm_run_table(struct pp_hwmgr *hwmgr, 29 + struct phm_runtime_table_header *rt_table, 30 + void *input, 31 + void *output, 32 + void *temp_storage) 33 + { 34 + int result = 0; 35 + phm_table_function *function; 36 + 37 + for (function = rt_table->function_list; NULL != *function; function++) { 38 + int tmp = (*function)(hwmgr, input, output, temp_storage, result); 39 + 40 + if (tmp == PP_Result_TableImmediateExit) 41 + break; 42 + if (tmp) { 43 + if (0 == result) 44 + result = tmp; 45 + if (rt_table->exit_error) 46 + break; 47 + } 48 + } 49 + 50 + return result; 51 + } 52 + 53 + int phm_dispatch_table(struct pp_hwmgr *hwmgr, 54 + struct phm_runtime_table_header *rt_table, 55 + void *input, void *output) 56 + { 57 + int result = 0; 58 + void *temp_storage = NULL; 59 + 60 + if (hwmgr == NULL || rt_table == NULL || rt_table->function_list == NULL) { 61 + printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n"); 62 + return 0; /*temp return ture because some function not implement on some asic */ 63 + } 64 + 65 + if (0 != rt_table->storage_size) { 66 + temp_storage = kzalloc(rt_table->storage_size, GFP_KERNEL); 67 + if (temp_storage == NULL) { 68 + printk(KERN_ERR "[ powerplay ] Could not allocate table temporary storage\n"); 69 + return -1; 70 + } 71 + } 72 + 73 + result = phm_run_table(hwmgr, rt_table, input, output, temp_storage); 74 + 75 + if (NULL != temp_storage) 76 + kfree(temp_storage); 77 + 78 + return result; 79 + } 80 + 81 + int phm_construct_table(struct pp_hwmgr *hwmgr, 82 + struct phm_master_table_header *master_table, 83 + struct phm_runtime_table_header *rt_table) 84 + { 85 + uint32_t function_count = 0; 86 + const struct phm_master_table_item *table_item; 87 + uint32_t size; 88 + phm_table_function *run_time_list; 89 + phm_table_function *rtf; 90 + 91 + if (hwmgr == NULL || master_table == NULL || rt_table == NULL) { 92 + printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n"); 93 + return -1; 94 + } 95 + 96 + for (table_item = master_table->master_list; 97 + NULL != table_item->tableFunction; table_item++) { 98 + if ((NULL == table_item->isFunctionNeededInRuntimeTable) || 99 + (table_item->isFunctionNeededInRuntimeTable(hwmgr))) 100 + function_count++; 101 + } 102 + 103 + size = (function_count + 1) * sizeof(phm_table_function); 104 + run_time_list = kzalloc(size, GFP_KERNEL); 105 + if (NULL == run_time_list) 106 + return -1; 107 + 108 + rtf = run_time_list; 109 + for (table_item = master_table->master_list; 110 + NULL != table_item->tableFunction; table_item++) { 111 + if ((rtf - run_time_list) > function_count) { 112 + printk(KERN_ERR "[ powerplay ] Check function results have changed\n"); 113 + kfree(run_time_list); 114 + return -1; 115 + } 116 + 117 + if ((NULL == table_item->isFunctionNeededInRuntimeTable) || 118 + (table_item->isFunctionNeededInRuntimeTable(hwmgr))) { 119 + *(rtf++) = table_item->tableFunction; 120 + } 121 + } 122 + 123 + if ((rtf - run_time_list) > function_count) { 124 + printk(KERN_ERR "[ powerplay ] Check function results have changed\n"); 125 + kfree(run_time_list); 126 + return -1; 127 + } 128 + 129 + *rtf = NULL; 130 + rt_table->function_list = run_time_list; 131 + rt_table->exit_error = (0 != (master_table->flags & PHM_MasterTableFlag_ExitOnError)); 132 + rt_table->storage_size = master_table->storage_size; 133 + return 0; 134 + } 135 + 136 + int phm_destroy_table(struct pp_hwmgr *hwmgr, 137 + struct phm_runtime_table_header *rt_table) 138 + { 139 + if (hwmgr == NULL || rt_table == NULL) { 140 + printk(KERN_ERR "[ powerplay ] Invalid Parameter\n"); 141 + return -1; 142 + } 143 + 144 + if (NULL == rt_table->function_list) 145 + return 0; 146 + 147 + kfree(rt_table->function_list); 148 + 149 + rt_table->function_list = NULL; 150 + rt_table->storage_size = 0; 151 + rt_table->exit_error = false; 152 + 153 + return 0; 154 + }
+84
drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #include <linux/errno.h> 24 + #include "hwmgr.h" 25 + #include "hardwaremanager.h" 26 + #include "pp_acpi.h" 27 + #include "amd_acpi.h" 28 + 29 + void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr) 30 + { 31 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition); 32 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition); 33 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition); 34 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating); 35 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM); 36 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating); 37 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport); 38 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep); 39 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS); 40 + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating); 41 + 42 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM); 43 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake); 44 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling); 45 + 46 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); 47 + 48 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support); 49 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays); 50 + 51 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress); 52 + 53 + if (acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST) && 54 + acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION)) 55 + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); 56 + } 57 + 58 + int phm_setup_asic(struct pp_hwmgr *hwmgr) 59 + { 60 + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 61 + PHM_PlatformCaps_TablelessHardwareInterface)) { 62 + if (NULL != hwmgr->hwmgr_func->asic_setup) 63 + return hwmgr->hwmgr_func->asic_setup(hwmgr); 64 + } else { 65 + return phm_dispatch_table (hwmgr, &(hwmgr->setup_asic), 66 + NULL, NULL); 67 + } 68 + 69 + return 0; 70 + } 71 + 72 + int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr) 73 + { 74 + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 75 + PHM_PlatformCaps_TablelessHardwareInterface)) { 76 + if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable) 77 + return hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr); 78 + } else { 79 + return phm_dispatch_table (hwmgr, 80 + &(hwmgr->enable_dynamic_state_management), 81 + NULL, NULL); 82 + } 83 + return 0; 84 + }
+201
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #include "linux/delay.h" 24 + #include <linux/types.h> 25 + #include <linux/kernel.h> 26 + #include <linux/slab.h> 27 + #include "cgs_common.h" 28 + #include "power_state.h" 29 + #include "hwmgr.h" 30 + 31 + 32 + 33 + int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) 34 + { 35 + struct pp_hwmgr *hwmgr; 36 + 37 + if ((handle == NULL) || (pp_init == NULL)) 38 + return -EINVAL; 39 + 40 + hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL); 41 + if (hwmgr == NULL) 42 + return -ENOMEM; 43 + 44 + handle->hwmgr = hwmgr; 45 + hwmgr->smumgr = handle->smu_mgr; 46 + hwmgr->device = pp_init->device; 47 + hwmgr->chip_family = pp_init->chip_family; 48 + hwmgr->chip_id = pp_init->chip_id; 49 + hwmgr->hw_revision = pp_init->rev_id; 50 + hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; 51 + hwmgr->power_source = PP_PowerSource_AC; 52 + 53 + switch (hwmgr->chip_family) { 54 + default: 55 + return -EINVAL; 56 + } 57 + 58 + phm_init_dynamic_caps(hwmgr); 59 + 60 + return 0; 61 + } 62 + 63 + int hwmgr_fini(struct pp_hwmgr *hwmgr) 64 + { 65 + if (hwmgr == NULL || hwmgr->ps == NULL) 66 + return -EINVAL; 67 + 68 + kfree(hwmgr->ps); 69 + kfree(hwmgr); 70 + return 0; 71 + } 72 + 73 + int hw_init_power_state_table(struct pp_hwmgr *hwmgr) 74 + { 75 + int result; 76 + unsigned int i; 77 + unsigned int table_entries; 78 + struct pp_power_state *state; 79 + int size; 80 + 81 + if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL) 82 + return -EINVAL; 83 + 84 + if (hwmgr->hwmgr_func->get_power_state_size == NULL) 85 + return -EINVAL; 86 + 87 + hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr); 88 + 89 + hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) + 90 + sizeof(struct pp_power_state); 91 + 92 + hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL); 93 + 94 + state = hwmgr->ps; 95 + 96 + for (i = 0; i < table_entries; i++) { 97 + result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); 98 + if (state->classification.flags & PP_StateClassificationFlag_Boot) { 99 + hwmgr->boot_ps = state; 100 + hwmgr->current_ps = hwmgr->request_ps = state; 101 + } 102 + 103 + state->id = i + 1; /* assigned unique num for every power state id */ 104 + 105 + if (state->classification.flags & PP_StateClassificationFlag_Uvd) 106 + hwmgr->uvd_ps = state; 107 + state = (struct pp_power_state *)((uint64_t)state + size); 108 + } 109 + 110 + return 0; 111 + } 112 + 113 + 114 + /** 115 + * Returns once the part of the register indicated by the mask has 116 + * reached the given value. 117 + */ 118 + int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, 119 + uint32_t value, uint32_t mask) 120 + { 121 + uint32_t i; 122 + uint32_t cur_value; 123 + 124 + if (hwmgr == NULL || hwmgr->device == NULL) { 125 + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); 126 + return -EINVAL; 127 + } 128 + 129 + for (i = 0; i < hwmgr->usec_timeout; i++) { 130 + cur_value = cgs_read_register(hwmgr->device, index); 131 + if ((cur_value & mask) == (value & mask)) 132 + break; 133 + udelay(1); 134 + } 135 + 136 + /* timeout means wrong logic*/ 137 + if (i == hwmgr->usec_timeout) 138 + return -1; 139 + return 0; 140 + } 141 + 142 + int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, 143 + uint32_t index, uint32_t value, uint32_t mask) 144 + { 145 + uint32_t i; 146 + uint32_t cur_value; 147 + 148 + if (hwmgr == NULL || hwmgr->device == NULL) { 149 + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); 150 + return -EINVAL; 151 + } 152 + 153 + for (i = 0; i < hwmgr->usec_timeout; i++) { 154 + cur_value = cgs_read_register(hwmgr->device, index); 155 + if ((cur_value & mask) != (value & mask)) 156 + break; 157 + udelay(1); 158 + } 159 + 160 + /* timeout means wrong logic*/ 161 + if (i == hwmgr->usec_timeout) 162 + return -1; 163 + return 0; 164 + } 165 + 166 + 167 + /** 168 + * Returns once the part of the register indicated by the mask has 169 + * reached the given value.The indirect space is described by giving 170 + * the memory-mapped index of the indirect index register. 171 + */ 172 + void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, 173 + uint32_t indirect_port, 174 + uint32_t index, 175 + uint32_t value, 176 + uint32_t mask) 177 + { 178 + if (hwmgr == NULL || hwmgr->device == NULL) { 179 + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); 180 + return; 181 + } 182 + 183 + cgs_write_register(hwmgr->device, indirect_port, index); 184 + phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); 185 + } 186 + 187 + void phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr, 188 + uint32_t indirect_port, 189 + uint32_t index, 190 + uint32_t value, 191 + uint32_t mask) 192 + { 193 + if (hwmgr == NULL || hwmgr->device == NULL) { 194 + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); 195 + return; 196 + } 197 + 198 + cgs_write_register(hwmgr->device, indirect_port, index); 199 + phm_wait_for_register_unequal(hwmgr, indirect_port + 1, 200 + value, mask); 201 + }
+76
drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
··· 1 + #include <linux/errno.h> 2 + #include "linux/delay.h" 3 + #include "hwmgr.h" 4 + #include "amd_acpi.h" 5 + 6 + bool acpi_atcs_functions_supported(void *device, uint32_t index) 7 + { 8 + int32_t result; 9 + struct atcs_verify_interface output_buf = {0}; 10 + 11 + int32_t temp_buffer = 1; 12 + 13 + result = cgs_call_acpi_method(device, CGS_ACPI_METHOD_ATCS, 14 + ATCS_FUNCTION_VERIFY_INTERFACE, 15 + &temp_buffer, 16 + &output_buf, 17 + 1, 18 + sizeof(temp_buffer), 19 + sizeof(output_buf)); 20 + 21 + return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false; 22 + } 23 + 24 + int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise) 25 + { 26 + struct atcs_pref_req_input atcs_input; 27 + struct atcs_pref_req_output atcs_output; 28 + u32 retry = 3; 29 + int result; 30 + struct cgs_system_info info = {0}; 31 + 32 + if (!acpi_atcs_functions_supported(device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST)) 33 + return -EINVAL; 34 + 35 + info.size = sizeof(struct cgs_system_info); 36 + info.info_id = CGS_SYSTEM_INFO_ADAPTER_BDF_ID; 37 + result = cgs_query_system_info(device, &info); 38 + if (result != 0) 39 + return -EINVAL; 40 + atcs_input.client_id = (uint16_t)info.value; 41 + atcs_input.size = sizeof(struct atcs_pref_req_input); 42 + atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK; 43 + atcs_input.flags = ATCS_WAIT_FOR_COMPLETION; 44 + if (advertise) 45 + atcs_input.flags |= ATCS_ADVERTISE_CAPS; 46 + atcs_input.req_type = ATCS_PCIE_LINK_SPEED; 47 + atcs_input.perf_req = perf_req; 48 + 49 + atcs_output.size = sizeof(struct atcs_pref_req_input); 50 + 51 + while (retry--) { 52 + result = cgs_call_acpi_method(device, 53 + CGS_ACPI_METHOD_ATCS, 54 + ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, 55 + &atcs_input, 56 + &atcs_output, 57 + 0, 58 + sizeof(atcs_input), 59 + sizeof(atcs_output)); 60 + if (result != 0) 61 + return -EIO; 62 + 63 + switch (atcs_output.ret_val) { 64 + case ATCS_REQUEST_REFUSED: 65 + default: 66 + return -EINVAL; 67 + case ATCS_REQUEST_COMPLETE: 68 + return 0; 69 + case ATCS_REQUEST_IN_PROGRESS: 70 + udelay(10); 71 + break; 72 + } 73 + } 74 + 75 + return 0; 76 + }
+1661
drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #include <linux/types.h> 24 + #include <linux/kernel.h> 25 + #include <linux/slab.h> 26 + 27 + #include "processpptables.h" 28 + #include <atom-types.h> 29 + #include <atombios.h> 30 + #include "pptable.h" 31 + #include "power_state.h" 32 + #include "hwmgr.h" 33 + #include "hardwaremanager.h" 34 + 35 + 36 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 37 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 38 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 39 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 40 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 41 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 42 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 43 + #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 44 + 45 + #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6 46 + 47 + static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr, 48 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 49 + { 50 + uint16_t vce_table_offset = 0; 51 + 52 + if (le16_to_cpu(powerplay_table->usTableSize) >= 53 + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 54 + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 55 + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 56 + 57 + if (powerplay_table3->usExtendendedHeaderOffset > 0) { 58 + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = 59 + (const ATOM_PPLIB_EXTENDEDHEADER *) 60 + (((unsigned long)powerplay_table3) + 61 + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 62 + if (le16_to_cpu(extended_header->usSize) >= 63 + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) 64 + vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset); 65 + } 66 + } 67 + 68 + return vce_table_offset; 69 + } 70 + 71 + static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr, 72 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 73 + { 74 + uint16_t table_offset = get_vce_table_offset(hwmgr, 75 + powerplay_table); 76 + 77 + if (table_offset > 0) 78 + return table_offset + 1; 79 + 80 + return 0; 81 + } 82 + 83 + static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr, 84 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 85 + { 86 + uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, 87 + powerplay_table); 88 + uint16_t table_size = 0; 89 + 90 + if (table_offset > 0) { 91 + const VCEClockInfoArray *p = (const VCEClockInfoArray *) 92 + (((unsigned long) powerplay_table) + table_offset); 93 + table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo); 94 + } 95 + 96 + return table_size; 97 + } 98 + 99 + static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr, 100 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 101 + { 102 + uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, 103 + powerplay_table); 104 + 105 + if (table_offset > 0) 106 + return table_offset + get_vce_clock_info_array_size(hwmgr, 107 + powerplay_table); 108 + 109 + return 0; 110 + } 111 + 112 + static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr, 113 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 114 + { 115 + uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); 116 + uint16_t table_size = 0; 117 + 118 + if (table_offset > 0) { 119 + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable = 120 + (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset); 121 + 122 + table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record); 123 + } 124 + return table_size; 125 + } 126 + 127 + static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 128 + { 129 + uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); 130 + 131 + if (table_offset > 0) 132 + return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table); 133 + 134 + return 0; 135 + } 136 + 137 + static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table( 138 + struct pp_hwmgr *hwmgr, 139 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 140 + { 141 + uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table); 142 + 143 + if (table_offset > 0) 144 + return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset); 145 + 146 + return NULL; 147 + } 148 + 149 + static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr, 150 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 151 + { 152 + uint16_t uvd_table_offset = 0; 153 + 154 + if (le16_to_cpu(powerplay_table->usTableSize) >= 155 + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 156 + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 157 + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 158 + if (powerplay_table3->usExtendendedHeaderOffset > 0) { 159 + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = 160 + (const ATOM_PPLIB_EXTENDEDHEADER *) 161 + (((unsigned long)powerplay_table3) + 162 + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 163 + if (le16_to_cpu(extended_header->usSize) >= 164 + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) 165 + uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset); 166 + } 167 + } 168 + return uvd_table_offset; 169 + } 170 + 171 + static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr, 172 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 173 + { 174 + uint16_t table_offset = get_uvd_table_offset(hwmgr, 175 + powerplay_table); 176 + 177 + if (table_offset > 0) 178 + return table_offset + 1; 179 + return 0; 180 + } 181 + 182 + static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr, 183 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 184 + { 185 + uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, 186 + powerplay_table); 187 + uint16_t table_size = 0; 188 + 189 + if (table_offset > 0) { 190 + const UVDClockInfoArray *p = (const UVDClockInfoArray *) 191 + (((unsigned long) powerplay_table) 192 + + table_offset); 193 + table_size = sizeof(UCHAR) + 194 + p->ucNumEntries * sizeof(UVDClockInfo); 195 + } 196 + 197 + return table_size; 198 + } 199 + 200 + static uint16_t get_uvd_clock_voltage_limit_table_offset( 201 + struct pp_hwmgr *hwmgr, 202 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 203 + { 204 + uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, 205 + powerplay_table); 206 + 207 + if (table_offset > 0) 208 + return table_offset + 209 + get_uvd_clock_info_array_size(hwmgr, powerplay_table); 210 + 211 + return 0; 212 + } 213 + 214 + static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr, 215 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 216 + { 217 + uint16_t samu_table_offset = 0; 218 + 219 + if (le16_to_cpu(powerplay_table->usTableSize) >= 220 + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 221 + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 222 + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 223 + if (powerplay_table3->usExtendendedHeaderOffset > 0) { 224 + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = 225 + (const ATOM_PPLIB_EXTENDEDHEADER *) 226 + (((unsigned long)powerplay_table3) + 227 + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 228 + if (le16_to_cpu(extended_header->usSize) >= 229 + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) 230 + samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset); 231 + } 232 + } 233 + 234 + return samu_table_offset; 235 + } 236 + 237 + static uint16_t get_samu_clock_voltage_limit_table_offset( 238 + struct pp_hwmgr *hwmgr, 239 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 240 + { 241 + uint16_t table_offset = get_samu_table_offset(hwmgr, 242 + powerplay_table); 243 + 244 + if (table_offset > 0) 245 + return table_offset + 1; 246 + 247 + return 0; 248 + } 249 + 250 + static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr, 251 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 252 + { 253 + uint16_t acp_table_offset = 0; 254 + 255 + if (le16_to_cpu(powerplay_table->usTableSize) >= 256 + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 257 + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 258 + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 259 + if (powerplay_table3->usExtendendedHeaderOffset > 0) { 260 + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = 261 + (const ATOM_PPLIB_EXTENDEDHEADER *) 262 + (((unsigned long)powerplay_table3) + 263 + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 264 + if (le16_to_cpu(pExtendedHeader->usSize) >= 265 + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) 266 + acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset); 267 + } 268 + } 269 + 270 + return acp_table_offset; 271 + } 272 + 273 + static uint16_t get_acp_clock_voltage_limit_table_offset( 274 + struct pp_hwmgr *hwmgr, 275 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 276 + { 277 + uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table); 278 + 279 + if (tableOffset > 0) 280 + return tableOffset + 1; 281 + 282 + return 0; 283 + } 284 + 285 + static uint16_t get_cacp_tdp_table_offset( 286 + struct pp_hwmgr *hwmgr, 287 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 288 + { 289 + uint16_t cacTdpTableOffset = 0; 290 + 291 + if (le16_to_cpu(powerplay_table->usTableSize) >= 292 + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 293 + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 294 + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 295 + if (powerplay_table3->usExtendendedHeaderOffset > 0) { 296 + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = 297 + (const ATOM_PPLIB_EXTENDEDHEADER *) 298 + (((unsigned long)powerplay_table3) + 299 + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 300 + if (le16_to_cpu(pExtendedHeader->usSize) >= 301 + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) 302 + cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset); 303 + } 304 + } 305 + 306 + return cacTdpTableOffset; 307 + } 308 + 309 + static int get_cac_tdp_table(struct pp_hwmgr *hwmgr, 310 + struct phm_cac_tdp_table **ptable, 311 + const ATOM_PowerTune_Table *table, 312 + uint16_t us_maximum_power_delivery_limit) 313 + { 314 + unsigned long table_size; 315 + struct phm_cac_tdp_table *tdp_table; 316 + 317 + table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table); 318 + 319 + tdp_table = kzalloc(table_size, GFP_KERNEL); 320 + if (NULL == tdp_table) 321 + return -ENOMEM; 322 + 323 + tdp_table->usTDP = le16_to_cpu(table->usTDP); 324 + tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP); 325 + tdp_table->usTDC = le16_to_cpu(table->usTDC); 326 + tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit); 327 + tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit); 328 + tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage); 329 + tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage); 330 + tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit; 331 + 332 + *ptable = tdp_table; 333 + 334 + return 0; 335 + } 336 + 337 + static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr, 338 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 339 + { 340 + uint16_t sclk_vdd_gfx_table_offset = 0; 341 + 342 + if (le16_to_cpu(powerplay_table->usTableSize) >= 343 + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 344 + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 345 + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 346 + if (powerplay_table3->usExtendendedHeaderOffset > 0) { 347 + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = 348 + (const ATOM_PPLIB_EXTENDEDHEADER *) 349 + (((unsigned long)powerplay_table3) + 350 + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 351 + if (le16_to_cpu(pExtendedHeader->usSize) >= 352 + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) 353 + sclk_vdd_gfx_table_offset = 354 + le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset); 355 + } 356 + } 357 + 358 + return sclk_vdd_gfx_table_offset; 359 + } 360 + 361 + static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset( 362 + struct pp_hwmgr *hwmgr, 363 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 364 + { 365 + uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table); 366 + 367 + if (tableOffset > 0) 368 + return tableOffset; 369 + 370 + return 0; 371 + } 372 + 373 + 374 + static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, 375 + struct phm_clock_voltage_dependency_table **ptable, 376 + const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table) 377 + { 378 + 379 + unsigned long table_size, i; 380 + struct phm_clock_voltage_dependency_table *dep_table; 381 + 382 + table_size = sizeof(unsigned long) + 383 + sizeof(struct phm_clock_voltage_dependency_table) 384 + * table->ucNumEntries; 385 + 386 + dep_table = kzalloc(table_size, GFP_KERNEL); 387 + if (NULL == dep_table) 388 + return -ENOMEM; 389 + 390 + dep_table->count = (unsigned long)table->ucNumEntries; 391 + 392 + for (i = 0; i < dep_table->count; i++) { 393 + dep_table->entries[i].clk = 394 + ((unsigned long)table->entries[i].ucClockHigh << 16) | 395 + le16_to_cpu(table->entries[i].usClockLow); 396 + dep_table->entries[i].v = 397 + (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 398 + } 399 + 400 + *ptable = dep_table; 401 + 402 + return 0; 403 + } 404 + 405 + static int get_valid_clk(struct pp_hwmgr *hwmgr, 406 + struct phm_clock_array **ptable, 407 + const struct phm_clock_voltage_dependency_table *table) 408 + { 409 + unsigned long table_size, i; 410 + struct phm_clock_array *clock_table; 411 + 412 + table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count; 413 + clock_table = kzalloc(table_size, GFP_KERNEL); 414 + if (NULL == clock_table) 415 + return -ENOMEM; 416 + 417 + clock_table->count = (unsigned long)table->count; 418 + 419 + for (i = 0; i < clock_table->count; i++) 420 + clock_table->values[i] = (unsigned long)table->entries[i].clk; 421 + 422 + *ptable = clock_table; 423 + 424 + return 0; 425 + } 426 + 427 + static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr, 428 + struct phm_clock_and_voltage_limits *limits, 429 + const ATOM_PPLIB_Clock_Voltage_Limit_Table *table) 430 + { 431 + limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) | 432 + le16_to_cpu(table->entries[0].usSclkLow); 433 + limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) | 434 + le16_to_cpu(table->entries[0].usMclkLow); 435 + limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc); 436 + limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci); 437 + 438 + return 0; 439 + } 440 + 441 + 442 + static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, 443 + enum phm_platform_caps cap) 444 + { 445 + if (enable) 446 + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); 447 + else 448 + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); 449 + } 450 + 451 + static int set_platform_caps(struct pp_hwmgr *hwmgr, 452 + unsigned long powerplay_caps) 453 + { 454 + set_hw_cap( 455 + hwmgr, 456 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY), 457 + PHM_PlatformCaps_PowerPlaySupport 458 + ); 459 + 460 + set_hw_cap( 461 + hwmgr, 462 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), 463 + PHM_PlatformCaps_BiosPowerSourceControl 464 + ); 465 + 466 + set_hw_cap( 467 + hwmgr, 468 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s), 469 + PHM_PlatformCaps_EnableASPML0s 470 + ); 471 + 472 + set_hw_cap( 473 + hwmgr, 474 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1), 475 + PHM_PlatformCaps_EnableASPML1 476 + ); 477 + 478 + set_hw_cap( 479 + hwmgr, 480 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS), 481 + PHM_PlatformCaps_EnableBackbias 482 + ); 483 + 484 + set_hw_cap( 485 + hwmgr, 486 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC), 487 + PHM_PlatformCaps_AutomaticDCTransition 488 + ); 489 + 490 + set_hw_cap( 491 + hwmgr, 492 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY), 493 + PHM_PlatformCaps_GeminiPrimary 494 + ); 495 + 496 + set_hw_cap( 497 + hwmgr, 498 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC), 499 + PHM_PlatformCaps_StepVddc 500 + ); 501 + 502 + set_hw_cap( 503 + hwmgr, 504 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL), 505 + PHM_PlatformCaps_EnableVoltageControl 506 + ); 507 + 508 + set_hw_cap( 509 + hwmgr, 510 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL), 511 + PHM_PlatformCaps_EnableSideportControl 512 + ); 513 + 514 + set_hw_cap( 515 + hwmgr, 516 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1), 517 + PHM_PlatformCaps_TurnOffPll_ASPML1 518 + ); 519 + 520 + set_hw_cap( 521 + hwmgr, 522 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL), 523 + PHM_PlatformCaps_EnableHTLinkControl 524 + ); 525 + 526 + set_hw_cap( 527 + hwmgr, 528 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL), 529 + PHM_PlatformCaps_EnableMVDDControl 530 + ); 531 + 532 + set_hw_cap( 533 + hwmgr, 534 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL), 535 + PHM_PlatformCaps_ControlVDDCI 536 + ); 537 + 538 + set_hw_cap( 539 + hwmgr, 540 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT), 541 + PHM_PlatformCaps_RegulatorHot 542 + ); 543 + 544 + set_hw_cap( 545 + hwmgr, 546 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT), 547 + PHM_PlatformCaps_BootStateOnAlert 548 + ); 549 + 550 + set_hw_cap( 551 + hwmgr, 552 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT), 553 + PHM_PlatformCaps_DontWaitForVBlankOnAlert 554 + ); 555 + 556 + set_hw_cap( 557 + hwmgr, 558 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO), 559 + PHM_PlatformCaps_BACO 560 + ); 561 + 562 + set_hw_cap( 563 + hwmgr, 564 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE), 565 + PHM_PlatformCaps_NewCACVoltage 566 + ); 567 + 568 + set_hw_cap( 569 + hwmgr, 570 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY), 571 + PHM_PlatformCaps_RevertGPIO5Polarity 572 + ); 573 + 574 + set_hw_cap( 575 + hwmgr, 576 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17), 577 + PHM_PlatformCaps_Thermal2GPIO17 578 + ); 579 + 580 + set_hw_cap( 581 + hwmgr, 582 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE), 583 + PHM_PlatformCaps_VRHotGPIOConfigurable 584 + ); 585 + 586 + set_hw_cap( 587 + hwmgr, 588 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION), 589 + PHM_PlatformCaps_TempInversion 590 + ); 591 + 592 + set_hw_cap( 593 + hwmgr, 594 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV), 595 + PHM_PlatformCaps_EVV 596 + ); 597 + 598 + set_hw_cap( 599 + hwmgr, 600 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), 601 + PHM_PlatformCaps_CombinePCCWithThermalSignal 602 + ); 603 + 604 + set_hw_cap( 605 + hwmgr, 606 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), 607 + PHM_PlatformCaps_LoadPostProductionFirmware 608 + ); 609 + 610 + set_hw_cap( 611 + hwmgr, 612 + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC), 613 + PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc 614 + ); 615 + 616 + return 0; 617 + } 618 + 619 + static PP_StateClassificationFlags make_classification_flags( 620 + struct pp_hwmgr *hwmgr, 621 + USHORT classification, 622 + USHORT classification2) 623 + { 624 + PP_StateClassificationFlags result = 0; 625 + 626 + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) 627 + result |= PP_StateClassificationFlag_Boot; 628 + 629 + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) 630 + result |= PP_StateClassificationFlag_Thermal; 631 + 632 + if (classification & 633 + ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 634 + result |= PP_StateClassificationFlag_LimitedPowerSource; 635 + 636 + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) 637 + result |= PP_StateClassificationFlag_Rest; 638 + 639 + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) 640 + result |= PP_StateClassificationFlag_Forced; 641 + 642 + if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 643 + result |= PP_StateClassificationFlag_3DPerformance; 644 + 645 + 646 + if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) 647 + result |= PP_StateClassificationFlag_ACOverdriveTemplate; 648 + 649 + if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 650 + result |= PP_StateClassificationFlag_Uvd; 651 + 652 + if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 653 + result |= PP_StateClassificationFlag_UvdHD; 654 + 655 + if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 656 + result |= PP_StateClassificationFlag_UvdSD; 657 + 658 + if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 659 + result |= PP_StateClassificationFlag_HD2; 660 + 661 + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) 662 + result |= PP_StateClassificationFlag_ACPI; 663 + 664 + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 665 + result |= PP_StateClassificationFlag_LimitedPowerSource_2; 666 + 667 + 668 + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 669 + result |= PP_StateClassificationFlag_ULV; 670 + 671 + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 672 + result |= PP_StateClassificationFlag_UvdMVC; 673 + 674 + return result; 675 + } 676 + 677 + static int init_non_clock_fields(struct pp_hwmgr *hwmgr, 678 + struct pp_power_state *ps, 679 + uint8_t version, 680 + const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) { 681 + unsigned long rrr_index; 682 + unsigned long tmp; 683 + 684 + ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) & 685 + ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; 686 + ps->classification.flags = make_classification_flags(hwmgr, 687 + le16_to_cpu(pnon_clock_info->usClassification), 688 + le16_to_cpu(pnon_clock_info->usClassification2)); 689 + 690 + ps->classification.temporary_state = false; 691 + ps->classification.to_be_deleted = false; 692 + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 693 + ATOM_PPLIB_SINGLE_DISPLAY_ONLY; 694 + 695 + ps->validation.singleDisplayOnly = (0 != tmp); 696 + 697 + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 698 + ATOM_PPLIB_DISALLOW_ON_DC; 699 + 700 + ps->validation.disallowOnDC = (0 != tmp); 701 + 702 + ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 703 + ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> 704 + ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; 705 + 706 + ps->pcie.lanes = 0; 707 + 708 + ps->display.disableFrameModulation = false; 709 + 710 + rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 711 + ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >> 712 + ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT; 713 + 714 + if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) { 715 + static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \ 716 + { 0, 50, 0 }; 717 + 718 + ps->display.refreshrateSource = PP_RefreshrateSource_Explicit; 719 + ps->display.explicitRefreshrate = look_up[rrr_index]; 720 + ps->display.limitRefreshrate = true; 721 + 722 + if (ps->display.explicitRefreshrate == 0) 723 + ps->display.limitRefreshrate = false; 724 + } else 725 + ps->display.limitRefreshrate = false; 726 + 727 + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 728 + ATOM_PPLIB_ENABLE_VARIBRIGHT; 729 + 730 + ps->display.enableVariBright = (0 != tmp); 731 + 732 + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 733 + ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF; 734 + 735 + ps->memory.dllOff = (0 != tmp); 736 + 737 + ps->memory.m3arb = (uint8_t)(le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 738 + ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT; 739 + 740 + ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * 741 + pnon_clock_info->ucMinTemperature; 742 + 743 + ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * 744 + pnon_clock_info->ucMaxTemperature; 745 + 746 + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 747 + ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING; 748 + 749 + ps->software.disableLoadBalancing = tmp; 750 + 751 + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 752 + ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS; 753 + 754 + ps->software.enableSleepForTimestamps = (0 != tmp); 755 + 756 + ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower; 757 + 758 + if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) { 759 + ps->uvd_clocks.VCLK = pnon_clock_info->ulVCLK; 760 + ps->uvd_clocks.DCLK = pnon_clock_info->ulDCLK; 761 + } else { 762 + ps->uvd_clocks.VCLK = 0; 763 + ps->uvd_clocks.DCLK = 0; 764 + } 765 + 766 + return 0; 767 + } 768 + 769 + static ULONG size_of_entry_v2(ULONG num_dpm_levels) 770 + { 771 + return (sizeof(UCHAR) + sizeof(UCHAR) + 772 + (num_dpm_levels * sizeof(UCHAR))); 773 + } 774 + 775 + static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( 776 + const StateArray * pstate_arrays, 777 + ULONG entry_index) 778 + { 779 + ULONG i; 780 + const ATOM_PPLIB_STATE_V2 *pstate; 781 + 782 + pstate = pstate_arrays->states; 783 + if (entry_index <= pstate_arrays->ucNumEntries) { 784 + for (i = 0; i < entry_index; i++) 785 + pstate = (ATOM_PPLIB_STATE_V2 *)( 786 + (unsigned long)pstate + 787 + size_of_entry_v2(pstate->ucNumDPMLevels)); 788 + } 789 + return pstate; 790 + } 791 + 792 + 793 + static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( 794 + struct pp_hwmgr *hwmgr) 795 + { 796 + const void *table_addr = NULL; 797 + uint8_t frev, crev; 798 + uint16_t size; 799 + 800 + table_addr = cgs_atom_get_data_table(hwmgr->device, 801 + GetIndexIntoMasterTable(DATA, PowerPlayInfo), 802 + &size, &frev, &crev); 803 + 804 + hwmgr->soft_pp_table = table_addr; 805 + 806 + return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr; 807 + } 808 + 809 + 810 + int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, 811 + unsigned long *num_of_entries) 812 + { 813 + const StateArray *pstate_arrays; 814 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); 815 + 816 + if (powerplay_table == NULL) 817 + return -1; 818 + 819 + if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { 820 + pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + 821 + le16_to_cpu(powerplay_table->usStateArrayOffset)); 822 + 823 + *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries); 824 + } else 825 + *num_of_entries = (unsigned long)(powerplay_table->ucNumStates); 826 + 827 + return 0; 828 + } 829 + 830 + int pp_tables_get_entry(struct pp_hwmgr *hwmgr, 831 + unsigned long entry_index, 832 + struct pp_power_state *ps, 833 + pp_tables_hw_clock_info_callback func) 834 + { 835 + int i; 836 + const StateArray *pstate_arrays; 837 + const ATOM_PPLIB_STATE_V2 *pstate_entry_v2; 838 + const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info; 839 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); 840 + int result = 0; 841 + int res = 0; 842 + 843 + const ClockInfoArray *pclock_arrays; 844 + 845 + const NonClockInfoArray *pnon_clock_arrays; 846 + 847 + const ATOM_PPLIB_STATE *pstate_entry; 848 + 849 + if (powerplay_table == NULL) 850 + return -1; 851 + 852 + ps->classification.bios_index = entry_index; 853 + 854 + if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { 855 + pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + 856 + le16_to_cpu(powerplay_table->usStateArrayOffset)); 857 + 858 + if (entry_index > pstate_arrays->ucNumEntries) 859 + return -1; 860 + 861 + pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index); 862 + pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + 863 + le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); 864 + 865 + pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) + 866 + le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset)); 867 + 868 + pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) + 869 + (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize)); 870 + 871 + result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info); 872 + 873 + for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) { 874 + const void *pclock_info = (const void *)( 875 + (unsigned long)(pclock_arrays->clockInfo) + 876 + (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize)); 877 + res = func(hwmgr, &ps->hardware, i, pclock_info); 878 + if ((0 == result) && (0 != res)) 879 + result = res; 880 + } 881 + } else { 882 + if (entry_index > powerplay_table->ucNumStates) 883 + return -1; 884 + 885 + pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + powerplay_table->usStateArrayOffset + 886 + entry_index * powerplay_table->ucStateEntrySize); 887 + 888 + pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table + 889 + le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) + 890 + pstate_entry->ucNonClockStateIndex * 891 + powerplay_table->ucNonClockSize); 892 + 893 + result = init_non_clock_fields(hwmgr, ps, 894 + powerplay_table->ucNonClockSize, 895 + pnon_clock_info); 896 + 897 + for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) { 898 + const void *pclock_info = (const void *)((unsigned long)powerplay_table + 899 + le16_to_cpu(powerplay_table->usClockInfoArrayOffset) + 900 + pstate_entry->ucClockStateIndices[i] * 901 + powerplay_table->ucClockInfoSize); 902 + 903 + int res = func(hwmgr, &ps->hardware, i, pclock_info); 904 + 905 + if ((0 == result) && (0 != res)) 906 + result = res; 907 + } 908 + } 909 + 910 + if ((0 == result) && 911 + (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) 912 + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware)); 913 + 914 + return result; 915 + } 916 + 917 + 918 + 919 + static int init_powerplay_tables( 920 + struct pp_hwmgr *hwmgr, 921 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table 922 + ) 923 + { 924 + return 0; 925 + } 926 + 927 + 928 + static int init_thermal_controller( 929 + struct pp_hwmgr *hwmgr, 930 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 931 + { 932 + return 0; 933 + } 934 + 935 + static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr, 936 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, 937 + const ATOM_FIRMWARE_INFO_V1_4 *fw_info) 938 + { 939 + hwmgr->platform_descriptor.overdriveLimit.engineClock = 940 + le32_to_cpu(fw_info->ulASICMaxEngineClock); 941 + 942 + hwmgr->platform_descriptor.overdriveLimit.memoryClock = 943 + le32_to_cpu(fw_info->ulASICMaxMemoryClock); 944 + 945 + hwmgr->platform_descriptor.maxOverdriveVDDC = 946 + le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF; 947 + 948 + hwmgr->platform_descriptor.minOverdriveVDDC = 949 + le16_to_cpu(fw_info->usBootUpVDDCVoltage); 950 + 951 + hwmgr->platform_descriptor.maxOverdriveVDDC = 952 + le16_to_cpu(fw_info->usBootUpVDDCVoltage); 953 + 954 + hwmgr->platform_descriptor.overdriveVDDCStep = 0; 955 + return 0; 956 + } 957 + 958 + static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr, 959 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, 960 + const ATOM_FIRMWARE_INFO_V2_1 *fw_info) 961 + { 962 + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3; 963 + const ATOM_PPLIB_EXTENDEDHEADER *header; 964 + 965 + if (le16_to_cpu(powerplay_table->usTableSize) < 966 + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) 967 + return 0; 968 + 969 + powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 970 + 971 + if (0 == powerplay_table3->usExtendendedHeaderOffset) 972 + return 0; 973 + 974 + header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) + 975 + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 976 + 977 + hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock); 978 + hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock); 979 + 980 + 981 + hwmgr->platform_descriptor.minOverdriveVDDC = 0; 982 + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; 983 + hwmgr->platform_descriptor.overdriveVDDCStep = 0; 984 + 985 + return 0; 986 + } 987 + 988 + static int init_overdrive_limits(struct pp_hwmgr *hwmgr, 989 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 990 + { 991 + int result; 992 + uint8_t frev, crev; 993 + uint16_t size; 994 + 995 + const ATOM_COMMON_TABLE_HEADER *fw_info = NULL; 996 + 997 + hwmgr->platform_descriptor.overdriveLimit.engineClock = 0; 998 + hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0; 999 + hwmgr->platform_descriptor.minOverdriveVDDC = 0; 1000 + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; 1001 + 1002 + /* We assume here that fw_info is unchanged if this call fails.*/ 1003 + fw_info = cgs_atom_get_data_table(hwmgr->device, 1004 + GetIndexIntoMasterTable(DATA, FirmwareInfo), 1005 + &size, &frev, &crev); 1006 + 1007 + if ((fw_info->ucTableFormatRevision == 1) 1008 + && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V1_4))) 1009 + result = init_overdrive_limits_V1_4(hwmgr, 1010 + powerplay_table, 1011 + (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info); 1012 + 1013 + else if ((fw_info->ucTableFormatRevision == 2) 1014 + && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) 1015 + result = init_overdrive_limits_V2_1(hwmgr, 1016 + powerplay_table, 1017 + (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info); 1018 + 1019 + if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 1020 + && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0 1021 + && !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1022 + PHM_PlatformCaps_OverdriveDisabledByPowerBudget)) 1023 + phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1024 + PHM_PlatformCaps_ACOverdriveSupport); 1025 + 1026 + return result; 1027 + } 1028 + 1029 + static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1030 + struct phm_uvd_clock_voltage_dependency_table **ptable, 1031 + const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table, 1032 + const UVDClockInfoArray *array) 1033 + { 1034 + unsigned long table_size, i; 1035 + struct phm_uvd_clock_voltage_dependency_table *uvd_table; 1036 + 1037 + table_size = sizeof(unsigned long) + 1038 + sizeof(struct phm_uvd_clock_voltage_dependency_table) * 1039 + table->numEntries; 1040 + 1041 + uvd_table = kzalloc(table_size, GFP_KERNEL); 1042 + if (NULL == uvd_table) 1043 + return -ENOMEM; 1044 + 1045 + uvd_table->count = table->numEntries; 1046 + 1047 + for (i = 0; i < table->numEntries; i++) { 1048 + const UVDClockInfo *entry = 1049 + &array->entries[table->entries[i].ucUVDClockInfoIndex]; 1050 + uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1051 + uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16) 1052 + | le16_to_cpu(entry->usVClkLow); 1053 + uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16) 1054 + | le16_to_cpu(entry->usDClkLow); 1055 + } 1056 + 1057 + *ptable = uvd_table; 1058 + 1059 + return 0; 1060 + } 1061 + 1062 + static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1063 + struct phm_vce_clock_voltage_dependency_table **ptable, 1064 + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table, 1065 + const VCEClockInfoArray *array) 1066 + { 1067 + unsigned long table_size, i; 1068 + struct phm_vce_clock_voltage_dependency_table *vce_table = NULL; 1069 + 1070 + table_size = sizeof(unsigned long) + 1071 + sizeof(struct phm_vce_clock_voltage_dependency_table) 1072 + * table->numEntries; 1073 + 1074 + vce_table = kzalloc(table_size, GFP_KERNEL); 1075 + if (NULL == vce_table) 1076 + return -ENOMEM; 1077 + 1078 + vce_table->count = table->numEntries; 1079 + for (i = 0; i < table->numEntries; i++) { 1080 + const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex]; 1081 + 1082 + vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1083 + vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16) 1084 + | le16_to_cpu(entry->usEVClkLow); 1085 + vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16) 1086 + | le16_to_cpu(entry->usECClkLow); 1087 + } 1088 + 1089 + *ptable = vce_table; 1090 + 1091 + return 0; 1092 + } 1093 + 1094 + static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1095 + struct phm_samu_clock_voltage_dependency_table **ptable, 1096 + const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table) 1097 + { 1098 + unsigned long table_size, i; 1099 + struct phm_samu_clock_voltage_dependency_table *samu_table; 1100 + 1101 + table_size = sizeof(unsigned long) + 1102 + sizeof(struct phm_samu_clock_voltage_dependency_table) * 1103 + table->numEntries; 1104 + 1105 + samu_table = kzalloc(table_size, GFP_KERNEL); 1106 + if (NULL == samu_table) 1107 + return -ENOMEM; 1108 + 1109 + samu_table->count = table->numEntries; 1110 + 1111 + for (i = 0; i < table->numEntries; i++) { 1112 + samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1113 + samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16) 1114 + | le16_to_cpu(table->entries[i].usSAMClockLow); 1115 + } 1116 + 1117 + *ptable = samu_table; 1118 + 1119 + return 0; 1120 + } 1121 + 1122 + static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1123 + struct phm_acp_clock_voltage_dependency_table **ptable, 1124 + const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table) 1125 + { 1126 + unsigned table_size, i; 1127 + struct phm_acp_clock_voltage_dependency_table *acp_table; 1128 + 1129 + table_size = sizeof(unsigned long) + 1130 + sizeof(struct phm_acp_clock_voltage_dependency_table) * 1131 + table->numEntries; 1132 + 1133 + acp_table = kzalloc(table_size, GFP_KERNEL); 1134 + if (NULL == acp_table) 1135 + return -ENOMEM; 1136 + 1137 + acp_table->count = (unsigned long)table->numEntries; 1138 + 1139 + for (i = 0; i < table->numEntries; i++) { 1140 + acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1141 + acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16) 1142 + | le16_to_cpu(table->entries[i].usACPClockLow); 1143 + } 1144 + 1145 + *ptable = acp_table; 1146 + 1147 + return 0; 1148 + } 1149 + 1150 + static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr, 1151 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1152 + { 1153 + ATOM_PPLIB_Clock_Voltage_Dependency_Table *table; 1154 + ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table; 1155 + int result = 0; 1156 + 1157 + uint16_t vce_clock_info_array_offset; 1158 + uint16_t uvd_clock_info_array_offset; 1159 + uint16_t table_offset; 1160 + 1161 + hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; 1162 + hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; 1163 + hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; 1164 + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; 1165 + hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; 1166 + hwmgr->dyn_state.vce_clocl_voltage_dependency_table = NULL; 1167 + hwmgr->dyn_state.uvd_clocl_voltage_dependency_table = NULL; 1168 + hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; 1169 + hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; 1170 + hwmgr->dyn_state.ppm_parameter_table = NULL; 1171 + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; 1172 + 1173 + vce_clock_info_array_offset = get_vce_clock_info_array_offset( 1174 + hwmgr, powerplay_table); 1175 + table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, 1176 + powerplay_table); 1177 + if (vce_clock_info_array_offset > 0 && table_offset > 0) { 1178 + const VCEClockInfoArray *array = (const VCEClockInfoArray *) 1179 + (((unsigned long) powerplay_table) + 1180 + vce_clock_info_array_offset); 1181 + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table = 1182 + (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 1183 + (((unsigned long) powerplay_table) + table_offset); 1184 + result = get_vce_clock_voltage_limit_table(hwmgr, 1185 + &hwmgr->dyn_state.vce_clocl_voltage_dependency_table, 1186 + table, array); 1187 + } 1188 + 1189 + uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table); 1190 + table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table); 1191 + 1192 + if (uvd_clock_info_array_offset > 0 && table_offset > 0) { 1193 + const UVDClockInfoArray *array = (const UVDClockInfoArray *) 1194 + (((unsigned long) powerplay_table) + 1195 + uvd_clock_info_array_offset); 1196 + const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable = 1197 + (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 1198 + (((unsigned long) powerplay_table) + table_offset); 1199 + result = get_uvd_clock_voltage_limit_table(hwmgr, 1200 + &hwmgr->dyn_state.uvd_clocl_voltage_dependency_table, ptable, array); 1201 + } 1202 + 1203 + table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr, 1204 + powerplay_table); 1205 + 1206 + if (table_offset > 0) { 1207 + const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable = 1208 + (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 1209 + (((unsigned long) powerplay_table) + table_offset); 1210 + result = get_samu_clock_voltage_limit_table(hwmgr, 1211 + &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable); 1212 + } 1213 + 1214 + table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr, 1215 + powerplay_table); 1216 + 1217 + if (table_offset > 0) { 1218 + const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable = 1219 + (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 1220 + (((unsigned long) powerplay_table) + table_offset); 1221 + result = get_acp_clock_voltage_limit_table(hwmgr, 1222 + &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable); 1223 + } 1224 + 1225 + table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table); 1226 + if (table_offset > 0) { 1227 + UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset); 1228 + 1229 + if (rev_id > 0) { 1230 + const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table = 1231 + (const ATOM_PPLIB_POWERTUNE_Table_V1 *) 1232 + (((unsigned long) powerplay_table) + table_offset); 1233 + result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table, 1234 + &tune_table->power_tune_table, 1235 + le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit)); 1236 + hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = 1237 + le16_to_cpu(tune_table->usTjMax); 1238 + } else { 1239 + const ATOM_PPLIB_POWERTUNE_Table *tune_table = 1240 + (const ATOM_PPLIB_POWERTUNE_Table *) 1241 + (((unsigned long) powerplay_table) + table_offset); 1242 + result = get_cac_tdp_table(hwmgr, 1243 + &hwmgr->dyn_state.cac_dtp_table, 1244 + &tune_table->power_tune_table, 255); 1245 + } 1246 + } 1247 + 1248 + if (le16_to_cpu(powerplay_table->usTableSize) >= 1249 + sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { 1250 + const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = 1251 + (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; 1252 + if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) { 1253 + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1254 + (((unsigned long) powerplay_table4) + 1255 + powerplay_table4->usVddcDependencyOnSCLKOffset); 1256 + result = get_clock_voltage_dependency_table(hwmgr, 1257 + &hwmgr->dyn_state.vddc_dependency_on_sclk, table); 1258 + } 1259 + 1260 + if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) { 1261 + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1262 + (((unsigned long) powerplay_table4) + 1263 + powerplay_table4->usVddciDependencyOnMCLKOffset); 1264 + result = get_clock_voltage_dependency_table(hwmgr, 1265 + &hwmgr->dyn_state.vddci_dependency_on_mclk, table); 1266 + } 1267 + 1268 + if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) { 1269 + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1270 + (((unsigned long) powerplay_table4) + 1271 + powerplay_table4->usVddcDependencyOnMCLKOffset); 1272 + result = get_clock_voltage_dependency_table(hwmgr, 1273 + &hwmgr->dyn_state.vddc_dependency_on_mclk, table); 1274 + } 1275 + 1276 + if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) { 1277 + limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 1278 + (((unsigned long) powerplay_table4) + 1279 + powerplay_table4->usMaxClockVoltageOnDCOffset); 1280 + result = get_clock_voltage_limit(hwmgr, 1281 + &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table); 1282 + } 1283 + 1284 + if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) && 1285 + (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count)) 1286 + result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values, 1287 + hwmgr->dyn_state.vddc_dependency_on_mclk); 1288 + 1289 + if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) && 1290 + (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count)) 1291 + result = get_valid_clk(hwmgr, 1292 + &hwmgr->dyn_state.valid_sclk_values, 1293 + hwmgr->dyn_state.vddc_dependency_on_sclk); 1294 + 1295 + if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) { 1296 + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1297 + (((unsigned long) powerplay_table4) + 1298 + powerplay_table4->usMvddDependencyOnMCLKOffset); 1299 + result = get_clock_voltage_dependency_table(hwmgr, 1300 + &hwmgr->dyn_state.mvdd_dependency_on_mclk, table); 1301 + } 1302 + } 1303 + 1304 + table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr, 1305 + powerplay_table); 1306 + 1307 + if (table_offset > 0) { 1308 + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1309 + (((unsigned long) powerplay_table) + table_offset); 1310 + result = get_clock_voltage_dependency_table(hwmgr, 1311 + &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table); 1312 + } 1313 + 1314 + return result; 1315 + } 1316 + 1317 + static int get_cac_leakage_table(struct pp_hwmgr *hwmgr, 1318 + struct phm_cac_leakage_table **ptable, 1319 + const ATOM_PPLIB_CAC_Leakage_Table *table) 1320 + { 1321 + struct phm_cac_leakage_table *cac_leakage_table; 1322 + unsigned long table_size, i; 1323 + 1324 + table_size = sizeof(ULONG) + 1325 + (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries); 1326 + 1327 + cac_leakage_table = kzalloc(table_size, GFP_KERNEL); 1328 + 1329 + cac_leakage_table->count = (ULONG)table->ucNumEntries; 1330 + 1331 + for (i = 0; i < cac_leakage_table->count; i++) { 1332 + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1333 + PHM_PlatformCaps_EVV)) { 1334 + cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1); 1335 + cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2); 1336 + cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3); 1337 + } else { 1338 + cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc); 1339 + cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue); 1340 + } 1341 + } 1342 + 1343 + *ptable = cac_leakage_table; 1344 + 1345 + return 0; 1346 + } 1347 + 1348 + static int get_platform_power_management_table(struct pp_hwmgr *hwmgr, 1349 + ATOM_PPLIB_PPM_Table *atom_ppm_table) 1350 + { 1351 + struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_PPLIB_PPM_Table), GFP_KERNEL); 1352 + 1353 + if (NULL == ptr) 1354 + return -ENOMEM; 1355 + 1356 + ptr->ppm_design = atom_ppm_table->ucPpmDesign; 1357 + ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); 1358 + ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP); 1359 + ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); 1360 + ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC); 1361 + ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); 1362 + ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP); 1363 + ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP); 1364 + ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); 1365 + ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax); 1366 + hwmgr->dyn_state.ppm_parameter_table = ptr; 1367 + 1368 + return 0; 1369 + } 1370 + 1371 + static int init_dpm2_parameters(struct pp_hwmgr *hwmgr, 1372 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1373 + { 1374 + int result = 0; 1375 + 1376 + if (le16_to_cpu(powerplay_table->usTableSize) >= 1377 + sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) { 1378 + const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 = 1379 + (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table; 1380 + const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 = 1381 + (const ATOM_PPLIB_POWERPLAYTABLE4 *) 1382 + (&ptable5->basicTable4); 1383 + const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 = 1384 + (const ATOM_PPLIB_POWERPLAYTABLE3 *) 1385 + (&ptable4->basicTable3); 1386 + const ATOM_PPLIB_EXTENDEDHEADER *extended_header; 1387 + uint16_t table_offset; 1388 + ATOM_PPLIB_PPM_Table *atom_ppm_table; 1389 + 1390 + hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit); 1391 + hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit); 1392 + 1393 + hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit); 1394 + hwmgr->platform_descriptor.TDPAdjustment = 0; 1395 + 1396 + hwmgr->platform_descriptor.VidAdjustment = 0; 1397 + hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; 1398 + hwmgr->platform_descriptor.VidMinLimit = 0; 1399 + hwmgr->platform_descriptor.VidMaxLimit = 1500000; 1400 + hwmgr->platform_descriptor.VidStep = 6250; 1401 + 1402 + hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit); 1403 + 1404 + if (hwmgr->platform_descriptor.TDPODLimit != 0) 1405 + phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1406 + PHM_PlatformCaps_PowerControl); 1407 + 1408 + hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold); 1409 + 1410 + hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage); 1411 + 1412 + hwmgr->dyn_state.cac_leakage_table = NULL; 1413 + 1414 + if (0 != ptable5->usCACLeakageTableOffset) { 1415 + const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table = 1416 + (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) + 1417 + le16_to_cpu(ptable5->usCACLeakageTableOffset)); 1418 + result = get_cac_leakage_table(hwmgr, 1419 + &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table); 1420 + } 1421 + 1422 + hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope); 1423 + 1424 + hwmgr->dyn_state.ppm_parameter_table = NULL; 1425 + 1426 + if (0 != ptable3->usExtendendedHeaderOffset) { 1427 + extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *) 1428 + (((unsigned long)powerplay_table) + 1429 + le16_to_cpu(ptable3->usExtendendedHeaderOffset)); 1430 + if ((extended_header->usPPMTableOffset > 0) && 1431 + le16_to_cpu(extended_header->usSize) >= 1432 + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) { 1433 + table_offset = le16_to_cpu(extended_header->usPPMTableOffset); 1434 + atom_ppm_table = (ATOM_PPLIB_PPM_Table *) 1435 + (((unsigned long)powerplay_table) + table_offset); 1436 + if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table)) 1437 + phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1438 + PHM_PlatformCaps_EnablePlatformPowerManagement); 1439 + } 1440 + } 1441 + } 1442 + return result; 1443 + } 1444 + 1445 + static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, 1446 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1447 + { 1448 + if (le16_to_cpu(powerplay_table->usTableSize) >= 1449 + sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { 1450 + const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = 1451 + (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; 1452 + 1453 + if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) { 1454 + const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable = 1455 + (ATOM_PPLIB_PhaseSheddingLimits_Table *) 1456 + (((unsigned long)powerplay_table4) + 1457 + le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset)); 1458 + struct phm_phase_shedding_limits_table *table; 1459 + unsigned long size, i; 1460 + 1461 + 1462 + size = sizeof(unsigned long) + 1463 + (sizeof(struct phm_phase_shedding_limits_table) * 1464 + ptable->ucNumEntries); 1465 + 1466 + table = kzalloc(size, GFP_KERNEL); 1467 + 1468 + table->count = (unsigned long)ptable->ucNumEntries; 1469 + 1470 + for (i = 0; i < table->count; i++) { 1471 + table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage); 1472 + table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16) 1473 + | le16_to_cpu(ptable->entries[i].usSclkLow); 1474 + table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16) 1475 + | le16_to_cpu(ptable->entries[i].usMclkLow); 1476 + } 1477 + hwmgr->dyn_state.vddc_phase_shed_limits_table = table; 1478 + } 1479 + } 1480 + 1481 + return 0; 1482 + } 1483 + 1484 + int get_number_of_vce_state_table_entries( 1485 + struct pp_hwmgr *hwmgr) 1486 + { 1487 + const ATOM_PPLIB_POWERPLAYTABLE *table = 1488 + get_powerplay_table(hwmgr); 1489 + const ATOM_PPLIB_VCE_State_Table *vce_table = 1490 + get_vce_state_table(hwmgr, table); 1491 + 1492 + if (vce_table > 0) 1493 + return vce_table->numEntries; 1494 + 1495 + return 0; 1496 + } 1497 + 1498 + int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, 1499 + unsigned long i, 1500 + struct PP_VCEState *vce_state, 1501 + void **clock_info, 1502 + unsigned long *flag) 1503 + { 1504 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); 1505 + 1506 + const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table); 1507 + 1508 + unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table); 1509 + 1510 + const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset); 1511 + 1512 + const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + powerplay_table->usClockInfoArrayOffset); 1513 + 1514 + const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i]; 1515 + 1516 + const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex]; 1517 + 1518 + unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F; 1519 + 1520 + *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX); 1521 + 1522 + vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | vce_clock_info->usEVClkLow; 1523 + vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | vce_clock_info->usECClkLow; 1524 + 1525 + *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize)); 1526 + 1527 + return 0; 1528 + } 1529 + 1530 + 1531 + static int pp_tables_initialize(struct pp_hwmgr *hwmgr) 1532 + { 1533 + int result; 1534 + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table; 1535 + 1536 + powerplay_table = get_powerplay_table(hwmgr); 1537 + 1538 + result = init_powerplay_tables(hwmgr, powerplay_table); 1539 + 1540 + if (0 == result) 1541 + result = set_platform_caps(hwmgr, 1542 + le32_to_cpu(powerplay_table->ulPlatformCaps)); 1543 + 1544 + if (0 == result) 1545 + result = init_thermal_controller(hwmgr, powerplay_table); 1546 + 1547 + if (0 == result) 1548 + result = init_overdrive_limits(hwmgr, powerplay_table); 1549 + 1550 + if (0 == result) 1551 + result = init_clock_voltage_dependency(hwmgr, 1552 + powerplay_table); 1553 + 1554 + if (0 == result) 1555 + result = init_dpm2_parameters(hwmgr, powerplay_table); 1556 + 1557 + if (0 == result) 1558 + result = init_phase_shedding_table(hwmgr, powerplay_table); 1559 + 1560 + return result; 1561 + } 1562 + 1563 + static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) 1564 + { 1565 + if (NULL != hwmgr->soft_pp_table) { 1566 + kfree(hwmgr->soft_pp_table); 1567 + hwmgr->soft_pp_table = NULL; 1568 + } 1569 + 1570 + if (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) { 1571 + kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); 1572 + hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; 1573 + } 1574 + 1575 + if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { 1576 + kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); 1577 + hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; 1578 + } 1579 + 1580 + if (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) { 1581 + kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); 1582 + hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; 1583 + } 1584 + 1585 + if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { 1586 + kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); 1587 + hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; 1588 + } 1589 + 1590 + if (NULL != hwmgr->dyn_state.valid_mclk_values) { 1591 + kfree(hwmgr->dyn_state.valid_mclk_values); 1592 + hwmgr->dyn_state.valid_mclk_values = NULL; 1593 + } 1594 + 1595 + if (NULL != hwmgr->dyn_state.valid_sclk_values) { 1596 + kfree(hwmgr->dyn_state.valid_sclk_values); 1597 + hwmgr->dyn_state.valid_sclk_values = NULL; 1598 + } 1599 + 1600 + if (NULL != hwmgr->dyn_state.cac_leakage_table) { 1601 + kfree(hwmgr->dyn_state.cac_leakage_table); 1602 + hwmgr->dyn_state.cac_leakage_table = NULL; 1603 + } 1604 + 1605 + if (NULL != hwmgr->dyn_state.vddc_phase_shed_limits_table) { 1606 + kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); 1607 + hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; 1608 + } 1609 + 1610 + if (NULL != hwmgr->dyn_state.vce_clocl_voltage_dependency_table) { 1611 + kfree(hwmgr->dyn_state.vce_clocl_voltage_dependency_table); 1612 + hwmgr->dyn_state.vce_clocl_voltage_dependency_table = NULL; 1613 + } 1614 + 1615 + if (NULL != hwmgr->dyn_state.uvd_clocl_voltage_dependency_table) { 1616 + kfree(hwmgr->dyn_state.uvd_clocl_voltage_dependency_table); 1617 + hwmgr->dyn_state.uvd_clocl_voltage_dependency_table = NULL; 1618 + } 1619 + 1620 + if (NULL != hwmgr->dyn_state.samu_clock_voltage_dependency_table) { 1621 + kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); 1622 + hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; 1623 + } 1624 + 1625 + if (NULL != hwmgr->dyn_state.acp_clock_voltage_dependency_table) { 1626 + kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); 1627 + hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; 1628 + } 1629 + 1630 + if (NULL != hwmgr->dyn_state.cac_dtp_table) { 1631 + kfree(hwmgr->dyn_state.cac_dtp_table); 1632 + hwmgr->dyn_state.cac_dtp_table = NULL; 1633 + } 1634 + 1635 + if (NULL != hwmgr->dyn_state.ppm_parameter_table) { 1636 + kfree(hwmgr->dyn_state.ppm_parameter_table); 1637 + hwmgr->dyn_state.ppm_parameter_table = NULL; 1638 + } 1639 + 1640 + if (NULL != hwmgr->dyn_state.vdd_gfx_dependency_on_sclk) { 1641 + kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); 1642 + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; 1643 + } 1644 + 1645 + if (NULL != hwmgr->dyn_state.vq_budgeting_table) { 1646 + kfree(hwmgr->dyn_state.vq_budgeting_table); 1647 + hwmgr->dyn_state.vq_budgeting_table = NULL; 1648 + } 1649 + 1650 + return 0; 1651 + } 1652 + 1653 + const struct pp_table_func pptable_funcs = { 1654 + .pptable_init = pp_tables_initialize, 1655 + .pptable_fini = pp_tables_uninitialize, 1656 + .pptable_get_number_of_vce_state_table_entries = 1657 + get_number_of_vce_state_table_entries, 1658 + .pptable_get_vce_state_table_entry = 1659 + get_vce_state_table_entry, 1660 + }; 1661 +
+47
drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * Interface Functions related to the BIOS PowerPlay Tables. 22 + * 23 + */ 24 + 25 + #ifndef PROCESSPPTABLES_H 26 + #define PROCESSPPTABLES_H 27 + 28 + struct pp_hwmgr; 29 + struct pp_power_state; 30 + struct pp_hw_power_state; 31 + 32 + extern const struct pp_table_func pptable_funcs; 33 + 34 + typedef int (*pp_tables_hw_clock_info_callback)(struct pp_hwmgr *hwmgr, 35 + struct pp_hw_power_state *hw_ps, 36 + unsigned int index, 37 + const void *clock_info); 38 + 39 + int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, 40 + unsigned long *num_of_entries); 41 + 42 + int pp_tables_get_entry(struct pp_hwmgr *hwmgr, 43 + unsigned long entry_index, 44 + struct pp_power_state *ps, 45 + pp_tables_hw_clock_info_callback func); 46 + 47 + #endif
-1
drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
··· 28 28 #include "amd_shared.h" 29 29 #include "cgs_common.h" 30 30 31 - 32 31 enum amd_pp_event { 33 32 AMD_PP_EVENT_INITIALIZE = 0, 34 33 AMD_PP_EVENT_UNINITIALIZE,
+280
drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #ifndef _HARDWARE_MANAGER_H_ 24 + #define _HARDWARE_MANAGER_H_ 25 + 26 + struct pp_hwmgr; 27 + 28 + /* Automatic Power State Throttling */ 29 + enum PHM_AutoThrottleSource 30 + { 31 + PHM_AutoThrottleSource_Thermal, 32 + PHM_AutoThrottleSource_External 33 + }; 34 + 35 + typedef enum PHM_AutoThrottleSource PHM_AutoThrottleSource; 36 + 37 + enum phm_platform_caps { 38 + PHM_PlatformCaps_AtomBiosPpV1 = 0, 39 + PHM_PlatformCaps_PowerPlaySupport, 40 + PHM_PlatformCaps_ACOverdriveSupport, 41 + PHM_PlatformCaps_BacklightSupport, 42 + PHM_PlatformCaps_ThermalController, 43 + PHM_PlatformCaps_BiosPowerSourceControl, 44 + PHM_PlatformCaps_DisableVoltageTransition, 45 + PHM_PlatformCaps_DisableEngineTransition, 46 + PHM_PlatformCaps_DisableMemoryTransition, 47 + PHM_PlatformCaps_DynamicPowerManagement, 48 + PHM_PlatformCaps_EnableASPML0s, 49 + PHM_PlatformCaps_EnableASPML1, 50 + PHM_PlatformCaps_OD5inACSupport, 51 + PHM_PlatformCaps_OD5inDCSupport, 52 + PHM_PlatformCaps_SoftStateOD5, 53 + PHM_PlatformCaps_NoOD5Support, 54 + PHM_PlatformCaps_ContinuousHardwarePerformanceRange, 55 + PHM_PlatformCaps_ActivityReporting, 56 + PHM_PlatformCaps_EnableBackbias, 57 + PHM_PlatformCaps_OverdriveDisabledByPowerBudget, 58 + PHM_PlatformCaps_ShowPowerBudgetWarning, 59 + PHM_PlatformCaps_PowerBudgetWaiverAvailable, 60 + PHM_PlatformCaps_GFXClockGatingSupport, 61 + PHM_PlatformCaps_MMClockGatingSupport, 62 + PHM_PlatformCaps_AutomaticDCTransition, 63 + PHM_PlatformCaps_GeminiPrimary, 64 + PHM_PlatformCaps_MemorySpreadSpectrumSupport, 65 + PHM_PlatformCaps_EngineSpreadSpectrumSupport, 66 + PHM_PlatformCaps_StepVddc, 67 + PHM_PlatformCaps_DynamicPCIEGen2Support, 68 + PHM_PlatformCaps_SMC, 69 + PHM_PlatformCaps_FaultyInternalThermalReading, /* Internal thermal controller reports faulty temperature value when DAC2 is active */ 70 + PHM_PlatformCaps_EnableVoltageControl, /* indicates voltage can be controlled */ 71 + PHM_PlatformCaps_EnableSideportControl, /* indicates Sideport can be controlled */ 72 + PHM_PlatformCaps_VideoPlaybackEEUNotification, /* indicates EEU notification of video start/stop is required */ 73 + PHM_PlatformCaps_TurnOffPll_ASPML1, /* PCIE Turn Off PLL in ASPM L1 */ 74 + PHM_PlatformCaps_EnableHTLinkControl, /* indicates HT Link can be controlled by ACPI or CLMC overrided/automated mode. */ 75 + PHM_PlatformCaps_PerformanceStateOnly, /* indicates only performance power state to be used on current system. */ 76 + PHM_PlatformCaps_ExclusiveModeAlwaysHigh, /* In Exclusive (3D) mode always stay in High state. */ 77 + PHM_PlatformCaps_DisableMGClockGating, /* to disable Medium Grain Clock Gating or not */ 78 + PHM_PlatformCaps_DisableMGCGTSSM, /* TO disable Medium Grain Clock Gating Shader Complex control */ 79 + PHM_PlatformCaps_UVDAlwaysHigh, /* In UVD mode always stay in High state */ 80 + PHM_PlatformCaps_DisablePowerGating, /* to disable power gating */ 81 + PHM_PlatformCaps_CustomThermalPolicy, /* indicates only performance power state to be used on current system. */ 82 + PHM_PlatformCaps_StayInBootState, /* Stay in Boot State, do not do clock/voltage or PCIe Lane and Gen switching (RV7xx and up). */ 83 + PHM_PlatformCaps_SMCAllowSeparateSWThermalState, /* SMC use separate SW thermal state, instead of the default SMC thermal policy. */ 84 + PHM_PlatformCaps_MultiUVDStateSupport, /* Powerplay state table supports multi UVD states. */ 85 + PHM_PlatformCaps_EnableSCLKDeepSleepForUVD, /* With HW ECOs, we don't need to disable SCLK Deep Sleep for UVD state. */ 86 + PHM_PlatformCaps_EnableMCUHTLinkControl, /* Enable HT link control by MCU */ 87 + PHM_PlatformCaps_ABM, /* ABM support.*/ 88 + PHM_PlatformCaps_KongThermalPolicy, /* A thermal policy specific for Kong */ 89 + PHM_PlatformCaps_SwitchVDDNB, /* if the users want to switch VDDNB */ 90 + PHM_PlatformCaps_ULPS, /* support ULPS mode either through ACPI state or ULPS state */ 91 + PHM_PlatformCaps_NativeULPS, /* hardware capable of ULPS state (other than through the ACPI state) */ 92 + PHM_PlatformCaps_EnableMVDDControl, /* indicates that memory voltage can be controlled */ 93 + PHM_PlatformCaps_ControlVDDCI, /* Control VDDCI separately from VDDC. */ 94 + PHM_PlatformCaps_DisableDCODT, /* indicates if DC ODT apply or not */ 95 + PHM_PlatformCaps_DynamicACTiming, /* if the SMC dynamically re-programs MC SEQ register values */ 96 + PHM_PlatformCaps_EnableThermalIntByGPIO, /* enable throttle control through GPIO */ 97 + PHM_PlatformCaps_BootStateOnAlert, /* Go to boot state on alerts, e.g. on an AC->DC transition. */ 98 + PHM_PlatformCaps_DontWaitForVBlankOnAlert, /* Do NOT wait for VBLANK during an alert (e.g. AC->DC transition). */ 99 + PHM_PlatformCaps_Force3DClockSupport, /* indicates if the platform supports force 3D clock. */ 100 + PHM_PlatformCaps_MicrocodeFanControl, /* Fan is controlled by the SMC microcode. */ 101 + PHM_PlatformCaps_AdjustUVDPriorityForSP, 102 + PHM_PlatformCaps_DisableLightSleep, /* Light sleep for evergreen family. */ 103 + PHM_PlatformCaps_DisableMCLS, /* MC Light sleep */ 104 + PHM_PlatformCaps_RegulatorHot, /* Enable throttling on 'regulator hot' events. */ 105 + PHM_PlatformCaps_BACO, /* Support Bus Alive Chip Off mode */ 106 + PHM_PlatformCaps_DisableDPM, /* Disable DPM, supported from Llano */ 107 + PHM_PlatformCaps_DynamicM3Arbiter, /* support dynamically change m3 arbitor parameters */ 108 + PHM_PlatformCaps_SclkDeepSleep, /* support sclk deep sleep */ 109 + PHM_PlatformCaps_DynamicPatchPowerState, /* this ASIC supports to patch power state dynamically */ 110 + PHM_PlatformCaps_ThermalAutoThrottling, /* enabling auto thermal throttling, */ 111 + PHM_PlatformCaps_SumoThermalPolicy, /* A thermal policy specific for Sumo */ 112 + PHM_PlatformCaps_PCIEPerformanceRequest, /* support to change RC voltage */ 113 + PHM_PlatformCaps_BLControlledByGPU, /* support varibright */ 114 + PHM_PlatformCaps_PowerContainment, /* support DPM2 power containment (AKA TDP clamping) */ 115 + PHM_PlatformCaps_SQRamping, /* support DPM2 SQ power throttle */ 116 + PHM_PlatformCaps_CAC, /* support Capacitance * Activity power estimation */ 117 + PHM_PlatformCaps_NIChipsets, /* Northern Island and beyond chipsets */ 118 + PHM_PlatformCaps_TrinityChipsets, /* Trinity chipset */ 119 + PHM_PlatformCaps_EvergreenChipsets, /* Evergreen family chipset */ 120 + PHM_PlatformCaps_PowerControl, /* Cayman and beyond chipsets */ 121 + PHM_PlatformCaps_DisableLSClockGating, /* to disable Light Sleep control for HDP memories */ 122 + PHM_PlatformCaps_BoostState, /* this ASIC supports boost state */ 123 + PHM_PlatformCaps_UserMaxClockForMultiDisplays, /* indicates if max memory clock is used for all status when multiple displays are connected */ 124 + PHM_PlatformCaps_RegWriteDelay, /* indicates if back to back reg write delay is required */ 125 + PHM_PlatformCaps_NonABMSupportInPPLib, /* ABM is not supported in PPLIB, (moved from PPLIB to DAL) */ 126 + PHM_PlatformCaps_GFXDynamicMGPowerGating, /* Enable Dynamic MG PowerGating on Trinity */ 127 + PHM_PlatformCaps_DisableSMUUVDHandshake, /* Disable SMU UVD Handshake */ 128 + PHM_PlatformCaps_DTE, /* Support Digital Temperature Estimation */ 129 + PHM_PlatformCaps_W5100Specifc_SmuSkipMsgDTE, /* This is for the feature requested by David B., and Tonny W.*/ 130 + PHM_PlatformCaps_UVDPowerGating, /* enable UVD power gating, supported from Llano */ 131 + PHM_PlatformCaps_UVDDynamicPowerGating, /* enable UVD Dynamic power gating, supported from UVD5 */ 132 + PHM_PlatformCaps_VCEPowerGating, /* Enable VCE power gating, supported for TN and later ASICs */ 133 + PHM_PlatformCaps_SamuPowerGating, /* Enable SAMU power gating, supported for KV and later ASICs */ 134 + PHM_PlatformCaps_UVDDPM, /* UVD clock DPM */ 135 + PHM_PlatformCaps_VCEDPM, /* VCE clock DPM */ 136 + PHM_PlatformCaps_SamuDPM, /* SAMU clock DPM */ 137 + PHM_PlatformCaps_AcpDPM, /* ACP clock DPM */ 138 + PHM_PlatformCaps_SclkDeepSleepAboveLow, /* Enable SCLK Deep Sleep on all DPM states */ 139 + PHM_PlatformCaps_DynamicUVDState, /* Dynamic UVD State */ 140 + PHM_PlatformCaps_WantSAMClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ 141 + PHM_PlatformCaps_WantUVDClkWithDummyBackEnd, /* Set UVD Clk With Dummy Back End */ 142 + PHM_PlatformCaps_WantVCEClkWithDummyBackEnd, /* Set VCE Clk With Dummy Back End */ 143 + PHM_PlatformCaps_WantACPClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ 144 + PHM_PlatformCaps_OD6inACSupport, /* indicates that the ASIC/back end supports OD6 */ 145 + PHM_PlatformCaps_OD6inDCSupport, /* indicates that the ASIC/back end supports OD6 in DC */ 146 + PHM_PlatformCaps_EnablePlatformPowerManagement, /* indicates that Platform Power Management feature is supported */ 147 + PHM_PlatformCaps_SurpriseRemoval, /* indicates that surprise removal feature is requested */ 148 + PHM_PlatformCaps_NewCACVoltage, /* indicates new CAC voltage table support */ 149 + PHM_PlatformCaps_DBRamping, /* for dI/dT feature */ 150 + PHM_PlatformCaps_TDRamping, /* for dI/dT feature */ 151 + PHM_PlatformCaps_TCPRamping, /* for dI/dT feature */ 152 + PHM_PlatformCaps_EnableSMU7ThermalManagement, /* SMC will manage thermal events */ 153 + PHM_PlatformCaps_FPS, /* FPS support */ 154 + PHM_PlatformCaps_ACP, /* ACP support */ 155 + PHM_PlatformCaps_SclkThrottleLowNotification, /* SCLK Throttle Low Notification */ 156 + PHM_PlatformCaps_XDMAEnabled, /* XDMA engine is enabled */ 157 + PHM_PlatformCaps_UseDummyBackEnd, /* use dummy back end */ 158 + PHM_PlatformCaps_EnableDFSBypass, /* Enable DFS bypass */ 159 + PHM_PlatformCaps_VddNBDirectRequest, 160 + PHM_PlatformCaps_PauseMMSessions, 161 + PHM_PlatformCaps_UnTabledHardwareInterface, /* Tableless/direct call hardware interface for CI and newer ASICs */ 162 + PHM_PlatformCaps_SMU7, /* indicates that vpuRecoveryBegin without SMU shutdown */ 163 + PHM_PlatformCaps_RevertGPIO5Polarity, /* indicates revert GPIO5 plarity table support */ 164 + PHM_PlatformCaps_Thermal2GPIO17, /* indicates thermal2GPIO17 table support */ 165 + PHM_PlatformCaps_ThermalOutGPIO, /* indicates ThermalOutGPIO support, pin number is assigned by VBIOS */ 166 + PHM_PlatformCaps_DisableMclkSwitchingForFrameLock, /* Disable memory clock switch during Framelock */ 167 + PHM_PlatformCaps_VRHotGPIOConfigurable, /* indicates VR_HOT GPIO configurable */ 168 + PHM_PlatformCaps_TempInversion, /* enable Temp Inversion feature */ 169 + PHM_PlatformCaps_IOIC3, 170 + PHM_PlatformCaps_ConnectedStandby, 171 + PHM_PlatformCaps_EVV, 172 + PHM_PlatformCaps_EnableLongIdleBACOSupport, 173 + PHM_PlatformCaps_CombinePCCWithThermalSignal, 174 + PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc, 175 + PHM_PlatformCaps_StablePState, 176 + PHM_PlatformCaps_OD6PlusinACSupport, 177 + PHM_PlatformCaps_OD6PlusinDCSupport, 178 + PHM_PlatformCaps_ODThermalLimitUnlock, 179 + PHM_PlatformCaps_ReducePowerLimit, 180 + PHM_PlatformCaps_ODFuzzyFanControlSupport, 181 + PHM_PlatformCaps_GeminiRegulatorFanControlSupport, 182 + PHM_PlatformCaps_ControlVDDGFX, 183 + PHM_PlatformCaps_BBBSupported, 184 + PHM_PlatformCaps_DisableVoltageIsland, 185 + PHM_PlatformCaps_FanSpeedInTableIsRPM, 186 + PHM_PlatformCaps_GFXClockGatingManagedInCAIL, 187 + PHM_PlatformCaps_IcelandULPSSWWorkAround, 188 + PHM_PlatformCaps_FPSEnhancement, 189 + PHM_PlatformCaps_LoadPostProductionFirmware, 190 + PHM_PlatformCaps_VpuRecoveryInProgress, 191 + PHM_PlatformCaps_Falcon_QuickTransition, 192 + PHM_PlatformCaps_AVFS, 193 + PHM_PlatformCaps_ClockStretcher, 194 + PHM_PlatformCaps_TablelessHardwareInterface, 195 + PHM_PlatformCaps_EnableDriverEVV, 196 + PHM_PlatformCaps_Max 197 + }; 198 + 199 + #define PHM_MAX_NUM_CAPS_BITS_PER_FIELD (sizeof(uint32_t)*8) 200 + 201 + /* Number of uint32_t entries used by CAPS table */ 202 + #define PHM_MAX_NUM_CAPS_ULONG_ENTRIES \ 203 + ((PHM_PlatformCaps_Max + ((PHM_MAX_NUM_CAPS_BITS_PER_FIELD) - 1)) / (PHM_MAX_NUM_CAPS_BITS_PER_FIELD)) 204 + 205 + struct pp_hw_descriptor { 206 + uint32_t hw_caps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; 207 + }; 208 + 209 + /* Function for setting a platform cap */ 210 + static inline void phm_cap_set(uint32_t *caps, 211 + enum phm_platform_caps c) 212 + { 213 + caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] |= (1UL << 214 + (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); 215 + } 216 + 217 + static inline void phm_cap_unset(uint32_t *caps, 218 + enum phm_platform_caps c) 219 + { 220 + caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] &= ~(1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); 221 + } 222 + 223 + static inline bool phm_cap_enabled(const uint32_t *caps, enum phm_platform_caps c) 224 + { 225 + return (0 != (caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] & 226 + (1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))))); 227 + } 228 + 229 + enum phm_clock_Type { 230 + PHM_DispClock = 1, 231 + PHM_SClock, 232 + PHM_MemClock 233 + }; 234 + 235 + #define MAX_NUM_CLOCKS 16 236 + 237 + struct PP_Clocks { 238 + uint32_t engineClock; 239 + uint32_t memoryClock; 240 + uint32_t BusBandwidth; 241 + uint32_t engineClockInSR; 242 + }; 243 + 244 + struct phm_platform_descriptor { 245 + uint32_t platformCaps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; 246 + uint32_t vbiosInterruptId; 247 + struct PP_Clocks overdriveLimit; 248 + struct PP_Clocks clockStep; 249 + uint32_t hardwareActivityPerformanceLevels; 250 + uint32_t minimumClocksReductionPercentage; 251 + uint32_t minOverdriveVDDC; 252 + uint32_t maxOverdriveVDDC; 253 + uint32_t overdriveVDDCStep; 254 + uint32_t hardwarePerformanceLevels; 255 + uint16_t powerBudget; 256 + uint32_t TDPLimit; 257 + uint32_t nearTDPLimit; 258 + uint32_t nearTDPLimitAdjusted; 259 + uint32_t SQRampingThreshold; 260 + uint32_t CACLeakage; 261 + uint16_t TDPODLimit; 262 + uint32_t TDPAdjustment; 263 + bool TDPAdjustmentPolarity; 264 + uint16_t LoadLineSlope; 265 + uint32_t VidMinLimit; 266 + uint32_t VidMaxLimit; 267 + uint32_t VidStep; 268 + uint32_t VidAdjustment; 269 + bool VidAdjustmentPolarity; 270 + }; 271 + 272 + struct phm_clocks { 273 + uint32_t num_of_entries; 274 + uint32_t clock[MAX_NUM_CLOCKS]; 275 + }; 276 + 277 + extern int phm_setup_asic(struct pp_hwmgr *hwmgr); 278 + extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); 279 + extern void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr); 280 + #endif /* _HARDWARE_MANAGER_H_ */
+607
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #ifndef _HWMGR_H_ 24 + #define _HWMGR_H_ 25 + 26 + #include "amd_powerplay.h" 27 + #include "pp_instance.h" 28 + #include "hardwaremanager.h" 29 + #include "pp_power_source.h" 30 + 31 + struct pp_instance; 32 + struct pp_hwmgr; 33 + struct pp_hw_power_state; 34 + struct pp_power_state; 35 + struct PP_VCEState; 36 + 37 + enum PP_Result { 38 + PP_Result_TableImmediateExit = 0x13, 39 + }; 40 + 41 + #define PCIE_PERF_REQ_REMOVE_REGISTRY 0 42 + #define PCIE_PERF_REQ_FORCE_LOWPOWER 1 43 + #define PCIE_PERF_REQ_GEN1 2 44 + #define PCIE_PERF_REQ_GEN2 3 45 + #define PCIE_PERF_REQ_GEN3 4 46 + 47 + enum PHM_BackEnd_Magic { 48 + PHM_Dummy_Magic = 0xAA5555AA, 49 + PHM_RV770_Magic = 0xDCBAABCD, 50 + PHM_Kong_Magic = 0x239478DF, 51 + PHM_NIslands_Magic = 0x736C494E, 52 + PHM_Sumo_Magic = 0x8339FA11, 53 + PHM_SIslands_Magic = 0x369431AC, 54 + PHM_Trinity_Magic = 0x96751873, 55 + PHM_CIslands_Magic = 0x38AC78B0, 56 + PHM_Kv_Magic = 0xDCBBABC0, 57 + PHM_VIslands_Magic = 0x20130307, 58 + PHM_Cz_Magic = 0x67DCBA25 59 + }; 60 + 61 + enum PP_DAL_POWERLEVEL { 62 + PP_DAL_POWERLEVEL_INVALID = 0, 63 + PP_DAL_POWERLEVEL_ULTRALOW, 64 + PP_DAL_POWERLEVEL_LOW, 65 + PP_DAL_POWERLEVEL_NOMINAL, 66 + PP_DAL_POWERLEVEL_PERFORMANCE, 67 + 68 + PP_DAL_POWERLEVEL_0 = PP_DAL_POWERLEVEL_ULTRALOW, 69 + PP_DAL_POWERLEVEL_1 = PP_DAL_POWERLEVEL_LOW, 70 + PP_DAL_POWERLEVEL_2 = PP_DAL_POWERLEVEL_NOMINAL, 71 + PP_DAL_POWERLEVEL_3 = PP_DAL_POWERLEVEL_PERFORMANCE, 72 + PP_DAL_POWERLEVEL_4 = PP_DAL_POWERLEVEL_3+1, 73 + PP_DAL_POWERLEVEL_5 = PP_DAL_POWERLEVEL_4+1, 74 + PP_DAL_POWERLEVEL_6 = PP_DAL_POWERLEVEL_5+1, 75 + PP_DAL_POWERLEVEL_7 = PP_DAL_POWERLEVEL_6+1, 76 + }; 77 + 78 + #define PHM_PCIE_POWERGATING_TARGET_GFX 0 79 + #define PHM_PCIE_POWERGATING_TARGET_DDI 1 80 + #define PHM_PCIE_POWERGATING_TARGET_PLLCASCADE 2 81 + #define PHM_PCIE_POWERGATING_TARGET_PHY 3 82 + 83 + typedef int (*phm_table_function)(struct pp_hwmgr *hwmgr, void *input, 84 + void *output, void *storage, int result); 85 + 86 + typedef bool (*phm_check_function)(struct pp_hwmgr *hwmgr); 87 + 88 + struct phm_acp_arbiter { 89 + uint32_t acpclk; 90 + }; 91 + 92 + struct phm_uvd_arbiter { 93 + uint32_t vclk; 94 + uint32_t dclk; 95 + uint32_t vclk_ceiling; 96 + uint32_t dclk_ceiling; 97 + }; 98 + 99 + struct phm_vce_arbiter { 100 + uint32_t evclk; 101 + uint32_t ecclk; 102 + }; 103 + 104 + struct phm_gfx_arbiter { 105 + uint32_t sclk; 106 + uint32_t mclk; 107 + uint32_t sclk_over_drive; 108 + uint32_t mclk_over_drive; 109 + uint32_t sclk_threshold; 110 + uint32_t num_cus; 111 + }; 112 + 113 + /* Entries in the master tables */ 114 + struct phm_master_table_item { 115 + phm_check_function isFunctionNeededInRuntimeTable; 116 + phm_table_function tableFunction; 117 + }; 118 + 119 + enum phm_master_table_flag { 120 + PHM_MasterTableFlag_None = 0, 121 + PHM_MasterTableFlag_ExitOnError = 1, 122 + }; 123 + 124 + /* The header of the master tables */ 125 + struct phm_master_table_header { 126 + uint32_t storage_size; 127 + uint32_t flags; 128 + struct phm_master_table_item *master_list; 129 + }; 130 + 131 + struct phm_runtime_table_header { 132 + uint32_t storage_size; 133 + bool exit_error; 134 + phm_table_function *function_list; 135 + }; 136 + 137 + struct phm_clock_array { 138 + uint32_t count; 139 + uint32_t values[1]; 140 + }; 141 + 142 + struct phm_clock_voltage_dependency_record { 143 + uint32_t clk; 144 + uint32_t v; 145 + }; 146 + 147 + struct phm_vceclock_voltage_dependency_record { 148 + uint32_t ecclk; 149 + uint32_t evclk; 150 + uint32_t v; 151 + }; 152 + 153 + struct phm_uvdclock_voltage_dependency_record { 154 + uint32_t vclk; 155 + uint32_t dclk; 156 + uint32_t v; 157 + }; 158 + 159 + struct phm_samuclock_voltage_dependency_record { 160 + uint32_t samclk; 161 + uint32_t v; 162 + }; 163 + 164 + struct phm_acpclock_voltage_dependency_record { 165 + uint32_t acpclk; 166 + uint32_t v; 167 + }; 168 + 169 + struct phm_clock_voltage_dependency_table { 170 + uint32_t count; /* Number of entries. */ 171 + struct phm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ 172 + }; 173 + 174 + struct phm_phase_shedding_limits_record { 175 + uint32_t Voltage; 176 + uint32_t Sclk; 177 + uint32_t Mclk; 178 + }; 179 + 180 + 181 + extern int phm_dispatch_table(struct pp_hwmgr *hwmgr, 182 + struct phm_runtime_table_header *rt_table, 183 + void *input, void *output); 184 + 185 + extern int phm_construct_table(struct pp_hwmgr *hwmgr, 186 + struct phm_master_table_header *master_table, 187 + struct phm_runtime_table_header *rt_table); 188 + 189 + extern int phm_destroy_table(struct pp_hwmgr *hwmgr, 190 + struct phm_runtime_table_header *rt_table); 191 + 192 + 193 + struct phm_uvd_clock_voltage_dependency_record { 194 + uint32_t vclk; 195 + uint32_t dclk; 196 + uint32_t v; 197 + }; 198 + 199 + struct phm_uvd_clock_voltage_dependency_table { 200 + uint8_t count; 201 + struct phm_uvd_clock_voltage_dependency_record entries[1]; 202 + }; 203 + 204 + struct phm_acp_clock_voltage_dependency_record { 205 + uint32_t acpclk; 206 + uint32_t v; 207 + }; 208 + 209 + struct phm_acp_clock_voltage_dependency_table { 210 + uint32_t count; 211 + struct phm_acp_clock_voltage_dependency_record entries[1]; 212 + }; 213 + 214 + struct phm_vce_clock_voltage_dependency_record { 215 + uint32_t ecclk; 216 + uint32_t evclk; 217 + uint32_t v; 218 + }; 219 + 220 + struct phm_phase_shedding_limits_table { 221 + uint32_t count; 222 + struct phm_phase_shedding_limits_record entries[1]; 223 + }; 224 + 225 + struct phm_vceclock_voltage_dependency_table { 226 + uint8_t count; /* Number of entries. */ 227 + struct phm_vceclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ 228 + }; 229 + 230 + struct phm_uvdclock_voltage_dependency_table { 231 + uint8_t count; /* Number of entries. */ 232 + struct phm_uvdclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ 233 + }; 234 + 235 + struct phm_samuclock_voltage_dependency_table { 236 + uint8_t count; /* Number of entries. */ 237 + struct phm_samuclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ 238 + }; 239 + 240 + struct phm_acpclock_voltage_dependency_table { 241 + uint32_t count; /* Number of entries. */ 242 + struct phm_acpclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ 243 + }; 244 + 245 + struct phm_vce_clock_voltage_dependency_table { 246 + uint8_t count; 247 + struct phm_vce_clock_voltage_dependency_record entries[1]; 248 + }; 249 + 250 + struct pp_hwmgr_func { 251 + int (*backend_init)(struct pp_hwmgr *hw_mgr); 252 + int (*backend_fini)(struct pp_hwmgr *hw_mgr); 253 + int (*asic_setup)(struct pp_hwmgr *hw_mgr); 254 + int (*get_power_state_size)(struct pp_hwmgr *hw_mgr); 255 + int (*force_dpm_level)(struct pp_hwmgr *hw_mgr, enum amd_dpm_forced_level level); 256 + int (*dynamic_state_management_enable)(struct pp_hwmgr *hw_mgr); 257 + int (*patch_boot_state)(struct pp_hwmgr *hwmgr, struct pp_hw_power_state *hw_ps); 258 + int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr, unsigned long, struct pp_power_state *); 259 + int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr); 260 + }; 261 + 262 + struct pp_table_func { 263 + int (*pptable_init)(struct pp_hwmgr *hw_mgr); 264 + int (*pptable_fini)(struct pp_hwmgr *hw_mgr); 265 + int (*pptable_get_number_of_vce_state_table_entries)(struct pp_hwmgr *hw_mgr); 266 + int (*pptable_get_vce_state_table_entry)( 267 + struct pp_hwmgr *hwmgr, 268 + unsigned long i, 269 + struct PP_VCEState *vce_state, 270 + void **clock_info, 271 + unsigned long *flag); 272 + }; 273 + 274 + union phm_cac_leakage_record { 275 + struct { 276 + uint16_t Vddc; /* in CI, we use it for StdVoltageHiSidd */ 277 + uint32_t Leakage; /* in CI, we use it for StdVoltageLoSidd */ 278 + }; 279 + struct { 280 + uint16_t Vddc1; 281 + uint16_t Vddc2; 282 + uint16_t Vddc3; 283 + }; 284 + }; 285 + 286 + struct phm_cac_leakage_table { 287 + uint32_t count; 288 + union phm_cac_leakage_record entries[1]; 289 + }; 290 + 291 + struct phm_samu_clock_voltage_dependency_record { 292 + uint32_t samclk; 293 + uint32_t v; 294 + }; 295 + 296 + 297 + struct phm_samu_clock_voltage_dependency_table { 298 + uint8_t count; 299 + struct phm_samu_clock_voltage_dependency_record entries[1]; 300 + }; 301 + 302 + struct phm_cac_tdp_table { 303 + uint16_t usTDP; 304 + uint16_t usConfigurableTDP; 305 + uint16_t usTDC; 306 + uint16_t usBatteryPowerLimit; 307 + uint16_t usSmallPowerLimit; 308 + uint16_t usLowCACLeakage; 309 + uint16_t usHighCACLeakage; 310 + uint16_t usMaximumPowerDeliveryLimit; 311 + uint16_t usOperatingTempMinLimit; 312 + uint16_t usOperatingTempMaxLimit; 313 + uint16_t usOperatingTempStep; 314 + uint16_t usOperatingTempHyst; 315 + uint16_t usDefaultTargetOperatingTemp; 316 + uint16_t usTargetOperatingTemp; 317 + uint16_t usPowerTuneDataSetID; 318 + uint16_t usSoftwareShutdownTemp; 319 + uint16_t usClockStretchAmount; 320 + uint16_t usTemperatureLimitHotspot; 321 + uint16_t usTemperatureLimitLiquid1; 322 + uint16_t usTemperatureLimitLiquid2; 323 + uint16_t usTemperatureLimitVrVddc; 324 + uint16_t usTemperatureLimitVrMvdd; 325 + uint16_t usTemperatureLimitPlx; 326 + uint8_t ucLiquid1_I2C_address; 327 + uint8_t ucLiquid2_I2C_address; 328 + uint8_t ucLiquid_I2C_Line; 329 + uint8_t ucVr_I2C_address; 330 + uint8_t ucVr_I2C_Line; 331 + uint8_t ucPlx_I2C_address; 332 + uint8_t ucPlx_I2C_Line; 333 + }; 334 + 335 + struct phm_ppm_table { 336 + uint8_t ppm_design; 337 + uint16_t cpu_core_number; 338 + uint32_t platform_tdp; 339 + uint32_t small_ac_platform_tdp; 340 + uint32_t platform_tdc; 341 + uint32_t small_ac_platform_tdc; 342 + uint32_t apu_tdp; 343 + uint32_t dgpu_tdp; 344 + uint32_t dgpu_ulv_power; 345 + uint32_t tj_max; 346 + }; 347 + 348 + struct phm_vq_budgeting_record { 349 + uint32_t ulCUs; 350 + uint32_t ulSustainableSOCPowerLimitLow; 351 + uint32_t ulSustainableSOCPowerLimitHigh; 352 + uint32_t ulMinSclkLow; 353 + uint32_t ulMinSclkHigh; 354 + uint8_t ucDispConfig; 355 + uint32_t ulDClk; 356 + uint32_t ulEClk; 357 + uint32_t ulSustainableSclk; 358 + uint32_t ulSustainableCUs; 359 + }; 360 + 361 + struct phm_vq_budgeting_table { 362 + uint8_t numEntries; 363 + struct phm_vq_budgeting_record entries[1]; 364 + }; 365 + 366 + struct phm_clock_and_voltage_limits { 367 + uint32_t sclk; 368 + uint32_t mclk; 369 + uint16_t vddc; 370 + uint16_t vddci; 371 + uint16_t vddgfx; 372 + }; 373 + 374 + 375 + 376 + struct phm_dynamic_state_info { 377 + struct phm_clock_voltage_dependency_table *vddc_dependency_on_sclk; 378 + struct phm_clock_voltage_dependency_table *vddci_dependency_on_mclk; 379 + struct phm_clock_voltage_dependency_table *vddc_dependency_on_mclk; 380 + struct phm_clock_voltage_dependency_table *mvdd_dependency_on_mclk; 381 + struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl; 382 + struct phm_clock_array *valid_sclk_values; 383 + struct phm_clock_array *valid_mclk_values; 384 + struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; 385 + struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; 386 + uint32_t mclk_sclk_ratio; 387 + uint32_t sclk_mclk_delta; 388 + uint32_t vddc_vddci_delta; 389 + uint32_t min_vddc_for_pcie_gen2; 390 + struct phm_cac_leakage_table *cac_leakage_table; 391 + struct phm_phase_shedding_limits_table *vddc_phase_shed_limits_table; 392 + 393 + struct phm_vce_clock_voltage_dependency_table 394 + *vce_clocl_voltage_dependency_table; 395 + struct phm_uvd_clock_voltage_dependency_table 396 + *uvd_clocl_voltage_dependency_table; 397 + struct phm_acp_clock_voltage_dependency_table 398 + *acp_clock_voltage_dependency_table; 399 + struct phm_samu_clock_voltage_dependency_table 400 + *samu_clock_voltage_dependency_table; 401 + 402 + struct phm_ppm_table *ppm_parameter_table; 403 + struct phm_cac_tdp_table *cac_dtp_table; 404 + struct phm_clock_voltage_dependency_table *vdd_gfx_dependency_on_sclk; 405 + struct phm_vq_budgeting_table *vq_budgeting_table; 406 + }; 407 + 408 + struct pp_hwmgr { 409 + uint32_t chip_family; 410 + uint32_t chip_id; 411 + uint32_t hw_revision; 412 + uint32_t sub_sys_id; 413 + uint32_t sub_vendor_id; 414 + 415 + void *device; 416 + struct pp_smumgr *smumgr; 417 + const void *soft_pp_table; 418 + enum amd_dpm_forced_level dpm_level; 419 + 420 + struct phm_gfx_arbiter gfx_arbiter; 421 + struct phm_acp_arbiter acp_arbiter; 422 + struct phm_uvd_arbiter uvd_arbiter; 423 + struct phm_vce_arbiter vce_arbiter; 424 + uint32_t usec_timeout; 425 + void *pptable; 426 + struct phm_platform_descriptor platform_descriptor; 427 + void *backend; 428 + enum PP_DAL_POWERLEVEL dal_power_level; 429 + struct phm_dynamic_state_info dyn_state; 430 + struct phm_runtime_table_header setup_asic; 431 + struct phm_runtime_table_header disable_dynamic_state_management; 432 + struct phm_runtime_table_header enable_dynamic_state_management; 433 + const struct pp_hwmgr_func *hwmgr_func; 434 + const struct pp_table_func *pptable_func; 435 + struct pp_power_state *ps; 436 + enum pp_power_source power_source; 437 + uint32_t num_ps; 438 + uint32_t ps_size; 439 + struct pp_power_state *current_ps; 440 + struct pp_power_state *request_ps; 441 + struct pp_power_state *boot_ps; 442 + struct pp_power_state *uvd_ps; 443 + }; 444 + 445 + 446 + extern int hwmgr_init(struct amd_pp_init *pp_init, 447 + struct pp_instance *handle); 448 + 449 + extern int hwmgr_fini(struct pp_hwmgr *hwmgr); 450 + 451 + extern int hw_init_power_state_table(struct pp_hwmgr *hwmgr); 452 + 453 + extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, 454 + uint32_t value, uint32_t mask); 455 + 456 + extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, 457 + uint32_t index, uint32_t value, uint32_t mask); 458 + 459 + 460 + 461 + extern void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, 462 + uint32_t indirect_port, 463 + uint32_t index, 464 + uint32_t value, 465 + uint32_t mask); 466 + 467 + extern void phm_wait_for_indirect_register_unequal( 468 + struct pp_hwmgr *hwmgr, 469 + uint32_t indirect_port, 470 + uint32_t index, 471 + uint32_t value, 472 + uint32_t mask); 473 + 474 + #define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT 475 + #define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK 476 + 477 + #define PHM_SET_FIELD(origval, reg, field, fieldval) \ 478 + (((origval) & ~PHM_FIELD_MASK(reg, field)) | \ 479 + (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field)))) 480 + 481 + #define PHM_GET_FIELD(value, reg, field) \ 482 + (((value) & PHM_FIELD_MASK(reg, field)) >> \ 483 + PHM_FIELD_SHIFT(reg, field)) 484 + 485 + 486 + #define PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, index, value, mask) \ 487 + phm_wait_on_register(hwmgr, index, value, mask) 488 + 489 + #define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, index, value, mask) \ 490 + phm_wait_for_register_unequal(hwmgr, index, value, mask) 491 + 492 + #define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 493 + phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask) 494 + 495 + #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 496 + phm_wait_for_indirect_register_unequal(hwmgr, mm##port##_INDEX, index, value, mask) 497 + 498 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 499 + phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX_0, index, value, mask) 500 + 501 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ 502 + phm_wait_for_indirect_register_unequal(hwmgr, mm##port##_INDEX_0, index, value, mask) 503 + 504 + /* Operations on named registers. */ 505 + 506 + #define PHM_WAIT_REGISTER(hwmgr, reg, value, mask) \ 507 + PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg, value, mask) 508 + 509 + #define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \ 510 + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg, value, mask) 511 + 512 + #define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ 513 + PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 514 + 515 + #define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ 516 + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 517 + 518 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ 519 + PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 520 + 521 + #define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ 522 + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) 523 + 524 + /* Operations on named fields. */ 525 + 526 + #define PHM_READ_FIELD(device, reg, field) \ 527 + PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) 528 + 529 + #define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \ 530 + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 531 + reg, field) 532 + 533 + #define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ 534 + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 535 + reg, field) 536 + 537 + #define PHM_WRITE_FIELD(device, reg, field, fieldval) \ 538 + cgs_write_register(device, mm##reg, PHM_SET_FIELD( \ 539 + cgs_read_register(device, mm##reg), reg, field, fieldval)) 540 + 541 + #define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \ 542 + cgs_write_ind_register(device, port, ix##reg, \ 543 + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 544 + reg, field, fieldval)) 545 + 546 + #define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ 547 + cgs_write_ind_register(device, port, ix##reg, \ 548 + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 549 + reg, field, fieldval)) 550 + 551 + #define PHM_WAIT_FIELD(hwmgr, reg, field, fieldval) \ 552 + PHM_WAIT_REGISTER(hwmgr, reg, (fieldval) \ 553 + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 554 + 555 + #define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ 556 + PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ 557 + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 558 + 559 + #define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ 560 + PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ 561 + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 562 + 563 + #define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \ 564 + PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, (fieldval) \ 565 + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 566 + 567 + #define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ 568 + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, (fieldval) \ 569 + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 570 + 571 + #define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ 572 + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, (fieldval) \ 573 + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) 574 + 575 + /* Operations on arrays of registers & fields. */ 576 + 577 + #define PHM_READ_ARRAY_REGISTER(device, reg, offset) \ 578 + cgs_read_register(device, mm##reg + (offset)) 579 + 580 + #define PHM_WRITE_ARRAY_REGISTER(device, reg, offset, value) \ 581 + cgs_write_register(device, mm##reg + (offset), value) 582 + 583 + #define PHM_WAIT_ARRAY_REGISTER(hwmgr, reg, offset, value, mask) \ 584 + PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg + (offset), value, mask) 585 + 586 + #define PHM_WAIT_ARRAY_REGISTER_UNEQUAL(hwmgr, reg, offset, value, mask) \ 587 + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg + (offset), value, mask) 588 + 589 + #define PHM_READ_ARRAY_FIELD(hwmgr, reg, offset, field) \ 590 + PHM_GET_FIELD(PHM_READ_ARRAY_REGISTER(hwmgr->device, reg, offset), reg, field) 591 + 592 + #define PHM_WRITE_ARRAY_FIELD(hwmgr, reg, offset, field, fieldvalue) \ 593 + PHM_WRITE_ARRAY_REGISTER(hwmgr->device, reg, offset, \ 594 + PHM_SET_FIELD(PHM_READ_ARRAY_REGISTER(hwmgr->device, reg, offset), \ 595 + reg, field, fieldvalue)) 596 + 597 + #define PHM_WAIT_ARRAY_FIELD(hwmgr, reg, offset, field, fieldvalue) \ 598 + PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg + (offset), \ 599 + (fieldvalue) << PHM_FIELD_SHIFT(reg, field), \ 600 + PHM_FIELD_MASK(reg, field)) 601 + 602 + #define PHM_WAIT_ARRAY_FIELD_UNEQUAL(hwmgr, reg, offset, field, fieldvalue) \ 603 + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg + (offset), \ 604 + (fieldvalue) << PHM_FIELD_SHIFT(reg, field), \ 605 + PHM_FIELD_MASK(reg, field)) 606 + 607 + #endif /* _HWMGR_H_ */
+200
drivers/gpu/drm/amd/powerplay/inc/power_state.h
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #ifndef PP_POWERSTATE_H 24 + #define PP_POWERSTATE_H 25 + 26 + struct pp_hw_power_state { 27 + unsigned int magic; 28 + }; 29 + 30 + struct pp_power_state; 31 + 32 + 33 + #define PP_INVALID_POWER_STATE_ID (0) 34 + 35 + 36 + /* 37 + * An item of a list containing Power States. 38 + */ 39 + 40 + struct PP_StateLinkedList { 41 + struct pp_power_state *next; 42 + struct pp_power_state *prev; 43 + }; 44 + 45 + 46 + enum PP_StateUILabel { 47 + PP_StateUILabel_None, 48 + PP_StateUILabel_Battery, 49 + PP_StateUILabel_MiddleLow, 50 + PP_StateUILabel_Balanced, 51 + PP_StateUILabel_MiddleHigh, 52 + PP_StateUILabel_Performance, 53 + PP_StateUILabel_BACO 54 + }; 55 + 56 + enum PP_StateClassificationFlag { 57 + PP_StateClassificationFlag_Boot = 0x0001, 58 + PP_StateClassificationFlag_Thermal = 0x0002, 59 + PP_StateClassificationFlag_LimitedPowerSource = 0x0004, 60 + PP_StateClassificationFlag_Rest = 0x0008, 61 + PP_StateClassificationFlag_Forced = 0x0010, 62 + PP_StateClassificationFlag_User3DPerformance = 0x0020, 63 + PP_StateClassificationFlag_User2DPerformance = 0x0040, 64 + PP_StateClassificationFlag_3DPerformance = 0x0080, 65 + PP_StateClassificationFlag_ACOverdriveTemplate = 0x0100, 66 + PP_StateClassificationFlag_Uvd = 0x0200, 67 + PP_StateClassificationFlag_3DPerformanceLow = 0x0400, 68 + PP_StateClassificationFlag_ACPI = 0x0800, 69 + PP_StateClassificationFlag_HD2 = 0x1000, 70 + PP_StateClassificationFlag_UvdHD = 0x2000, 71 + PP_StateClassificationFlag_UvdSD = 0x4000, 72 + PP_StateClassificationFlag_UserDCPerformance = 0x8000, 73 + PP_StateClassificationFlag_DCOverdriveTemplate = 0x10000, 74 + PP_StateClassificationFlag_BACO = 0x20000, 75 + PP_StateClassificationFlag_LimitedPowerSource_2 = 0x40000, 76 + PP_StateClassificationFlag_ULV = 0x80000, 77 + PP_StateClassificationFlag_UvdMVC = 0x100000, 78 + }; 79 + 80 + typedef unsigned int PP_StateClassificationFlags; 81 + 82 + struct PP_StateClassificationBlock { 83 + enum PP_StateUILabel ui_label; 84 + enum PP_StateClassificationFlag flags; 85 + int bios_index; 86 + bool temporary_state; 87 + bool to_be_deleted; 88 + }; 89 + 90 + struct PP_StatePcieBlock { 91 + unsigned int lanes; 92 + }; 93 + 94 + enum PP_RefreshrateSource { 95 + PP_RefreshrateSource_EDID, 96 + PP_RefreshrateSource_Explicit 97 + }; 98 + 99 + struct PP_StateDisplayBlock { 100 + bool disableFrameModulation; 101 + bool limitRefreshrate; 102 + enum PP_RefreshrateSource refreshrateSource; 103 + int explicitRefreshrate; 104 + int edidRefreshrateIndex; 105 + bool enableVariBright; 106 + }; 107 + 108 + struct PP_StateMemroyBlock { 109 + bool dllOff; 110 + uint8_t m3arb; 111 + uint8_t unused[3]; 112 + }; 113 + 114 + struct PP_StateSoftwareAlgorithmBlock { 115 + bool disableLoadBalancing; 116 + bool enableSleepForTimestamps; 117 + }; 118 + 119 + #define PP_TEMPERATURE_UNITS_PER_CENTIGRADES 1000 120 + 121 + /** 122 + * Type to hold a temperature range. 123 + */ 124 + struct PP_TemperatureRange { 125 + uint16_t min; 126 + uint16_t max; 127 + }; 128 + 129 + struct PP_StateValidationBlock { 130 + bool singleDisplayOnly; 131 + bool disallowOnDC; 132 + uint8_t supportedPowerLevels; 133 + }; 134 + 135 + struct PP_UVD_CLOCKS { 136 + uint32_t VCLK; 137 + uint32_t DCLK; 138 + }; 139 + 140 + /** 141 + * Structure to hold a PowerPlay Power State. 142 + */ 143 + struct pp_power_state { 144 + uint32_t id; 145 + struct PP_StateLinkedList orderedList; 146 + struct PP_StateLinkedList allStatesList; 147 + 148 + struct PP_StateClassificationBlock classification; 149 + struct PP_StateValidationBlock validation; 150 + struct PP_StatePcieBlock pcie; 151 + struct PP_StateDisplayBlock display; 152 + struct PP_StateMemroyBlock memory; 153 + struct PP_TemperatureRange temperatures; 154 + struct PP_StateSoftwareAlgorithmBlock software; 155 + struct PP_UVD_CLOCKS uvd_clocks; 156 + struct pp_hw_power_state hardware; 157 + }; 158 + 159 + 160 + /*Structure to hold a VCE state entry*/ 161 + struct PP_VCEState { 162 + uint32_t evclk; 163 + uint32_t ecclk; 164 + uint32_t sclk; 165 + uint32_t mclk; 166 + }; 167 + 168 + enum PP_MMProfilingState { 169 + PP_MMProfilingState_NA = 0, 170 + PP_MMProfilingState_Started, 171 + PP_MMProfilingState_Stopped 172 + }; 173 + 174 + struct PP_Clock_Engine_Request { 175 + unsigned long clientType; 176 + unsigned long ctxid; 177 + uint64_t context_handle; 178 + unsigned long sclk; 179 + unsigned long sclkHardMin; 180 + unsigned long mclk; 181 + unsigned long iclk; 182 + unsigned long evclk; 183 + unsigned long ecclk; 184 + unsigned long ecclkHardMin; 185 + unsigned long vclk; 186 + unsigned long dclk; 187 + unsigned long samclk; 188 + unsigned long acpclk; 189 + unsigned long sclkOverdrive; 190 + unsigned long mclkOverdrive; 191 + unsigned long sclk_threshold; 192 + unsigned long flag; 193 + unsigned long vclk_ceiling; 194 + unsigned long dclk_ceiling; 195 + unsigned long num_cus; 196 + unsigned long pmflag; 197 + enum PP_MMProfilingState MMProfilingState; 198 + }; 199 + 200 + #endif
+28
drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + 24 + extern bool acpi_atcs_functions_supported(void *device, 25 + uint32_t index); 26 + extern int acpi_pcie_perf_request(void *device, 27 + uint8_t perf_req, 28 + bool advertise);
+2 -1
drivers/gpu/drm/amd/powerplay/inc/pp_instance.h
··· 24 24 #define _PP_INSTANCE_H_ 25 25 26 26 #include "smumgr.h" 27 - 27 + #include "hwmgr.h" 28 28 29 29 struct pp_instance { 30 30 struct pp_smumgr *smu_mgr; 31 + struct pp_hwmgr *hwmgr; 31 32 }; 32 33 33 34 #endif
+36
drivers/gpu/drm/amd/powerplay/inc/pp_power_source.h
··· 1 + /* 2 + * Copyright 2015 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + 24 + #ifndef PP_POWERSOURCE_H 25 + #define PP_POWERSOURCE_H 26 + 27 + enum pp_power_source { 28 + PP_PowerSource_AC = 0, 29 + PP_PowerSource_DC, 30 + PP_PowerSource_LimitedPower, 31 + PP_PowerSource_LimitedPower_2, 32 + PP_PowerSource_Max 33 + }; 34 + 35 + 36 + #endif