hardwaremanager.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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 "pp_debug.h"
  24. #include <linux/errno.h>
  25. #include "hwmgr.h"
  26. #include "hardwaremanager.h"
  27. #include "power_state.h"
  28. #define PHM_FUNC_CHECK(hw) \
  29. do { \
  30. if ((hw) == NULL || (hw)->hwmgr_func == NULL) \
  31. return -EINVAL; \
  32. } while (0)
  33. bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr)
  34. {
  35. return hwmgr->block_hw_access;
  36. }
  37. int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block)
  38. {
  39. hwmgr->block_hw_access = block;
  40. return 0;
  41. }
  42. int phm_setup_asic(struct pp_hwmgr *hwmgr)
  43. {
  44. PHM_FUNC_CHECK(hwmgr);
  45. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  46. PHM_PlatformCaps_TablelessHardwareInterface)) {
  47. if (NULL != hwmgr->hwmgr_func->asic_setup)
  48. return hwmgr->hwmgr_func->asic_setup(hwmgr);
  49. } else {
  50. return phm_dispatch_table(hwmgr, &(hwmgr->setup_asic),
  51. NULL, NULL);
  52. }
  53. return 0;
  54. }
  55. int phm_power_down_asic(struct pp_hwmgr *hwmgr)
  56. {
  57. PHM_FUNC_CHECK(hwmgr);
  58. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  59. PHM_PlatformCaps_TablelessHardwareInterface)) {
  60. if (NULL != hwmgr->hwmgr_func->power_off_asic)
  61. return hwmgr->hwmgr_func->power_off_asic(hwmgr);
  62. } else {
  63. return phm_dispatch_table(hwmgr, &(hwmgr->power_down_asic),
  64. NULL, NULL);
  65. }
  66. return 0;
  67. }
  68. int phm_set_power_state(struct pp_hwmgr *hwmgr,
  69. const struct pp_hw_power_state *pcurrent_state,
  70. const struct pp_hw_power_state *pnew_power_state)
  71. {
  72. struct phm_set_power_state_input states;
  73. PHM_FUNC_CHECK(hwmgr);
  74. states.pcurrent_state = pcurrent_state;
  75. states.pnew_state = pnew_power_state;
  76. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  77. PHM_PlatformCaps_TablelessHardwareInterface)) {
  78. if (NULL != hwmgr->hwmgr_func->power_state_set)
  79. return hwmgr->hwmgr_func->power_state_set(hwmgr, &states);
  80. } else {
  81. return phm_dispatch_table(hwmgr, &(hwmgr->set_power_state), &states, NULL);
  82. }
  83. return 0;
  84. }
  85. int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
  86. {
  87. int ret = 1;
  88. bool enabled;
  89. PHM_FUNC_CHECK(hwmgr);
  90. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  91. PHM_PlatformCaps_TablelessHardwareInterface)) {
  92. if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable)
  93. ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr);
  94. } else {
  95. ret = phm_dispatch_table(hwmgr,
  96. &(hwmgr->enable_dynamic_state_management),
  97. NULL, NULL);
  98. }
  99. enabled = ret == 0;
  100. cgs_notify_dpm_enabled(hwmgr->device, enabled);
  101. return ret;
  102. }
  103. int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr)
  104. {
  105. int ret = -1;
  106. bool enabled;
  107. PHM_FUNC_CHECK(hwmgr);
  108. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  109. PHM_PlatformCaps_TablelessHardwareInterface)) {
  110. if (hwmgr->hwmgr_func->dynamic_state_management_disable)
  111. ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr);
  112. } else {
  113. ret = phm_dispatch_table(hwmgr,
  114. &(hwmgr->disable_dynamic_state_management),
  115. NULL, NULL);
  116. }
  117. enabled = ret == 0 ? false : true;
  118. cgs_notify_dpm_enabled(hwmgr->device, enabled);
  119. return ret;
  120. }
  121. int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level)
  122. {
  123. int ret = 0;
  124. PHM_FUNC_CHECK(hwmgr);
  125. if (hwmgr->hwmgr_func->force_dpm_level != NULL) {
  126. ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level);
  127. if (ret)
  128. return ret;
  129. if (hwmgr->hwmgr_func->set_power_profile_state) {
  130. if (hwmgr->current_power_profile == AMD_PP_GFX_PROFILE)
  131. ret = hwmgr->hwmgr_func->set_power_profile_state(
  132. hwmgr,
  133. &hwmgr->gfx_power_profile);
  134. else if (hwmgr->current_power_profile == AMD_PP_COMPUTE_PROFILE)
  135. ret = hwmgr->hwmgr_func->set_power_profile_state(
  136. hwmgr,
  137. &hwmgr->compute_power_profile);
  138. }
  139. }
  140. return ret;
  141. }
  142. int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
  143. struct pp_power_state *adjusted_ps,
  144. const struct pp_power_state *current_ps)
  145. {
  146. PHM_FUNC_CHECK(hwmgr);
  147. if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL)
  148. return hwmgr->hwmgr_func->apply_state_adjust_rules(
  149. hwmgr,
  150. adjusted_ps,
  151. current_ps);
  152. return 0;
  153. }
  154. int phm_powerdown_uvd(struct pp_hwmgr *hwmgr)
  155. {
  156. PHM_FUNC_CHECK(hwmgr);
  157. if (hwmgr->hwmgr_func->powerdown_uvd != NULL)
  158. return hwmgr->hwmgr_func->powerdown_uvd(hwmgr);
  159. return 0;
  160. }
  161. int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate)
  162. {
  163. PHM_FUNC_CHECK(hwmgr);
  164. if (hwmgr->hwmgr_func->powergate_uvd != NULL)
  165. return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate);
  166. return 0;
  167. }
  168. int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate)
  169. {
  170. PHM_FUNC_CHECK(hwmgr);
  171. if (hwmgr->hwmgr_func->powergate_vce != NULL)
  172. return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate);
  173. return 0;
  174. }
  175. int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr)
  176. {
  177. PHM_FUNC_CHECK(hwmgr);
  178. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  179. PHM_PlatformCaps_TablelessHardwareInterface)) {
  180. if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating)
  181. return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr);
  182. } else {
  183. return phm_dispatch_table(hwmgr, &(hwmgr->enable_clock_power_gatings), NULL, NULL);
  184. }
  185. return 0;
  186. }
  187. int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr)
  188. {
  189. PHM_FUNC_CHECK(hwmgr);
  190. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  191. PHM_PlatformCaps_TablelessHardwareInterface)) {
  192. if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating)
  193. return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr);
  194. }
  195. return 0;
  196. }
  197. int phm_display_configuration_changed(struct pp_hwmgr *hwmgr)
  198. {
  199. PHM_FUNC_CHECK(hwmgr);
  200. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  201. PHM_PlatformCaps_TablelessHardwareInterface)) {
  202. if (NULL != hwmgr->hwmgr_func->display_config_changed)
  203. hwmgr->hwmgr_func->display_config_changed(hwmgr);
  204. } else
  205. return phm_dispatch_table(hwmgr, &hwmgr->display_configuration_changed, NULL, NULL);
  206. return 0;
  207. }
  208. int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
  209. {
  210. PHM_FUNC_CHECK(hwmgr);
  211. if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
  212. PHM_PlatformCaps_TablelessHardwareInterface))
  213. if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment)
  214. hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr);
  215. return 0;
  216. }
  217. int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr)
  218. {
  219. PHM_FUNC_CHECK(hwmgr);
  220. if (hwmgr->hwmgr_func->stop_thermal_controller == NULL)
  221. return -EINVAL;
  222. return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr);
  223. }
  224. int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info)
  225. {
  226. PHM_FUNC_CHECK(hwmgr);
  227. if (hwmgr->hwmgr_func->register_internal_thermal_interrupt == NULL)
  228. return -EINVAL;
  229. return hwmgr->hwmgr_func->register_internal_thermal_interrupt(hwmgr, info);
  230. }
  231. /**
  232. * Initializes the thermal controller subsystem.
  233. *
  234. * @param pHwMgr the address of the powerplay hardware manager.
  235. * @param pTemperatureRange the address of the structure holding the temperature range.
  236. * @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher.
  237. */
  238. int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range)
  239. {
  240. return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), temperature_range, NULL);
  241. }
  242. bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
  243. {
  244. PHM_FUNC_CHECK(hwmgr);
  245. if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL)
  246. return false;
  247. return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr);
  248. }
  249. int phm_check_states_equal(struct pp_hwmgr *hwmgr,
  250. const struct pp_hw_power_state *pstate1,
  251. const struct pp_hw_power_state *pstate2,
  252. bool *equal)
  253. {
  254. PHM_FUNC_CHECK(hwmgr);
  255. if (hwmgr->hwmgr_func->check_states_equal == NULL)
  256. return -EINVAL;
  257. return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal);
  258. }
  259. int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr,
  260. const struct amd_pp_display_configuration *display_config)
  261. {
  262. PHM_FUNC_CHECK(hwmgr);
  263. if (display_config == NULL)
  264. return -EINVAL;
  265. hwmgr->display_config = *display_config;
  266. if (hwmgr->hwmgr_func->store_cc6_data == NULL)
  267. return -EINVAL;
  268. /* TODO: pass other display configuration in the future */
  269. if (hwmgr->hwmgr_func->store_cc6_data)
  270. hwmgr->hwmgr_func->store_cc6_data(hwmgr,
  271. display_config->cpu_pstate_separation_time,
  272. display_config->cpu_cc6_disable,
  273. display_config->cpu_pstate_disable,
  274. display_config->nb_pstate_switch_disable);
  275. return 0;
  276. }
  277. int phm_get_dal_power_level(struct pp_hwmgr *hwmgr,
  278. struct amd_pp_simple_clock_info *info)
  279. {
  280. PHM_FUNC_CHECK(hwmgr);
  281. if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL)
  282. return -EINVAL;
  283. return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info);
  284. }
  285. int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr)
  286. {
  287. PHM_FUNC_CHECK(hwmgr);
  288. if (hwmgr->hwmgr_func->set_cpu_power_state != NULL)
  289. return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr);
  290. return 0;
  291. }
  292. int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state,
  293. PHM_PerformanceLevelDesignation designation, uint32_t index,
  294. PHM_PerformanceLevel *level)
  295. {
  296. PHM_FUNC_CHECK(hwmgr);
  297. if (hwmgr->hwmgr_func->get_performance_level == NULL)
  298. return -EINVAL;
  299. return hwmgr->hwmgr_func->get_performance_level(hwmgr, state, designation, index, level);
  300. }
  301. /**
  302. * Gets Clock Info.
  303. *
  304. * @param pHwMgr the address of the powerplay hardware manager.
  305. * @param pPowerState the address of the Power State structure.
  306. * @param pClockInfo the address of PP_ClockInfo structure where the result will be returned.
  307. * @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end.
  308. */
  309. int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *pclock_info,
  310. PHM_PerformanceLevelDesignation designation)
  311. {
  312. int result;
  313. PHM_PerformanceLevel performance_level;
  314. PHM_FUNC_CHECK(hwmgr);
  315. PP_ASSERT_WITH_CODE((NULL != state), "Invalid Input!", return -EINVAL);
  316. PP_ASSERT_WITH_CODE((NULL != pclock_info), "Invalid Input!", return -EINVAL);
  317. result = phm_get_performance_level(hwmgr, state, PHM_PerformanceLevelDesignation_Activity, 0, &performance_level);
  318. PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve minimum clocks.", return result);
  319. pclock_info->min_mem_clk = performance_level.memory_clock;
  320. pclock_info->min_eng_clk = performance_level.coreClock;
  321. pclock_info->min_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
  322. result = phm_get_performance_level(hwmgr, state, designation,
  323. (hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1), &performance_level);
  324. PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve maximum clocks.", return result);
  325. pclock_info->max_mem_clk = performance_level.memory_clock;
  326. pclock_info->max_eng_clk = performance_level.coreClock;
  327. pclock_info->max_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth;
  328. return 0;
  329. }
  330. int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info)
  331. {
  332. PHM_FUNC_CHECK(hwmgr);
  333. if (hwmgr->hwmgr_func->get_current_shallow_sleep_clocks == NULL)
  334. return -EINVAL;
  335. return hwmgr->hwmgr_func->get_current_shallow_sleep_clocks(hwmgr, state, clock_info);
  336. }
  337. int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks)
  338. {
  339. PHM_FUNC_CHECK(hwmgr);
  340. if (hwmgr->hwmgr_func->get_clock_by_type == NULL)
  341. return -EINVAL;
  342. return hwmgr->hwmgr_func->get_clock_by_type(hwmgr, type, clocks);
  343. }
  344. int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
  345. enum amd_pp_clock_type type,
  346. struct pp_clock_levels_with_latency *clocks)
  347. {
  348. PHM_FUNC_CHECK(hwmgr);
  349. if (hwmgr->hwmgr_func->get_clock_by_type_with_latency == NULL)
  350. return -EINVAL;
  351. return hwmgr->hwmgr_func->get_clock_by_type_with_latency(hwmgr, type, clocks);
  352. }
  353. int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
  354. enum amd_pp_clock_type type,
  355. struct pp_clock_levels_with_voltage *clocks)
  356. {
  357. PHM_FUNC_CHECK(hwmgr);
  358. if (hwmgr->hwmgr_func->get_clock_by_type_with_voltage == NULL)
  359. return -EINVAL;
  360. return hwmgr->hwmgr_func->get_clock_by_type_with_voltage(hwmgr, type, clocks);
  361. }
  362. int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr,
  363. struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
  364. {
  365. PHM_FUNC_CHECK(hwmgr);
  366. if (!hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges)
  367. return -EINVAL;
  368. return hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges(hwmgr,
  369. wm_with_clock_ranges);
  370. }
  371. int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
  372. struct pp_display_clock_request *clock)
  373. {
  374. PHM_FUNC_CHECK(hwmgr);
  375. if (!hwmgr->hwmgr_func->display_clock_voltage_request)
  376. return -EINVAL;
  377. return hwmgr->hwmgr_func->display_clock_voltage_request(hwmgr, clock);
  378. }
  379. int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
  380. {
  381. PHM_FUNC_CHECK(hwmgr);
  382. if (hwmgr->hwmgr_func->get_max_high_clocks == NULL)
  383. return -EINVAL;
  384. return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks);
  385. }
  386. int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr)
  387. {
  388. PHM_FUNC_CHECK(hwmgr);
  389. if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL)
  390. return -EINVAL;
  391. return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr);
  392. }