18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2013 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <linux/pci.h> 258c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#include "cikd.h" 288c2ecf20Sopenharmony_ci#include "kv_dpm.h" 298c2ecf20Sopenharmony_ci#include "r600_dpm.h" 308c2ecf20Sopenharmony_ci#include "radeon.h" 318c2ecf20Sopenharmony_ci#include "radeon_asic.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define KV_MAX_DEEPSLEEP_DIVIDER_ID 5 348c2ecf20Sopenharmony_ci#define KV_MINIMUM_ENGINE_CLOCK 800 358c2ecf20Sopenharmony_ci#define SMC_RAM_END 0x40000 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic int kv_enable_nb_dpm(struct radeon_device *rdev, 388c2ecf20Sopenharmony_ci bool enable); 398c2ecf20Sopenharmony_cistatic void kv_init_graphics_levels(struct radeon_device *rdev); 408c2ecf20Sopenharmony_cistatic int kv_calculate_ds_divider(struct radeon_device *rdev); 418c2ecf20Sopenharmony_cistatic int kv_calculate_nbps_level_settings(struct radeon_device *rdev); 428c2ecf20Sopenharmony_cistatic int kv_calculate_dpm_settings(struct radeon_device *rdev); 438c2ecf20Sopenharmony_cistatic void kv_enable_new_levels(struct radeon_device *rdev); 448c2ecf20Sopenharmony_cistatic void kv_program_nbps_index_settings(struct radeon_device *rdev, 458c2ecf20Sopenharmony_ci struct radeon_ps *new_rps); 468c2ecf20Sopenharmony_cistatic int kv_set_enabled_level(struct radeon_device *rdev, u32 level); 478c2ecf20Sopenharmony_cistatic int kv_set_enabled_levels(struct radeon_device *rdev); 488c2ecf20Sopenharmony_cistatic int kv_force_dpm_highest(struct radeon_device *rdev); 498c2ecf20Sopenharmony_cistatic int kv_force_dpm_lowest(struct radeon_device *rdev); 508c2ecf20Sopenharmony_cistatic void kv_apply_state_adjust_rules(struct radeon_device *rdev, 518c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 528c2ecf20Sopenharmony_ci struct radeon_ps *old_rps); 538c2ecf20Sopenharmony_cistatic int kv_set_thermal_temperature_range(struct radeon_device *rdev, 548c2ecf20Sopenharmony_ci int min_temp, int max_temp); 558c2ecf20Sopenharmony_cistatic int kv_init_fps_limits(struct radeon_device *rdev); 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_civoid kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); 588c2ecf20Sopenharmony_cistatic void kv_dpm_powergate_vce(struct radeon_device *rdev, bool gate); 598c2ecf20Sopenharmony_cistatic void kv_dpm_powergate_samu(struct radeon_device *rdev, bool gate); 608c2ecf20Sopenharmony_cistatic void kv_dpm_powergate_acp(struct radeon_device *rdev, bool gate); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ciextern void cik_enter_rlc_safe_mode(struct radeon_device *rdev); 638c2ecf20Sopenharmony_ciextern void cik_exit_rlc_safe_mode(struct radeon_device *rdev); 648c2ecf20Sopenharmony_ciextern void cik_update_cg(struct radeon_device *rdev, 658c2ecf20Sopenharmony_ci u32 block, bool enable); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_values sx_local_cac_cfg_kv[] = 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci { 0, 4, 1 }, 708c2ecf20Sopenharmony_ci { 1, 4, 1 }, 718c2ecf20Sopenharmony_ci { 2, 5, 1 }, 728c2ecf20Sopenharmony_ci { 3, 4, 2 }, 738c2ecf20Sopenharmony_ci { 4, 1, 1 }, 748c2ecf20Sopenharmony_ci { 5, 5, 2 }, 758c2ecf20Sopenharmony_ci { 6, 6, 1 }, 768c2ecf20Sopenharmony_ci { 7, 9, 2 }, 778c2ecf20Sopenharmony_ci { 0xffffffff } 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_values mc0_local_cac_cfg_kv[] = 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci { 0, 4, 1 }, 838c2ecf20Sopenharmony_ci { 0xffffffff } 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_values mc1_local_cac_cfg_kv[] = 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci { 0, 4, 1 }, 898c2ecf20Sopenharmony_ci { 0xffffffff } 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_values mc2_local_cac_cfg_kv[] = 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci { 0, 4, 1 }, 958c2ecf20Sopenharmony_ci { 0xffffffff } 968c2ecf20Sopenharmony_ci}; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_values mc3_local_cac_cfg_kv[] = 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci { 0, 4, 1 }, 1018c2ecf20Sopenharmony_ci { 0xffffffff } 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_values cpl_local_cac_cfg_kv[] = 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci { 0, 4, 1 }, 1078c2ecf20Sopenharmony_ci { 1, 4, 1 }, 1088c2ecf20Sopenharmony_ci { 2, 5, 1 }, 1098c2ecf20Sopenharmony_ci { 3, 4, 1 }, 1108c2ecf20Sopenharmony_ci { 4, 1, 1 }, 1118c2ecf20Sopenharmony_ci { 5, 5, 1 }, 1128c2ecf20Sopenharmony_ci { 6, 6, 1 }, 1138c2ecf20Sopenharmony_ci { 7, 9, 1 }, 1148c2ecf20Sopenharmony_ci { 8, 4, 1 }, 1158c2ecf20Sopenharmony_ci { 9, 2, 1 }, 1168c2ecf20Sopenharmony_ci { 10, 3, 1 }, 1178c2ecf20Sopenharmony_ci { 11, 6, 1 }, 1188c2ecf20Sopenharmony_ci { 12, 8, 2 }, 1198c2ecf20Sopenharmony_ci { 13, 1, 1 }, 1208c2ecf20Sopenharmony_ci { 14, 2, 1 }, 1218c2ecf20Sopenharmony_ci { 15, 3, 1 }, 1228c2ecf20Sopenharmony_ci { 16, 1, 1 }, 1238c2ecf20Sopenharmony_ci { 17, 4, 1 }, 1248c2ecf20Sopenharmony_ci { 18, 3, 1 }, 1258c2ecf20Sopenharmony_ci { 19, 1, 1 }, 1268c2ecf20Sopenharmony_ci { 20, 8, 1 }, 1278c2ecf20Sopenharmony_ci { 21, 5, 1 }, 1288c2ecf20Sopenharmony_ci { 22, 1, 1 }, 1298c2ecf20Sopenharmony_ci { 23, 1, 1 }, 1308c2ecf20Sopenharmony_ci { 24, 4, 1 }, 1318c2ecf20Sopenharmony_ci { 27, 6, 1 }, 1328c2ecf20Sopenharmony_ci { 28, 1, 1 }, 1338c2ecf20Sopenharmony_ci { 0xffffffff } 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_reg sx0_cac_config_reg[] = 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci { 0xc0400d00, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_reg mc0_cac_config_reg[] = 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci { 0xc0400d30, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } 1448c2ecf20Sopenharmony_ci}; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_reg mc1_cac_config_reg[] = 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci { 0xc0400d3c, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_reg mc2_cac_config_reg[] = 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci { 0xc0400d48, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } 1548c2ecf20Sopenharmony_ci}; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_reg mc3_cac_config_reg[] = 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci { 0xc0400d54, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } 1598c2ecf20Sopenharmony_ci}; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic const struct kv_lcac_config_reg cpl_cac_config_reg[] = 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci { 0xc0400d80, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } 1648c2ecf20Sopenharmony_ci}; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic const struct kv_pt_config_reg didt_config_kv[] = 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci { 0x10, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 1698c2ecf20Sopenharmony_ci { 0x10, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 1708c2ecf20Sopenharmony_ci { 0x10, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 1718c2ecf20Sopenharmony_ci { 0x10, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 1728c2ecf20Sopenharmony_ci { 0x11, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 1738c2ecf20Sopenharmony_ci { 0x11, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 1748c2ecf20Sopenharmony_ci { 0x11, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 1758c2ecf20Sopenharmony_ci { 0x11, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 1768c2ecf20Sopenharmony_ci { 0x12, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 1778c2ecf20Sopenharmony_ci { 0x12, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 1788c2ecf20Sopenharmony_ci { 0x12, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 1798c2ecf20Sopenharmony_ci { 0x12, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 1808c2ecf20Sopenharmony_ci { 0x2, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, 1818c2ecf20Sopenharmony_ci { 0x2, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, 1828c2ecf20Sopenharmony_ci { 0x2, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, 1838c2ecf20Sopenharmony_ci { 0x1, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 1848c2ecf20Sopenharmony_ci { 0x1, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 1858c2ecf20Sopenharmony_ci { 0x0, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 1868c2ecf20Sopenharmony_ci { 0x30, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 1878c2ecf20Sopenharmony_ci { 0x30, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 1888c2ecf20Sopenharmony_ci { 0x30, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 1898c2ecf20Sopenharmony_ci { 0x30, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 1908c2ecf20Sopenharmony_ci { 0x31, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 1918c2ecf20Sopenharmony_ci { 0x31, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 1928c2ecf20Sopenharmony_ci { 0x31, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 1938c2ecf20Sopenharmony_ci { 0x31, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 1948c2ecf20Sopenharmony_ci { 0x32, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 1958c2ecf20Sopenharmony_ci { 0x32, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 1968c2ecf20Sopenharmony_ci { 0x32, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 1978c2ecf20Sopenharmony_ci { 0x32, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 1988c2ecf20Sopenharmony_ci { 0x22, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, 1998c2ecf20Sopenharmony_ci { 0x22, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, 2008c2ecf20Sopenharmony_ci { 0x22, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, 2018c2ecf20Sopenharmony_ci { 0x21, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 2028c2ecf20Sopenharmony_ci { 0x21, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 2038c2ecf20Sopenharmony_ci { 0x20, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2048c2ecf20Sopenharmony_ci { 0x50, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2058c2ecf20Sopenharmony_ci { 0x50, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 2068c2ecf20Sopenharmony_ci { 0x50, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 2078c2ecf20Sopenharmony_ci { 0x50, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 2088c2ecf20Sopenharmony_ci { 0x51, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2098c2ecf20Sopenharmony_ci { 0x51, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 2108c2ecf20Sopenharmony_ci { 0x51, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 2118c2ecf20Sopenharmony_ci { 0x51, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 2128c2ecf20Sopenharmony_ci { 0x52, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2138c2ecf20Sopenharmony_ci { 0x52, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 2148c2ecf20Sopenharmony_ci { 0x52, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 2158c2ecf20Sopenharmony_ci { 0x52, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 2168c2ecf20Sopenharmony_ci { 0x42, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, 2178c2ecf20Sopenharmony_ci { 0x42, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, 2188c2ecf20Sopenharmony_ci { 0x42, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, 2198c2ecf20Sopenharmony_ci { 0x41, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 2208c2ecf20Sopenharmony_ci { 0x41, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 2218c2ecf20Sopenharmony_ci { 0x40, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2228c2ecf20Sopenharmony_ci { 0x70, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2238c2ecf20Sopenharmony_ci { 0x70, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 2248c2ecf20Sopenharmony_ci { 0x70, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 2258c2ecf20Sopenharmony_ci { 0x70, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 2268c2ecf20Sopenharmony_ci { 0x71, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2278c2ecf20Sopenharmony_ci { 0x71, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 2288c2ecf20Sopenharmony_ci { 0x71, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 2298c2ecf20Sopenharmony_ci { 0x71, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 2308c2ecf20Sopenharmony_ci { 0x72, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2318c2ecf20Sopenharmony_ci { 0x72, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, 2328c2ecf20Sopenharmony_ci { 0x72, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, 2338c2ecf20Sopenharmony_ci { 0x72, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, 2348c2ecf20Sopenharmony_ci { 0x62, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, 2358c2ecf20Sopenharmony_ci { 0x62, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, 2368c2ecf20Sopenharmony_ci { 0x62, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, 2378c2ecf20Sopenharmony_ci { 0x61, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 2388c2ecf20Sopenharmony_ci { 0x61, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, 2398c2ecf20Sopenharmony_ci { 0x60, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, 2408c2ecf20Sopenharmony_ci { 0xFFFFFFFF } 2418c2ecf20Sopenharmony_ci}; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic struct kv_ps *kv_get_ps(struct radeon_ps *rps) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci struct kv_ps *ps = rps->ps_priv; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return ps; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic struct kv_power_info *kv_get_pi(struct radeon_device *rdev) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci struct kv_power_info *pi = rdev->pm.dpm.priv; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci return pi; 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci#if 0 2588c2ecf20Sopenharmony_cistatic void kv_program_local_cac_table(struct radeon_device *rdev, 2598c2ecf20Sopenharmony_ci const struct kv_lcac_config_values *local_cac_table, 2608c2ecf20Sopenharmony_ci const struct kv_lcac_config_reg *local_cac_reg) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci u32 i, count, data; 2638c2ecf20Sopenharmony_ci const struct kv_lcac_config_values *values = local_cac_table; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci while (values->block_id != 0xffffffff) { 2668c2ecf20Sopenharmony_ci count = values->signal_id; 2678c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 2688c2ecf20Sopenharmony_ci data = ((values->block_id << local_cac_reg->block_shift) & 2698c2ecf20Sopenharmony_ci local_cac_reg->block_mask); 2708c2ecf20Sopenharmony_ci data |= ((i << local_cac_reg->signal_shift) & 2718c2ecf20Sopenharmony_ci local_cac_reg->signal_mask); 2728c2ecf20Sopenharmony_ci data |= ((values->t << local_cac_reg->t_shift) & 2738c2ecf20Sopenharmony_ci local_cac_reg->t_mask); 2748c2ecf20Sopenharmony_ci data |= ((1 << local_cac_reg->enable_shift) & 2758c2ecf20Sopenharmony_ci local_cac_reg->enable_mask); 2768c2ecf20Sopenharmony_ci WREG32_SMC(local_cac_reg->cntl, data); 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci values++; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci#endif 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic int kv_program_pt_config_registers(struct radeon_device *rdev, 2848c2ecf20Sopenharmony_ci const struct kv_pt_config_reg *cac_config_regs) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci const struct kv_pt_config_reg *config_regs = cac_config_regs; 2878c2ecf20Sopenharmony_ci u32 data; 2888c2ecf20Sopenharmony_ci u32 cache = 0; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (config_regs == NULL) 2918c2ecf20Sopenharmony_ci return -EINVAL; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci while (config_regs->offset != 0xFFFFFFFF) { 2948c2ecf20Sopenharmony_ci if (config_regs->type == KV_CONFIGREG_CACHE) { 2958c2ecf20Sopenharmony_ci cache |= ((config_regs->value << config_regs->shift) & config_regs->mask); 2968c2ecf20Sopenharmony_ci } else { 2978c2ecf20Sopenharmony_ci switch (config_regs->type) { 2988c2ecf20Sopenharmony_ci case KV_CONFIGREG_SMC_IND: 2998c2ecf20Sopenharmony_ci data = RREG32_SMC(config_regs->offset); 3008c2ecf20Sopenharmony_ci break; 3018c2ecf20Sopenharmony_ci case KV_CONFIGREG_DIDT_IND: 3028c2ecf20Sopenharmony_ci data = RREG32_DIDT(config_regs->offset); 3038c2ecf20Sopenharmony_ci break; 3048c2ecf20Sopenharmony_ci default: 3058c2ecf20Sopenharmony_ci data = RREG32(config_regs->offset << 2); 3068c2ecf20Sopenharmony_ci break; 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci data &= ~config_regs->mask; 3108c2ecf20Sopenharmony_ci data |= ((config_regs->value << config_regs->shift) & config_regs->mask); 3118c2ecf20Sopenharmony_ci data |= cache; 3128c2ecf20Sopenharmony_ci cache = 0; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci switch (config_regs->type) { 3158c2ecf20Sopenharmony_ci case KV_CONFIGREG_SMC_IND: 3168c2ecf20Sopenharmony_ci WREG32_SMC(config_regs->offset, data); 3178c2ecf20Sopenharmony_ci break; 3188c2ecf20Sopenharmony_ci case KV_CONFIGREG_DIDT_IND: 3198c2ecf20Sopenharmony_ci WREG32_DIDT(config_regs->offset, data); 3208c2ecf20Sopenharmony_ci break; 3218c2ecf20Sopenharmony_ci default: 3228c2ecf20Sopenharmony_ci WREG32(config_regs->offset << 2, data); 3238c2ecf20Sopenharmony_ci break; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci config_regs++; 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci return 0; 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic void kv_do_enable_didt(struct radeon_device *rdev, bool enable) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 3358c2ecf20Sopenharmony_ci u32 data; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (pi->caps_sq_ramping) { 3388c2ecf20Sopenharmony_ci data = RREG32_DIDT(DIDT_SQ_CTRL0); 3398c2ecf20Sopenharmony_ci if (enable) 3408c2ecf20Sopenharmony_ci data |= DIDT_CTRL_EN; 3418c2ecf20Sopenharmony_ci else 3428c2ecf20Sopenharmony_ci data &= ~DIDT_CTRL_EN; 3438c2ecf20Sopenharmony_ci WREG32_DIDT(DIDT_SQ_CTRL0, data); 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (pi->caps_db_ramping) { 3478c2ecf20Sopenharmony_ci data = RREG32_DIDT(DIDT_DB_CTRL0); 3488c2ecf20Sopenharmony_ci if (enable) 3498c2ecf20Sopenharmony_ci data |= DIDT_CTRL_EN; 3508c2ecf20Sopenharmony_ci else 3518c2ecf20Sopenharmony_ci data &= ~DIDT_CTRL_EN; 3528c2ecf20Sopenharmony_ci WREG32_DIDT(DIDT_DB_CTRL0, data); 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci if (pi->caps_td_ramping) { 3568c2ecf20Sopenharmony_ci data = RREG32_DIDT(DIDT_TD_CTRL0); 3578c2ecf20Sopenharmony_ci if (enable) 3588c2ecf20Sopenharmony_ci data |= DIDT_CTRL_EN; 3598c2ecf20Sopenharmony_ci else 3608c2ecf20Sopenharmony_ci data &= ~DIDT_CTRL_EN; 3618c2ecf20Sopenharmony_ci WREG32_DIDT(DIDT_TD_CTRL0, data); 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (pi->caps_tcp_ramping) { 3658c2ecf20Sopenharmony_ci data = RREG32_DIDT(DIDT_TCP_CTRL0); 3668c2ecf20Sopenharmony_ci if (enable) 3678c2ecf20Sopenharmony_ci data |= DIDT_CTRL_EN; 3688c2ecf20Sopenharmony_ci else 3698c2ecf20Sopenharmony_ci data &= ~DIDT_CTRL_EN; 3708c2ecf20Sopenharmony_ci WREG32_DIDT(DIDT_TCP_CTRL0, data); 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic int kv_enable_didt(struct radeon_device *rdev, bool enable) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 3778c2ecf20Sopenharmony_ci int ret; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci if (pi->caps_sq_ramping || 3808c2ecf20Sopenharmony_ci pi->caps_db_ramping || 3818c2ecf20Sopenharmony_ci pi->caps_td_ramping || 3828c2ecf20Sopenharmony_ci pi->caps_tcp_ramping) { 3838c2ecf20Sopenharmony_ci cik_enter_rlc_safe_mode(rdev); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (enable) { 3868c2ecf20Sopenharmony_ci ret = kv_program_pt_config_registers(rdev, didt_config_kv); 3878c2ecf20Sopenharmony_ci if (ret) { 3888c2ecf20Sopenharmony_ci cik_exit_rlc_safe_mode(rdev); 3898c2ecf20Sopenharmony_ci return ret; 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci } 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci kv_do_enable_didt(rdev, enable); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci cik_exit_rlc_safe_mode(rdev); 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci return 0; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci#if 0 4028c2ecf20Sopenharmony_cistatic void kv_initialize_hardware_cac_manager(struct radeon_device *rdev) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (pi->caps_cac) { 4078c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_SX0_OVR_SEL, 0); 4088c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_SX0_OVR_VAL, 0); 4098c2ecf20Sopenharmony_ci kv_program_local_cac_table(rdev, sx_local_cac_cfg_kv, sx0_cac_config_reg); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC0_OVR_SEL, 0); 4128c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC0_OVR_VAL, 0); 4138c2ecf20Sopenharmony_ci kv_program_local_cac_table(rdev, mc0_local_cac_cfg_kv, mc0_cac_config_reg); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC1_OVR_SEL, 0); 4168c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC1_OVR_VAL, 0); 4178c2ecf20Sopenharmony_ci kv_program_local_cac_table(rdev, mc1_local_cac_cfg_kv, mc1_cac_config_reg); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC2_OVR_SEL, 0); 4208c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC2_OVR_VAL, 0); 4218c2ecf20Sopenharmony_ci kv_program_local_cac_table(rdev, mc2_local_cac_cfg_kv, mc2_cac_config_reg); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC3_OVR_SEL, 0); 4248c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_MC3_OVR_VAL, 0); 4258c2ecf20Sopenharmony_ci kv_program_local_cac_table(rdev, mc3_local_cac_cfg_kv, mc3_cac_config_reg); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_CPL_OVR_SEL, 0); 4288c2ecf20Sopenharmony_ci WREG32_SMC(LCAC_CPL_OVR_VAL, 0); 4298c2ecf20Sopenharmony_ci kv_program_local_cac_table(rdev, cpl_local_cac_cfg_kv, cpl_cac_config_reg); 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci#endif 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic int kv_enable_smc_cac(struct radeon_device *rdev, bool enable) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 4378c2ecf20Sopenharmony_ci int ret = 0; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (pi->caps_cac) { 4408c2ecf20Sopenharmony_ci if (enable) { 4418c2ecf20Sopenharmony_ci ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_EnableCac); 4428c2ecf20Sopenharmony_ci if (ret) 4438c2ecf20Sopenharmony_ci pi->cac_enabled = false; 4448c2ecf20Sopenharmony_ci else 4458c2ecf20Sopenharmony_ci pi->cac_enabled = true; 4468c2ecf20Sopenharmony_ci } else if (pi->cac_enabled) { 4478c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_DisableCac); 4488c2ecf20Sopenharmony_ci pi->cac_enabled = false; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci return ret; 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic int kv_process_firmware_header(struct radeon_device *rdev) 4568c2ecf20Sopenharmony_ci{ 4578c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 4588c2ecf20Sopenharmony_ci u32 tmp; 4598c2ecf20Sopenharmony_ci int ret; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci ret = kv_read_smc_sram_dword(rdev, SMU7_FIRMWARE_HEADER_LOCATION + 4628c2ecf20Sopenharmony_ci offsetof(SMU7_Firmware_Header, DpmTable), 4638c2ecf20Sopenharmony_ci &tmp, pi->sram_end); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci if (ret == 0) 4668c2ecf20Sopenharmony_ci pi->dpm_table_start = tmp; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci ret = kv_read_smc_sram_dword(rdev, SMU7_FIRMWARE_HEADER_LOCATION + 4698c2ecf20Sopenharmony_ci offsetof(SMU7_Firmware_Header, SoftRegisters), 4708c2ecf20Sopenharmony_ci &tmp, pi->sram_end); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (ret == 0) 4738c2ecf20Sopenharmony_ci pi->soft_regs_start = tmp; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci return ret; 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic int kv_enable_dpm_voltage_scaling(struct radeon_device *rdev) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 4818c2ecf20Sopenharmony_ci int ret; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci pi->graphics_voltage_change_enable = 1; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 4868c2ecf20Sopenharmony_ci pi->dpm_table_start + 4878c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, GraphicsVoltageChangeEnable), 4888c2ecf20Sopenharmony_ci &pi->graphics_voltage_change_enable, 4898c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci return ret; 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic int kv_set_dpm_interval(struct radeon_device *rdev) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 4978c2ecf20Sopenharmony_ci int ret; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci pi->graphics_interval = 1; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 5028c2ecf20Sopenharmony_ci pi->dpm_table_start + 5038c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, GraphicsInterval), 5048c2ecf20Sopenharmony_ci &pi->graphics_interval, 5058c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci return ret; 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic int kv_set_dpm_boot_state(struct radeon_device *rdev) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 5138c2ecf20Sopenharmony_ci int ret; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 5168c2ecf20Sopenharmony_ci pi->dpm_table_start + 5178c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, GraphicsBootLevel), 5188c2ecf20Sopenharmony_ci &pi->graphics_boot_level, 5198c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci return ret; 5228c2ecf20Sopenharmony_ci} 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic void kv_program_vc(struct radeon_device *rdev) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci WREG32_SMC(CG_FTV_0, 0x3FFFC100); 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic void kv_clear_vc(struct radeon_device *rdev) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci WREG32_SMC(CG_FTV_0, 0); 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic int kv_set_divider_value(struct radeon_device *rdev, 5358c2ecf20Sopenharmony_ci u32 index, u32 sclk) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 5388c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 5398c2ecf20Sopenharmony_ci int ret; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 5428c2ecf20Sopenharmony_ci sclk, false, ÷rs); 5438c2ecf20Sopenharmony_ci if (ret) 5448c2ecf20Sopenharmony_ci return ret; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci pi->graphics_level[index].SclkDid = (u8)dividers.post_div; 5478c2ecf20Sopenharmony_ci pi->graphics_level[index].SclkFrequency = cpu_to_be32(sclk); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci return 0; 5508c2ecf20Sopenharmony_ci} 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_cistatic u32 kv_convert_vid2_to_vid7(struct radeon_device *rdev, 5538c2ecf20Sopenharmony_ci struct sumo_vid_mapping_table *vid_mapping_table, 5548c2ecf20Sopenharmony_ci u32 vid_2bit) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *vddc_sclk_table = 5578c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 5588c2ecf20Sopenharmony_ci u32 i; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (vddc_sclk_table && vddc_sclk_table->count) { 5618c2ecf20Sopenharmony_ci if (vid_2bit < vddc_sclk_table->count) 5628c2ecf20Sopenharmony_ci return vddc_sclk_table->entries[vid_2bit].v; 5638c2ecf20Sopenharmony_ci else 5648c2ecf20Sopenharmony_ci return vddc_sclk_table->entries[vddc_sclk_table->count - 1].v; 5658c2ecf20Sopenharmony_ci } else { 5668c2ecf20Sopenharmony_ci for (i = 0; i < vid_mapping_table->num_entries; i++) { 5678c2ecf20Sopenharmony_ci if (vid_mapping_table->entries[i].vid_2bit == vid_2bit) 5688c2ecf20Sopenharmony_ci return vid_mapping_table->entries[i].vid_7bit; 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_cistatic u32 kv_convert_vid7_to_vid2(struct radeon_device *rdev, 5758c2ecf20Sopenharmony_ci struct sumo_vid_mapping_table *vid_mapping_table, 5768c2ecf20Sopenharmony_ci u32 vid_7bit) 5778c2ecf20Sopenharmony_ci{ 5788c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *vddc_sclk_table = 5798c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 5808c2ecf20Sopenharmony_ci u32 i; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci if (vddc_sclk_table && vddc_sclk_table->count) { 5838c2ecf20Sopenharmony_ci for (i = 0; i < vddc_sclk_table->count; i++) { 5848c2ecf20Sopenharmony_ci if (vddc_sclk_table->entries[i].v == vid_7bit) 5858c2ecf20Sopenharmony_ci return i; 5868c2ecf20Sopenharmony_ci } 5878c2ecf20Sopenharmony_ci return vddc_sclk_table->count - 1; 5888c2ecf20Sopenharmony_ci } else { 5898c2ecf20Sopenharmony_ci for (i = 0; i < vid_mapping_table->num_entries; i++) { 5908c2ecf20Sopenharmony_ci if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) 5918c2ecf20Sopenharmony_ci return vid_mapping_table->entries[i].vid_2bit; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_cistatic u16 kv_convert_8bit_index_to_voltage(struct radeon_device *rdev, 5998c2ecf20Sopenharmony_ci u16 voltage) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci return 6200 - (voltage * 25); 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_cistatic u16 kv_convert_2bit_index_to_voltage(struct radeon_device *rdev, 6058c2ecf20Sopenharmony_ci u32 vid_2bit) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 6088c2ecf20Sopenharmony_ci u32 vid_8bit = kv_convert_vid2_to_vid7(rdev, 6098c2ecf20Sopenharmony_ci &pi->sys_info.vid_mapping_table, 6108c2ecf20Sopenharmony_ci vid_2bit); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci return kv_convert_8bit_index_to_voltage(rdev, (u16)vid_8bit); 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_cistatic int kv_set_vid(struct radeon_device *rdev, u32 index, u32 vid) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci pi->graphics_level[index].VoltageDownH = (u8)pi->voltage_drop_t; 6218c2ecf20Sopenharmony_ci pi->graphics_level[index].MinVddNb = 6228c2ecf20Sopenharmony_ci cpu_to_be32(kv_convert_2bit_index_to_voltage(rdev, vid)); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci return 0; 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_cistatic int kv_set_at(struct radeon_device *rdev, u32 index, u32 at) 6288c2ecf20Sopenharmony_ci{ 6298c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci pi->graphics_level[index].AT = cpu_to_be16((u16)at); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci return 0; 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic void kv_dpm_power_level_enable(struct radeon_device *rdev, 6378c2ecf20Sopenharmony_ci u32 index, bool enable) 6388c2ecf20Sopenharmony_ci{ 6398c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci pi->graphics_level[index].EnabledForActivity = enable ? 1 : 0; 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic void kv_start_dpm(struct radeon_device *rdev) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci u32 tmp = RREG32_SMC(GENERAL_PWRMGT); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci tmp |= GLOBAL_PWRMGT_EN; 6498c2ecf20Sopenharmony_ci WREG32_SMC(GENERAL_PWRMGT, tmp); 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci kv_smc_dpm_enable(rdev, true); 6528c2ecf20Sopenharmony_ci} 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_cistatic void kv_stop_dpm(struct radeon_device *rdev) 6558c2ecf20Sopenharmony_ci{ 6568c2ecf20Sopenharmony_ci kv_smc_dpm_enable(rdev, false); 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic void kv_start_am(struct radeon_device *rdev) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci u32 sclk_pwrmgt_cntl = RREG32_SMC(SCLK_PWRMGT_CNTL); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci sclk_pwrmgt_cntl &= ~(RESET_SCLK_CNT | RESET_BUSY_CNT); 6648c2ecf20Sopenharmony_ci sclk_pwrmgt_cntl |= DYNAMIC_PM_EN; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci WREG32_SMC(SCLK_PWRMGT_CNTL, sclk_pwrmgt_cntl); 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_cistatic void kv_reset_am(struct radeon_device *rdev) 6708c2ecf20Sopenharmony_ci{ 6718c2ecf20Sopenharmony_ci u32 sclk_pwrmgt_cntl = RREG32_SMC(SCLK_PWRMGT_CNTL); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci sclk_pwrmgt_cntl |= (RESET_SCLK_CNT | RESET_BUSY_CNT); 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci WREG32_SMC(SCLK_PWRMGT_CNTL, sclk_pwrmgt_cntl); 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_cistatic int kv_freeze_sclk_dpm(struct radeon_device *rdev, bool freeze) 6798c2ecf20Sopenharmony_ci{ 6808c2ecf20Sopenharmony_ci return kv_notify_message_to_smu(rdev, freeze ? 6818c2ecf20Sopenharmony_ci PPSMC_MSG_SCLKDPM_FreezeLevel : PPSMC_MSG_SCLKDPM_UnfreezeLevel); 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_cistatic int kv_force_lowest_valid(struct radeon_device *rdev) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci return kv_force_dpm_lowest(rdev); 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_cistatic int kv_unforce_levels(struct radeon_device *rdev) 6908c2ecf20Sopenharmony_ci{ 6918c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) 6928c2ecf20Sopenharmony_ci return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel); 6938c2ecf20Sopenharmony_ci else 6948c2ecf20Sopenharmony_ci return kv_set_enabled_levels(rdev); 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_cistatic int kv_update_sclk_t(struct radeon_device *rdev) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 7008c2ecf20Sopenharmony_ci u32 low_sclk_interrupt_t = 0; 7018c2ecf20Sopenharmony_ci int ret = 0; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (pi->caps_sclk_throttle_low_notification) { 7048c2ecf20Sopenharmony_ci low_sclk_interrupt_t = cpu_to_be32(pi->low_sclk_interrupt_t); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 7078c2ecf20Sopenharmony_ci pi->dpm_table_start + 7088c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, LowSclkInterruptT), 7098c2ecf20Sopenharmony_ci (u8 *)&low_sclk_interrupt_t, 7108c2ecf20Sopenharmony_ci sizeof(u32), pi->sram_end); 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci return ret; 7138c2ecf20Sopenharmony_ci} 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_cistatic int kv_program_bootup_state(struct radeon_device *rdev) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 7188c2ecf20Sopenharmony_ci u32 i; 7198c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 7208c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci if (table && table->count) { 7238c2ecf20Sopenharmony_ci for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { 7248c2ecf20Sopenharmony_ci if (table->entries[i].clk == pi->boot_pl.sclk) 7258c2ecf20Sopenharmony_ci break; 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci pi->graphics_boot_level = (u8)i; 7298c2ecf20Sopenharmony_ci kv_dpm_power_level_enable(rdev, i, true); 7308c2ecf20Sopenharmony_ci } else { 7318c2ecf20Sopenharmony_ci struct sumo_sclk_voltage_mapping_table *table = 7328c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci if (table->num_max_dpm_entries == 0) 7358c2ecf20Sopenharmony_ci return -EINVAL; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { 7388c2ecf20Sopenharmony_ci if (table->entries[i].sclk_frequency == pi->boot_pl.sclk) 7398c2ecf20Sopenharmony_ci break; 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci pi->graphics_boot_level = (u8)i; 7438c2ecf20Sopenharmony_ci kv_dpm_power_level_enable(rdev, i, true); 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci return 0; 7468c2ecf20Sopenharmony_ci} 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_cistatic int kv_enable_auto_thermal_throttling(struct radeon_device *rdev) 7498c2ecf20Sopenharmony_ci{ 7508c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 7518c2ecf20Sopenharmony_ci int ret; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci pi->graphics_therm_throttle_enable = 1; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 7568c2ecf20Sopenharmony_ci pi->dpm_table_start + 7578c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, GraphicsThermThrottleEnable), 7588c2ecf20Sopenharmony_ci &pi->graphics_therm_throttle_enable, 7598c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci return ret; 7628c2ecf20Sopenharmony_ci} 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_cistatic int kv_upload_dpm_settings(struct radeon_device *rdev) 7658c2ecf20Sopenharmony_ci{ 7668c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 7678c2ecf20Sopenharmony_ci int ret; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 7708c2ecf20Sopenharmony_ci pi->dpm_table_start + 7718c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, GraphicsLevel), 7728c2ecf20Sopenharmony_ci (u8 *)&pi->graphics_level, 7738c2ecf20Sopenharmony_ci sizeof(SMU7_Fusion_GraphicsLevel) * SMU7_MAX_LEVELS_GRAPHICS, 7748c2ecf20Sopenharmony_ci pi->sram_end); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci if (ret) 7778c2ecf20Sopenharmony_ci return ret; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 7808c2ecf20Sopenharmony_ci pi->dpm_table_start + 7818c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, GraphicsDpmLevelCount), 7828c2ecf20Sopenharmony_ci &pi->graphics_dpm_level_count, 7838c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci return ret; 7868c2ecf20Sopenharmony_ci} 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_cistatic u32 kv_get_clock_difference(u32 a, u32 b) 7898c2ecf20Sopenharmony_ci{ 7908c2ecf20Sopenharmony_ci return (a >= b) ? a - b : b - a; 7918c2ecf20Sopenharmony_ci} 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_cistatic u32 kv_get_clk_bypass(struct radeon_device *rdev, u32 clk) 7948c2ecf20Sopenharmony_ci{ 7958c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 7968c2ecf20Sopenharmony_ci u32 value; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci if (pi->caps_enable_dfs_bypass) { 7998c2ecf20Sopenharmony_ci if (kv_get_clock_difference(clk, 40000) < 200) 8008c2ecf20Sopenharmony_ci value = 3; 8018c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(clk, 30000) < 200) 8028c2ecf20Sopenharmony_ci value = 2; 8038c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(clk, 20000) < 200) 8048c2ecf20Sopenharmony_ci value = 7; 8058c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(clk, 15000) < 200) 8068c2ecf20Sopenharmony_ci value = 6; 8078c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(clk, 10000) < 200) 8088c2ecf20Sopenharmony_ci value = 8; 8098c2ecf20Sopenharmony_ci else 8108c2ecf20Sopenharmony_ci value = 0; 8118c2ecf20Sopenharmony_ci } else { 8128c2ecf20Sopenharmony_ci value = 0; 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci return value; 8168c2ecf20Sopenharmony_ci} 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistatic int kv_populate_uvd_table(struct radeon_device *rdev) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 8218c2ecf20Sopenharmony_ci struct radeon_uvd_clock_voltage_dependency_table *table = 8228c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; 8238c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 8248c2ecf20Sopenharmony_ci int ret; 8258c2ecf20Sopenharmony_ci u32 i; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci if (table == NULL || table->count == 0) 8288c2ecf20Sopenharmony_ci return 0; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci pi->uvd_level_count = 0; 8318c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 8328c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 8338c2ecf20Sopenharmony_ci (pi->high_voltage_t < table->entries[i].v)) 8348c2ecf20Sopenharmony_ci break; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci pi->uvd_level[i].VclkFrequency = cpu_to_be32(table->entries[i].vclk); 8378c2ecf20Sopenharmony_ci pi->uvd_level[i].DclkFrequency = cpu_to_be32(table->entries[i].dclk); 8388c2ecf20Sopenharmony_ci pi->uvd_level[i].MinVddNb = cpu_to_be16(table->entries[i].v); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci pi->uvd_level[i].VClkBypassCntl = 8418c2ecf20Sopenharmony_ci (u8)kv_get_clk_bypass(rdev, table->entries[i].vclk); 8428c2ecf20Sopenharmony_ci pi->uvd_level[i].DClkBypassCntl = 8438c2ecf20Sopenharmony_ci (u8)kv_get_clk_bypass(rdev, table->entries[i].dclk); 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 8468c2ecf20Sopenharmony_ci table->entries[i].vclk, false, ÷rs); 8478c2ecf20Sopenharmony_ci if (ret) 8488c2ecf20Sopenharmony_ci return ret; 8498c2ecf20Sopenharmony_ci pi->uvd_level[i].VclkDivider = (u8)dividers.post_div; 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 8528c2ecf20Sopenharmony_ci table->entries[i].dclk, false, ÷rs); 8538c2ecf20Sopenharmony_ci if (ret) 8548c2ecf20Sopenharmony_ci return ret; 8558c2ecf20Sopenharmony_ci pi->uvd_level[i].DclkDivider = (u8)dividers.post_div; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci pi->uvd_level_count++; 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 8618c2ecf20Sopenharmony_ci pi->dpm_table_start + 8628c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, UvdLevelCount), 8638c2ecf20Sopenharmony_ci (u8 *)&pi->uvd_level_count, 8648c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 8658c2ecf20Sopenharmony_ci if (ret) 8668c2ecf20Sopenharmony_ci return ret; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci pi->uvd_interval = 1; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 8718c2ecf20Sopenharmony_ci pi->dpm_table_start + 8728c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, UVDInterval), 8738c2ecf20Sopenharmony_ci &pi->uvd_interval, 8748c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 8758c2ecf20Sopenharmony_ci if (ret) 8768c2ecf20Sopenharmony_ci return ret; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 8798c2ecf20Sopenharmony_ci pi->dpm_table_start + 8808c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, UvdLevel), 8818c2ecf20Sopenharmony_ci (u8 *)&pi->uvd_level, 8828c2ecf20Sopenharmony_ci sizeof(SMU7_Fusion_UvdLevel) * SMU7_MAX_LEVELS_UVD, 8838c2ecf20Sopenharmony_ci pi->sram_end); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci return ret; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci} 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_cistatic int kv_populate_vce_table(struct radeon_device *rdev) 8908c2ecf20Sopenharmony_ci{ 8918c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 8928c2ecf20Sopenharmony_ci int ret; 8938c2ecf20Sopenharmony_ci u32 i; 8948c2ecf20Sopenharmony_ci struct radeon_vce_clock_voltage_dependency_table *table = 8958c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 8968c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci if (table == NULL || table->count == 0) 8998c2ecf20Sopenharmony_ci return 0; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci pi->vce_level_count = 0; 9028c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 9038c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 9048c2ecf20Sopenharmony_ci pi->high_voltage_t < table->entries[i].v) 9058c2ecf20Sopenharmony_ci break; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci pi->vce_level[i].Frequency = cpu_to_be32(table->entries[i].evclk); 9088c2ecf20Sopenharmony_ci pi->vce_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci pi->vce_level[i].ClkBypassCntl = 9118c2ecf20Sopenharmony_ci (u8)kv_get_clk_bypass(rdev, table->entries[i].evclk); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 9148c2ecf20Sopenharmony_ci table->entries[i].evclk, false, ÷rs); 9158c2ecf20Sopenharmony_ci if (ret) 9168c2ecf20Sopenharmony_ci return ret; 9178c2ecf20Sopenharmony_ci pi->vce_level[i].Divider = (u8)dividers.post_div; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci pi->vce_level_count++; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 9238c2ecf20Sopenharmony_ci pi->dpm_table_start + 9248c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, VceLevelCount), 9258c2ecf20Sopenharmony_ci (u8 *)&pi->vce_level_count, 9268c2ecf20Sopenharmony_ci sizeof(u8), 9278c2ecf20Sopenharmony_ci pi->sram_end); 9288c2ecf20Sopenharmony_ci if (ret) 9298c2ecf20Sopenharmony_ci return ret; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci pi->vce_interval = 1; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 9348c2ecf20Sopenharmony_ci pi->dpm_table_start + 9358c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, VCEInterval), 9368c2ecf20Sopenharmony_ci (u8 *)&pi->vce_interval, 9378c2ecf20Sopenharmony_ci sizeof(u8), 9388c2ecf20Sopenharmony_ci pi->sram_end); 9398c2ecf20Sopenharmony_ci if (ret) 9408c2ecf20Sopenharmony_ci return ret; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 9438c2ecf20Sopenharmony_ci pi->dpm_table_start + 9448c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, VceLevel), 9458c2ecf20Sopenharmony_ci (u8 *)&pi->vce_level, 9468c2ecf20Sopenharmony_ci sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_VCE, 9478c2ecf20Sopenharmony_ci pi->sram_end); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci return ret; 9508c2ecf20Sopenharmony_ci} 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_cistatic int kv_populate_samu_table(struct radeon_device *rdev) 9538c2ecf20Sopenharmony_ci{ 9548c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 9558c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 9568c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; 9578c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 9588c2ecf20Sopenharmony_ci int ret; 9598c2ecf20Sopenharmony_ci u32 i; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci if (table == NULL || table->count == 0) 9628c2ecf20Sopenharmony_ci return 0; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci pi->samu_level_count = 0; 9658c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 9668c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 9678c2ecf20Sopenharmony_ci pi->high_voltage_t < table->entries[i].v) 9688c2ecf20Sopenharmony_ci break; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci pi->samu_level[i].Frequency = cpu_to_be32(table->entries[i].clk); 9718c2ecf20Sopenharmony_ci pi->samu_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci pi->samu_level[i].ClkBypassCntl = 9748c2ecf20Sopenharmony_ci (u8)kv_get_clk_bypass(rdev, table->entries[i].clk); 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 9778c2ecf20Sopenharmony_ci table->entries[i].clk, false, ÷rs); 9788c2ecf20Sopenharmony_ci if (ret) 9798c2ecf20Sopenharmony_ci return ret; 9808c2ecf20Sopenharmony_ci pi->samu_level[i].Divider = (u8)dividers.post_div; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci pi->samu_level_count++; 9838c2ecf20Sopenharmony_ci } 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 9868c2ecf20Sopenharmony_ci pi->dpm_table_start + 9878c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, SamuLevelCount), 9888c2ecf20Sopenharmony_ci (u8 *)&pi->samu_level_count, 9898c2ecf20Sopenharmony_ci sizeof(u8), 9908c2ecf20Sopenharmony_ci pi->sram_end); 9918c2ecf20Sopenharmony_ci if (ret) 9928c2ecf20Sopenharmony_ci return ret; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci pi->samu_interval = 1; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 9978c2ecf20Sopenharmony_ci pi->dpm_table_start + 9988c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, SAMUInterval), 9998c2ecf20Sopenharmony_ci (u8 *)&pi->samu_interval, 10008c2ecf20Sopenharmony_ci sizeof(u8), 10018c2ecf20Sopenharmony_ci pi->sram_end); 10028c2ecf20Sopenharmony_ci if (ret) 10038c2ecf20Sopenharmony_ci return ret; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 10068c2ecf20Sopenharmony_ci pi->dpm_table_start + 10078c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, SamuLevel), 10088c2ecf20Sopenharmony_ci (u8 *)&pi->samu_level, 10098c2ecf20Sopenharmony_ci sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_SAMU, 10108c2ecf20Sopenharmony_ci pi->sram_end); 10118c2ecf20Sopenharmony_ci if (ret) 10128c2ecf20Sopenharmony_ci return ret; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci return ret; 10158c2ecf20Sopenharmony_ci} 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_cistatic int kv_populate_acp_table(struct radeon_device *rdev) 10198c2ecf20Sopenharmony_ci{ 10208c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 10218c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 10228c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; 10238c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 10248c2ecf20Sopenharmony_ci int ret; 10258c2ecf20Sopenharmony_ci u32 i; 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci if (table == NULL || table->count == 0) 10288c2ecf20Sopenharmony_ci return 0; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci pi->acp_level_count = 0; 10318c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 10328c2ecf20Sopenharmony_ci pi->acp_level[i].Frequency = cpu_to_be32(table->entries[i].clk); 10338c2ecf20Sopenharmony_ci pi->acp_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 10368c2ecf20Sopenharmony_ci table->entries[i].clk, false, ÷rs); 10378c2ecf20Sopenharmony_ci if (ret) 10388c2ecf20Sopenharmony_ci return ret; 10398c2ecf20Sopenharmony_ci pi->acp_level[i].Divider = (u8)dividers.post_div; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci pi->acp_level_count++; 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 10458c2ecf20Sopenharmony_ci pi->dpm_table_start + 10468c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, AcpLevelCount), 10478c2ecf20Sopenharmony_ci (u8 *)&pi->acp_level_count, 10488c2ecf20Sopenharmony_ci sizeof(u8), 10498c2ecf20Sopenharmony_ci pi->sram_end); 10508c2ecf20Sopenharmony_ci if (ret) 10518c2ecf20Sopenharmony_ci return ret; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci pi->acp_interval = 1; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 10568c2ecf20Sopenharmony_ci pi->dpm_table_start + 10578c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, ACPInterval), 10588c2ecf20Sopenharmony_ci (u8 *)&pi->acp_interval, 10598c2ecf20Sopenharmony_ci sizeof(u8), 10608c2ecf20Sopenharmony_ci pi->sram_end); 10618c2ecf20Sopenharmony_ci if (ret) 10628c2ecf20Sopenharmony_ci return ret; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 10658c2ecf20Sopenharmony_ci pi->dpm_table_start + 10668c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, AcpLevel), 10678c2ecf20Sopenharmony_ci (u8 *)&pi->acp_level, 10688c2ecf20Sopenharmony_ci sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_ACP, 10698c2ecf20Sopenharmony_ci pi->sram_end); 10708c2ecf20Sopenharmony_ci if (ret) 10718c2ecf20Sopenharmony_ci return ret; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci return ret; 10748c2ecf20Sopenharmony_ci} 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_cistatic void kv_calculate_dfs_bypass_settings(struct radeon_device *rdev) 10778c2ecf20Sopenharmony_ci{ 10788c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 10798c2ecf20Sopenharmony_ci u32 i; 10808c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 10818c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci if (table && table->count) { 10848c2ecf20Sopenharmony_ci for (i = 0; i < pi->graphics_dpm_level_count; i++) { 10858c2ecf20Sopenharmony_ci if (pi->caps_enable_dfs_bypass) { 10868c2ecf20Sopenharmony_ci if (kv_get_clock_difference(table->entries[i].clk, 40000) < 200) 10878c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 3; 10888c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].clk, 30000) < 200) 10898c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 2; 10908c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].clk, 26600) < 200) 10918c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 7; 10928c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].clk , 20000) < 200) 10938c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 6; 10948c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].clk , 10000) < 200) 10958c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 8; 10968c2ecf20Sopenharmony_ci else 10978c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 0; 10988c2ecf20Sopenharmony_ci } else { 10998c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 0; 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci } else { 11038c2ecf20Sopenharmony_ci struct sumo_sclk_voltage_mapping_table *table = 11048c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table; 11058c2ecf20Sopenharmony_ci for (i = 0; i < pi->graphics_dpm_level_count; i++) { 11068c2ecf20Sopenharmony_ci if (pi->caps_enable_dfs_bypass) { 11078c2ecf20Sopenharmony_ci if (kv_get_clock_difference(table->entries[i].sclk_frequency, 40000) < 200) 11088c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 3; 11098c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 30000) < 200) 11108c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 2; 11118c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 26600) < 200) 11128c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 7; 11138c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 20000) < 200) 11148c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 6; 11158c2ecf20Sopenharmony_ci else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 10000) < 200) 11168c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 8; 11178c2ecf20Sopenharmony_ci else 11188c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 0; 11198c2ecf20Sopenharmony_ci } else { 11208c2ecf20Sopenharmony_ci pi->graphics_level[i].ClkBypassCntl = 0; 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci } 11238c2ecf20Sopenharmony_ci } 11248c2ecf20Sopenharmony_ci} 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_cistatic int kv_enable_ulv(struct radeon_device *rdev, bool enable) 11278c2ecf20Sopenharmony_ci{ 11288c2ecf20Sopenharmony_ci return kv_notify_message_to_smu(rdev, enable ? 11298c2ecf20Sopenharmony_ci PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV); 11308c2ecf20Sopenharmony_ci} 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_cistatic void kv_reset_acp_boot_level(struct radeon_device *rdev) 11338c2ecf20Sopenharmony_ci{ 11348c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci pi->acp_boot_level = 0xff; 11378c2ecf20Sopenharmony_ci} 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_cistatic void kv_update_current_ps(struct radeon_device *rdev, 11408c2ecf20Sopenharmony_ci struct radeon_ps *rps) 11418c2ecf20Sopenharmony_ci{ 11428c2ecf20Sopenharmony_ci struct kv_ps *new_ps = kv_get_ps(rps); 11438c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci pi->current_rps = *rps; 11468c2ecf20Sopenharmony_ci pi->current_ps = *new_ps; 11478c2ecf20Sopenharmony_ci pi->current_rps.ps_priv = &pi->current_ps; 11488c2ecf20Sopenharmony_ci} 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_cistatic void kv_update_requested_ps(struct radeon_device *rdev, 11518c2ecf20Sopenharmony_ci struct radeon_ps *rps) 11528c2ecf20Sopenharmony_ci{ 11538c2ecf20Sopenharmony_ci struct kv_ps *new_ps = kv_get_ps(rps); 11548c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci pi->requested_rps = *rps; 11578c2ecf20Sopenharmony_ci pi->requested_ps = *new_ps; 11588c2ecf20Sopenharmony_ci pi->requested_rps.ps_priv = &pi->requested_ps; 11598c2ecf20Sopenharmony_ci} 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_civoid kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 11648c2ecf20Sopenharmony_ci int ret; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (pi->bapm_enable) { 11678c2ecf20Sopenharmony_ci ret = kv_smc_bapm_enable(rdev, enable); 11688c2ecf20Sopenharmony_ci if (ret) 11698c2ecf20Sopenharmony_ci DRM_ERROR("kv_smc_bapm_enable failed\n"); 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci} 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_cistatic void kv_enable_thermal_int(struct radeon_device *rdev, bool enable) 11748c2ecf20Sopenharmony_ci{ 11758c2ecf20Sopenharmony_ci u32 thermal_int; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci thermal_int = RREG32_SMC(CG_THERMAL_INT_CTRL); 11788c2ecf20Sopenharmony_ci if (enable) 11798c2ecf20Sopenharmony_ci thermal_int |= THERM_INTH_MASK | THERM_INTL_MASK; 11808c2ecf20Sopenharmony_ci else 11818c2ecf20Sopenharmony_ci thermal_int &= ~(THERM_INTH_MASK | THERM_INTL_MASK); 11828c2ecf20Sopenharmony_ci WREG32_SMC(CG_THERMAL_INT_CTRL, thermal_int); 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ciint kv_dpm_enable(struct radeon_device *rdev) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 11898c2ecf20Sopenharmony_ci int ret; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci ret = kv_process_firmware_header(rdev); 11928c2ecf20Sopenharmony_ci if (ret) { 11938c2ecf20Sopenharmony_ci DRM_ERROR("kv_process_firmware_header failed\n"); 11948c2ecf20Sopenharmony_ci return ret; 11958c2ecf20Sopenharmony_ci } 11968c2ecf20Sopenharmony_ci kv_init_fps_limits(rdev); 11978c2ecf20Sopenharmony_ci kv_init_graphics_levels(rdev); 11988c2ecf20Sopenharmony_ci ret = kv_program_bootup_state(rdev); 11998c2ecf20Sopenharmony_ci if (ret) { 12008c2ecf20Sopenharmony_ci DRM_ERROR("kv_program_bootup_state failed\n"); 12018c2ecf20Sopenharmony_ci return ret; 12028c2ecf20Sopenharmony_ci } 12038c2ecf20Sopenharmony_ci kv_calculate_dfs_bypass_settings(rdev); 12048c2ecf20Sopenharmony_ci ret = kv_upload_dpm_settings(rdev); 12058c2ecf20Sopenharmony_ci if (ret) { 12068c2ecf20Sopenharmony_ci DRM_ERROR("kv_upload_dpm_settings failed\n"); 12078c2ecf20Sopenharmony_ci return ret; 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci ret = kv_populate_uvd_table(rdev); 12108c2ecf20Sopenharmony_ci if (ret) { 12118c2ecf20Sopenharmony_ci DRM_ERROR("kv_populate_uvd_table failed\n"); 12128c2ecf20Sopenharmony_ci return ret; 12138c2ecf20Sopenharmony_ci } 12148c2ecf20Sopenharmony_ci ret = kv_populate_vce_table(rdev); 12158c2ecf20Sopenharmony_ci if (ret) { 12168c2ecf20Sopenharmony_ci DRM_ERROR("kv_populate_vce_table failed\n"); 12178c2ecf20Sopenharmony_ci return ret; 12188c2ecf20Sopenharmony_ci } 12198c2ecf20Sopenharmony_ci ret = kv_populate_samu_table(rdev); 12208c2ecf20Sopenharmony_ci if (ret) { 12218c2ecf20Sopenharmony_ci DRM_ERROR("kv_populate_samu_table failed\n"); 12228c2ecf20Sopenharmony_ci return ret; 12238c2ecf20Sopenharmony_ci } 12248c2ecf20Sopenharmony_ci ret = kv_populate_acp_table(rdev); 12258c2ecf20Sopenharmony_ci if (ret) { 12268c2ecf20Sopenharmony_ci DRM_ERROR("kv_populate_acp_table failed\n"); 12278c2ecf20Sopenharmony_ci return ret; 12288c2ecf20Sopenharmony_ci } 12298c2ecf20Sopenharmony_ci kv_program_vc(rdev); 12308c2ecf20Sopenharmony_ci#if 0 12318c2ecf20Sopenharmony_ci kv_initialize_hardware_cac_manager(rdev); 12328c2ecf20Sopenharmony_ci#endif 12338c2ecf20Sopenharmony_ci kv_start_am(rdev); 12348c2ecf20Sopenharmony_ci if (pi->enable_auto_thermal_throttling) { 12358c2ecf20Sopenharmony_ci ret = kv_enable_auto_thermal_throttling(rdev); 12368c2ecf20Sopenharmony_ci if (ret) { 12378c2ecf20Sopenharmony_ci DRM_ERROR("kv_enable_auto_thermal_throttling failed\n"); 12388c2ecf20Sopenharmony_ci return ret; 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci ret = kv_enable_dpm_voltage_scaling(rdev); 12428c2ecf20Sopenharmony_ci if (ret) { 12438c2ecf20Sopenharmony_ci DRM_ERROR("kv_enable_dpm_voltage_scaling failed\n"); 12448c2ecf20Sopenharmony_ci return ret; 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci ret = kv_set_dpm_interval(rdev); 12478c2ecf20Sopenharmony_ci if (ret) { 12488c2ecf20Sopenharmony_ci DRM_ERROR("kv_set_dpm_interval failed\n"); 12498c2ecf20Sopenharmony_ci return ret; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_ci ret = kv_set_dpm_boot_state(rdev); 12528c2ecf20Sopenharmony_ci if (ret) { 12538c2ecf20Sopenharmony_ci DRM_ERROR("kv_set_dpm_boot_state failed\n"); 12548c2ecf20Sopenharmony_ci return ret; 12558c2ecf20Sopenharmony_ci } 12568c2ecf20Sopenharmony_ci ret = kv_enable_ulv(rdev, true); 12578c2ecf20Sopenharmony_ci if (ret) { 12588c2ecf20Sopenharmony_ci DRM_ERROR("kv_enable_ulv failed\n"); 12598c2ecf20Sopenharmony_ci return ret; 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci kv_start_dpm(rdev); 12628c2ecf20Sopenharmony_ci ret = kv_enable_didt(rdev, true); 12638c2ecf20Sopenharmony_ci if (ret) { 12648c2ecf20Sopenharmony_ci DRM_ERROR("kv_enable_didt failed\n"); 12658c2ecf20Sopenharmony_ci return ret; 12668c2ecf20Sopenharmony_ci } 12678c2ecf20Sopenharmony_ci ret = kv_enable_smc_cac(rdev, true); 12688c2ecf20Sopenharmony_ci if (ret) { 12698c2ecf20Sopenharmony_ci DRM_ERROR("kv_enable_smc_cac failed\n"); 12708c2ecf20Sopenharmony_ci return ret; 12718c2ecf20Sopenharmony_ci } 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci kv_reset_acp_boot_level(rdev); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci ret = kv_smc_bapm_enable(rdev, false); 12768c2ecf20Sopenharmony_ci if (ret) { 12778c2ecf20Sopenharmony_ci DRM_ERROR("kv_smc_bapm_enable failed\n"); 12788c2ecf20Sopenharmony_ci return ret; 12798c2ecf20Sopenharmony_ci } 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci return ret; 12848c2ecf20Sopenharmony_ci} 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ciint kv_dpm_late_enable(struct radeon_device *rdev) 12878c2ecf20Sopenharmony_ci{ 12888c2ecf20Sopenharmony_ci int ret = 0; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci if (rdev->irq.installed && 12918c2ecf20Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 12928c2ecf20Sopenharmony_ci ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 12938c2ecf20Sopenharmony_ci if (ret) { 12948c2ecf20Sopenharmony_ci DRM_ERROR("kv_set_thermal_temperature_range failed\n"); 12958c2ecf20Sopenharmony_ci return ret; 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci kv_enable_thermal_int(rdev, true); 12988c2ecf20Sopenharmony_ci } 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci /* powerdown unused blocks for now */ 13018c2ecf20Sopenharmony_ci kv_dpm_powergate_acp(rdev, true); 13028c2ecf20Sopenharmony_ci kv_dpm_powergate_samu(rdev, true); 13038c2ecf20Sopenharmony_ci kv_dpm_powergate_vce(rdev, true); 13048c2ecf20Sopenharmony_ci kv_dpm_powergate_uvd(rdev, true); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci return ret; 13078c2ecf20Sopenharmony_ci} 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_civoid kv_dpm_disable(struct radeon_device *rdev) 13108c2ecf20Sopenharmony_ci{ 13118c2ecf20Sopenharmony_ci kv_smc_bapm_enable(rdev, false); 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci if (rdev->family == CHIP_MULLINS) 13148c2ecf20Sopenharmony_ci kv_enable_nb_dpm(rdev, false); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci /* powerup blocks */ 13178c2ecf20Sopenharmony_ci kv_dpm_powergate_acp(rdev, false); 13188c2ecf20Sopenharmony_ci kv_dpm_powergate_samu(rdev, false); 13198c2ecf20Sopenharmony_ci kv_dpm_powergate_vce(rdev, false); 13208c2ecf20Sopenharmony_ci kv_dpm_powergate_uvd(rdev, false); 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci kv_enable_smc_cac(rdev, false); 13238c2ecf20Sopenharmony_ci kv_enable_didt(rdev, false); 13248c2ecf20Sopenharmony_ci kv_clear_vc(rdev); 13258c2ecf20Sopenharmony_ci kv_stop_dpm(rdev); 13268c2ecf20Sopenharmony_ci kv_enable_ulv(rdev, false); 13278c2ecf20Sopenharmony_ci kv_reset_am(rdev); 13288c2ecf20Sopenharmony_ci kv_enable_thermal_int(rdev, false); 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 13318c2ecf20Sopenharmony_ci} 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci#if 0 13348c2ecf20Sopenharmony_cistatic int kv_write_smc_soft_register(struct radeon_device *rdev, 13358c2ecf20Sopenharmony_ci u16 reg_offset, u32 value) 13368c2ecf20Sopenharmony_ci{ 13378c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci return kv_copy_bytes_to_smc(rdev, pi->soft_regs_start + reg_offset, 13408c2ecf20Sopenharmony_ci (u8 *)&value, sizeof(u16), pi->sram_end); 13418c2ecf20Sopenharmony_ci} 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_cistatic int kv_read_smc_soft_register(struct radeon_device *rdev, 13448c2ecf20Sopenharmony_ci u16 reg_offset, u32 *value) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci return kv_read_smc_sram_dword(rdev, pi->soft_regs_start + reg_offset, 13498c2ecf20Sopenharmony_ci value, pi->sram_end); 13508c2ecf20Sopenharmony_ci} 13518c2ecf20Sopenharmony_ci#endif 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_cistatic void kv_init_sclk_t(struct radeon_device *rdev) 13548c2ecf20Sopenharmony_ci{ 13558c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_ci pi->low_sclk_interrupt_t = 0; 13588c2ecf20Sopenharmony_ci} 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_cistatic int kv_init_fps_limits(struct radeon_device *rdev) 13618c2ecf20Sopenharmony_ci{ 13628c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 13638c2ecf20Sopenharmony_ci int ret = 0; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci if (pi->caps_fps) { 13668c2ecf20Sopenharmony_ci u16 tmp; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci tmp = 45; 13698c2ecf20Sopenharmony_ci pi->fps_high_t = cpu_to_be16(tmp); 13708c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 13718c2ecf20Sopenharmony_ci pi->dpm_table_start + 13728c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, FpsHighT), 13738c2ecf20Sopenharmony_ci (u8 *)&pi->fps_high_t, 13748c2ecf20Sopenharmony_ci sizeof(u16), pi->sram_end); 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci tmp = 30; 13778c2ecf20Sopenharmony_ci pi->fps_low_t = cpu_to_be16(tmp); 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 13808c2ecf20Sopenharmony_ci pi->dpm_table_start + 13818c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, FpsLowT), 13828c2ecf20Sopenharmony_ci (u8 *)&pi->fps_low_t, 13838c2ecf20Sopenharmony_ci sizeof(u16), pi->sram_end); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci } 13868c2ecf20Sopenharmony_ci return ret; 13878c2ecf20Sopenharmony_ci} 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_cistatic void kv_init_powergate_state(struct radeon_device *rdev) 13908c2ecf20Sopenharmony_ci{ 13918c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci pi->uvd_power_gated = false; 13948c2ecf20Sopenharmony_ci pi->vce_power_gated = false; 13958c2ecf20Sopenharmony_ci pi->samu_power_gated = false; 13968c2ecf20Sopenharmony_ci pi->acp_power_gated = false; 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci} 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_cistatic int kv_enable_uvd_dpm(struct radeon_device *rdev, bool enable) 14018c2ecf20Sopenharmony_ci{ 14028c2ecf20Sopenharmony_ci return kv_notify_message_to_smu(rdev, enable ? 14038c2ecf20Sopenharmony_ci PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable); 14048c2ecf20Sopenharmony_ci} 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_cistatic int kv_enable_vce_dpm(struct radeon_device *rdev, bool enable) 14078c2ecf20Sopenharmony_ci{ 14088c2ecf20Sopenharmony_ci return kv_notify_message_to_smu(rdev, enable ? 14098c2ecf20Sopenharmony_ci PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable); 14108c2ecf20Sopenharmony_ci} 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_cistatic int kv_enable_samu_dpm(struct radeon_device *rdev, bool enable) 14138c2ecf20Sopenharmony_ci{ 14148c2ecf20Sopenharmony_ci return kv_notify_message_to_smu(rdev, enable ? 14158c2ecf20Sopenharmony_ci PPSMC_MSG_SAMUDPM_Enable : PPSMC_MSG_SAMUDPM_Disable); 14168c2ecf20Sopenharmony_ci} 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cistatic int kv_enable_acp_dpm(struct radeon_device *rdev, bool enable) 14198c2ecf20Sopenharmony_ci{ 14208c2ecf20Sopenharmony_ci return kv_notify_message_to_smu(rdev, enable ? 14218c2ecf20Sopenharmony_ci PPSMC_MSG_ACPDPM_Enable : PPSMC_MSG_ACPDPM_Disable); 14228c2ecf20Sopenharmony_ci} 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_cistatic int kv_update_uvd_dpm(struct radeon_device *rdev, bool gate) 14258c2ecf20Sopenharmony_ci{ 14268c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 14278c2ecf20Sopenharmony_ci struct radeon_uvd_clock_voltage_dependency_table *table = 14288c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; 14298c2ecf20Sopenharmony_ci int ret; 14308c2ecf20Sopenharmony_ci u32 mask; 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci if (!gate) { 14338c2ecf20Sopenharmony_ci if (table->count) 14348c2ecf20Sopenharmony_ci pi->uvd_boot_level = table->count - 1; 14358c2ecf20Sopenharmony_ci else 14368c2ecf20Sopenharmony_ci pi->uvd_boot_level = 0; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci if (!pi->caps_uvd_dpm || pi->caps_stable_p_state) { 14398c2ecf20Sopenharmony_ci mask = 1 << pi->uvd_boot_level; 14408c2ecf20Sopenharmony_ci } else { 14418c2ecf20Sopenharmony_ci mask = 0x1f; 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 14458c2ecf20Sopenharmony_ci pi->dpm_table_start + 14468c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, UvdBootLevel), 14478c2ecf20Sopenharmony_ci (uint8_t *)&pi->uvd_boot_level, 14488c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 14498c2ecf20Sopenharmony_ci if (ret) 14508c2ecf20Sopenharmony_ci return ret; 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci kv_send_msg_to_smc_with_parameter(rdev, 14538c2ecf20Sopenharmony_ci PPSMC_MSG_UVDDPM_SetEnabledMask, 14548c2ecf20Sopenharmony_ci mask); 14558c2ecf20Sopenharmony_ci } 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci return kv_enable_uvd_dpm(rdev, !gate); 14588c2ecf20Sopenharmony_ci} 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_cistatic u8 kv_get_vce_boot_level(struct radeon_device *rdev, u32 evclk) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci u8 i; 14638c2ecf20Sopenharmony_ci struct radeon_vce_clock_voltage_dependency_table *table = 14648c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 14678c2ecf20Sopenharmony_ci if (table->entries[i].evclk >= evclk) 14688c2ecf20Sopenharmony_ci break; 14698c2ecf20Sopenharmony_ci } 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci return i; 14728c2ecf20Sopenharmony_ci} 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_cistatic int kv_update_vce_dpm(struct radeon_device *rdev, 14758c2ecf20Sopenharmony_ci struct radeon_ps *radeon_new_state, 14768c2ecf20Sopenharmony_ci struct radeon_ps *radeon_current_state) 14778c2ecf20Sopenharmony_ci{ 14788c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 14798c2ecf20Sopenharmony_ci struct radeon_vce_clock_voltage_dependency_table *table = 14808c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 14818c2ecf20Sopenharmony_ci int ret; 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci if (radeon_new_state->evclk > 0 && radeon_current_state->evclk == 0) { 14848c2ecf20Sopenharmony_ci kv_dpm_powergate_vce(rdev, false); 14858c2ecf20Sopenharmony_ci /* turn the clocks on when encoding */ 14868c2ecf20Sopenharmony_ci cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, false); 14878c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) 14888c2ecf20Sopenharmony_ci pi->vce_boot_level = table->count - 1; 14898c2ecf20Sopenharmony_ci else 14908c2ecf20Sopenharmony_ci pi->vce_boot_level = kv_get_vce_boot_level(rdev, radeon_new_state->evclk); 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 14938c2ecf20Sopenharmony_ci pi->dpm_table_start + 14948c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, VceBootLevel), 14958c2ecf20Sopenharmony_ci (u8 *)&pi->vce_boot_level, 14968c2ecf20Sopenharmony_ci sizeof(u8), 14978c2ecf20Sopenharmony_ci pi->sram_end); 14988c2ecf20Sopenharmony_ci if (ret) 14998c2ecf20Sopenharmony_ci return ret; 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) 15028c2ecf20Sopenharmony_ci kv_send_msg_to_smc_with_parameter(rdev, 15038c2ecf20Sopenharmony_ci PPSMC_MSG_VCEDPM_SetEnabledMask, 15048c2ecf20Sopenharmony_ci (1 << pi->vce_boot_level)); 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci kv_enable_vce_dpm(rdev, true); 15078c2ecf20Sopenharmony_ci } else if (radeon_new_state->evclk == 0 && radeon_current_state->evclk > 0) { 15088c2ecf20Sopenharmony_ci kv_enable_vce_dpm(rdev, false); 15098c2ecf20Sopenharmony_ci /* turn the clocks off when not encoding */ 15108c2ecf20Sopenharmony_ci cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, true); 15118c2ecf20Sopenharmony_ci kv_dpm_powergate_vce(rdev, true); 15128c2ecf20Sopenharmony_ci } 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci return 0; 15158c2ecf20Sopenharmony_ci} 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_cistatic int kv_update_samu_dpm(struct radeon_device *rdev, bool gate) 15188c2ecf20Sopenharmony_ci{ 15198c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 15208c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 15218c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; 15228c2ecf20Sopenharmony_ci int ret; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci if (!gate) { 15258c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) 15268c2ecf20Sopenharmony_ci pi->samu_boot_level = table->count - 1; 15278c2ecf20Sopenharmony_ci else 15288c2ecf20Sopenharmony_ci pi->samu_boot_level = 0; 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 15318c2ecf20Sopenharmony_ci pi->dpm_table_start + 15328c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, SamuBootLevel), 15338c2ecf20Sopenharmony_ci (u8 *)&pi->samu_boot_level, 15348c2ecf20Sopenharmony_ci sizeof(u8), 15358c2ecf20Sopenharmony_ci pi->sram_end); 15368c2ecf20Sopenharmony_ci if (ret) 15378c2ecf20Sopenharmony_ci return ret; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) 15408c2ecf20Sopenharmony_ci kv_send_msg_to_smc_with_parameter(rdev, 15418c2ecf20Sopenharmony_ci PPSMC_MSG_SAMUDPM_SetEnabledMask, 15428c2ecf20Sopenharmony_ci (1 << pi->samu_boot_level)); 15438c2ecf20Sopenharmony_ci } 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci return kv_enable_samu_dpm(rdev, !gate); 15468c2ecf20Sopenharmony_ci} 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_cistatic u8 kv_get_acp_boot_level(struct radeon_device *rdev) 15498c2ecf20Sopenharmony_ci{ 15508c2ecf20Sopenharmony_ci u8 i; 15518c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 15528c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 15558c2ecf20Sopenharmony_ci if (table->entries[i].clk >= 0) /* XXX */ 15568c2ecf20Sopenharmony_ci break; 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci if (i >= table->count) 15608c2ecf20Sopenharmony_ci i = table->count - 1; 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci return i; 15638c2ecf20Sopenharmony_ci} 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_cistatic void kv_update_acp_boot_level(struct radeon_device *rdev) 15668c2ecf20Sopenharmony_ci{ 15678c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 15688c2ecf20Sopenharmony_ci u8 acp_boot_level; 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci if (!pi->caps_stable_p_state) { 15718c2ecf20Sopenharmony_ci acp_boot_level = kv_get_acp_boot_level(rdev); 15728c2ecf20Sopenharmony_ci if (acp_boot_level != pi->acp_boot_level) { 15738c2ecf20Sopenharmony_ci pi->acp_boot_level = acp_boot_level; 15748c2ecf20Sopenharmony_ci kv_send_msg_to_smc_with_parameter(rdev, 15758c2ecf20Sopenharmony_ci PPSMC_MSG_ACPDPM_SetEnabledMask, 15768c2ecf20Sopenharmony_ci (1 << pi->acp_boot_level)); 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci } 15798c2ecf20Sopenharmony_ci} 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_cistatic int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) 15828c2ecf20Sopenharmony_ci{ 15838c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 15848c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 15858c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; 15868c2ecf20Sopenharmony_ci int ret; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci if (!gate) { 15898c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) 15908c2ecf20Sopenharmony_ci pi->acp_boot_level = table->count - 1; 15918c2ecf20Sopenharmony_ci else 15928c2ecf20Sopenharmony_ci pi->acp_boot_level = kv_get_acp_boot_level(rdev); 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 15958c2ecf20Sopenharmony_ci pi->dpm_table_start + 15968c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, AcpBootLevel), 15978c2ecf20Sopenharmony_ci (u8 *)&pi->acp_boot_level, 15988c2ecf20Sopenharmony_ci sizeof(u8), 15998c2ecf20Sopenharmony_ci pi->sram_end); 16008c2ecf20Sopenharmony_ci if (ret) 16018c2ecf20Sopenharmony_ci return ret; 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) 16048c2ecf20Sopenharmony_ci kv_send_msg_to_smc_with_parameter(rdev, 16058c2ecf20Sopenharmony_ci PPSMC_MSG_ACPDPM_SetEnabledMask, 16068c2ecf20Sopenharmony_ci (1 << pi->acp_boot_level)); 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci return kv_enable_acp_dpm(rdev, !gate); 16108c2ecf20Sopenharmony_ci} 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_civoid kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) 16138c2ecf20Sopenharmony_ci{ 16148c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci if (pi->uvd_power_gated == gate) 16178c2ecf20Sopenharmony_ci return; 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci pi->uvd_power_gated = gate; 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci if (gate) { 16228c2ecf20Sopenharmony_ci if (pi->caps_uvd_pg) { 16238c2ecf20Sopenharmony_ci uvd_v1_0_stop(rdev); 16248c2ecf20Sopenharmony_ci cik_update_cg(rdev, RADEON_CG_BLOCK_UVD, false); 16258c2ecf20Sopenharmony_ci } 16268c2ecf20Sopenharmony_ci kv_update_uvd_dpm(rdev, gate); 16278c2ecf20Sopenharmony_ci if (pi->caps_uvd_pg) 16288c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_UVDPowerOFF); 16298c2ecf20Sopenharmony_ci } else { 16308c2ecf20Sopenharmony_ci if (pi->caps_uvd_pg) { 16318c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_UVDPowerON); 16328c2ecf20Sopenharmony_ci uvd_v4_2_resume(rdev); 16338c2ecf20Sopenharmony_ci uvd_v1_0_start(rdev); 16348c2ecf20Sopenharmony_ci cik_update_cg(rdev, RADEON_CG_BLOCK_UVD, true); 16358c2ecf20Sopenharmony_ci } 16368c2ecf20Sopenharmony_ci kv_update_uvd_dpm(rdev, gate); 16378c2ecf20Sopenharmony_ci } 16388c2ecf20Sopenharmony_ci} 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_cistatic void kv_dpm_powergate_vce(struct radeon_device *rdev, bool gate) 16418c2ecf20Sopenharmony_ci{ 16428c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci if (pi->vce_power_gated == gate) 16458c2ecf20Sopenharmony_ci return; 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci pi->vce_power_gated = gate; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci if (gate) { 16508c2ecf20Sopenharmony_ci if (pi->caps_vce_pg) { 16518c2ecf20Sopenharmony_ci /* XXX do we need a vce_v1_0_stop() ? */ 16528c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerOFF); 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci } else { 16558c2ecf20Sopenharmony_ci if (pi->caps_vce_pg) { 16568c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_VCEPowerON); 16578c2ecf20Sopenharmony_ci vce_v2_0_resume(rdev); 16588c2ecf20Sopenharmony_ci vce_v1_0_start(rdev); 16598c2ecf20Sopenharmony_ci } 16608c2ecf20Sopenharmony_ci } 16618c2ecf20Sopenharmony_ci} 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_cistatic void kv_dpm_powergate_samu(struct radeon_device *rdev, bool gate) 16648c2ecf20Sopenharmony_ci{ 16658c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci if (pi->samu_power_gated == gate) 16688c2ecf20Sopenharmony_ci return; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci pi->samu_power_gated = gate; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci if (gate) { 16738c2ecf20Sopenharmony_ci kv_update_samu_dpm(rdev, true); 16748c2ecf20Sopenharmony_ci if (pi->caps_samu_pg) 16758c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_SAMPowerOFF); 16768c2ecf20Sopenharmony_ci } else { 16778c2ecf20Sopenharmony_ci if (pi->caps_samu_pg) 16788c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_SAMPowerON); 16798c2ecf20Sopenharmony_ci kv_update_samu_dpm(rdev, false); 16808c2ecf20Sopenharmony_ci } 16818c2ecf20Sopenharmony_ci} 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_cistatic void kv_dpm_powergate_acp(struct radeon_device *rdev, bool gate) 16848c2ecf20Sopenharmony_ci{ 16858c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci if (pi->acp_power_gated == gate) 16888c2ecf20Sopenharmony_ci return; 16898c2ecf20Sopenharmony_ci 16908c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) 16918c2ecf20Sopenharmony_ci return; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci pi->acp_power_gated = gate; 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci if (gate) { 16968c2ecf20Sopenharmony_ci kv_update_acp_dpm(rdev, true); 16978c2ecf20Sopenharmony_ci if (pi->caps_acp_pg) 16988c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_ACPPowerOFF); 16998c2ecf20Sopenharmony_ci } else { 17008c2ecf20Sopenharmony_ci if (pi->caps_acp_pg) 17018c2ecf20Sopenharmony_ci kv_notify_message_to_smu(rdev, PPSMC_MSG_ACPPowerON); 17028c2ecf20Sopenharmony_ci kv_update_acp_dpm(rdev, false); 17038c2ecf20Sopenharmony_ci } 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_cistatic void kv_set_valid_clock_range(struct radeon_device *rdev, 17078c2ecf20Sopenharmony_ci struct radeon_ps *new_rps) 17088c2ecf20Sopenharmony_ci{ 17098c2ecf20Sopenharmony_ci struct kv_ps *new_ps = kv_get_ps(new_rps); 17108c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 17118c2ecf20Sopenharmony_ci u32 i; 17128c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 17138c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci if (table && table->count) { 17168c2ecf20Sopenharmony_ci for (i = 0; i < pi->graphics_dpm_level_count; i++) { 17178c2ecf20Sopenharmony_ci if ((table->entries[i].clk >= new_ps->levels[0].sclk) || 17188c2ecf20Sopenharmony_ci (i == (pi->graphics_dpm_level_count - 1))) { 17198c2ecf20Sopenharmony_ci pi->lowest_valid = i; 17208c2ecf20Sopenharmony_ci break; 17218c2ecf20Sopenharmony_ci } 17228c2ecf20Sopenharmony_ci } 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { 17258c2ecf20Sopenharmony_ci if (table->entries[i].clk <= new_ps->levels[new_ps->num_levels - 1].sclk) 17268c2ecf20Sopenharmony_ci break; 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci pi->highest_valid = i; 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci if (pi->lowest_valid > pi->highest_valid) { 17318c2ecf20Sopenharmony_ci if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) > 17328c2ecf20Sopenharmony_ci (table->entries[pi->lowest_valid].clk - new_ps->levels[new_ps->num_levels - 1].sclk)) 17338c2ecf20Sopenharmony_ci pi->highest_valid = pi->lowest_valid; 17348c2ecf20Sopenharmony_ci else 17358c2ecf20Sopenharmony_ci pi->lowest_valid = pi->highest_valid; 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci } else { 17388c2ecf20Sopenharmony_ci struct sumo_sclk_voltage_mapping_table *table = 17398c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci for (i = 0; i < (int)pi->graphics_dpm_level_count; i++) { 17428c2ecf20Sopenharmony_ci if (table->entries[i].sclk_frequency >= new_ps->levels[0].sclk || 17438c2ecf20Sopenharmony_ci i == (int)(pi->graphics_dpm_level_count - 1)) { 17448c2ecf20Sopenharmony_ci pi->lowest_valid = i; 17458c2ecf20Sopenharmony_ci break; 17468c2ecf20Sopenharmony_ci } 17478c2ecf20Sopenharmony_ci } 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { 17508c2ecf20Sopenharmony_ci if (table->entries[i].sclk_frequency <= 17518c2ecf20Sopenharmony_ci new_ps->levels[new_ps->num_levels - 1].sclk) 17528c2ecf20Sopenharmony_ci break; 17538c2ecf20Sopenharmony_ci } 17548c2ecf20Sopenharmony_ci pi->highest_valid = i; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci if (pi->lowest_valid > pi->highest_valid) { 17578c2ecf20Sopenharmony_ci if ((new_ps->levels[0].sclk - 17588c2ecf20Sopenharmony_ci table->entries[pi->highest_valid].sclk_frequency) > 17598c2ecf20Sopenharmony_ci (table->entries[pi->lowest_valid].sclk_frequency - 17608c2ecf20Sopenharmony_ci new_ps->levels[new_ps->num_levels -1].sclk)) 17618c2ecf20Sopenharmony_ci pi->highest_valid = pi->lowest_valid; 17628c2ecf20Sopenharmony_ci else 17638c2ecf20Sopenharmony_ci pi->lowest_valid = pi->highest_valid; 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci } 17668c2ecf20Sopenharmony_ci} 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_cistatic int kv_update_dfs_bypass_settings(struct radeon_device *rdev, 17698c2ecf20Sopenharmony_ci struct radeon_ps *new_rps) 17708c2ecf20Sopenharmony_ci{ 17718c2ecf20Sopenharmony_ci struct kv_ps *new_ps = kv_get_ps(new_rps); 17728c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 17738c2ecf20Sopenharmony_ci int ret = 0; 17748c2ecf20Sopenharmony_ci u8 clk_bypass_cntl; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci if (pi->caps_enable_dfs_bypass) { 17778c2ecf20Sopenharmony_ci clk_bypass_cntl = new_ps->need_dfs_bypass ? 17788c2ecf20Sopenharmony_ci pi->graphics_level[pi->graphics_boot_level].ClkBypassCntl : 0; 17798c2ecf20Sopenharmony_ci ret = kv_copy_bytes_to_smc(rdev, 17808c2ecf20Sopenharmony_ci (pi->dpm_table_start + 17818c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_DpmTable, GraphicsLevel) + 17828c2ecf20Sopenharmony_ci (pi->graphics_boot_level * sizeof(SMU7_Fusion_GraphicsLevel)) + 17838c2ecf20Sopenharmony_ci offsetof(SMU7_Fusion_GraphicsLevel, ClkBypassCntl)), 17848c2ecf20Sopenharmony_ci &clk_bypass_cntl, 17858c2ecf20Sopenharmony_ci sizeof(u8), pi->sram_end); 17868c2ecf20Sopenharmony_ci } 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci return ret; 17898c2ecf20Sopenharmony_ci} 17908c2ecf20Sopenharmony_ci 17918c2ecf20Sopenharmony_cistatic int kv_enable_nb_dpm(struct radeon_device *rdev, 17928c2ecf20Sopenharmony_ci bool enable) 17938c2ecf20Sopenharmony_ci{ 17948c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 17958c2ecf20Sopenharmony_ci int ret = 0; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci if (enable) { 17988c2ecf20Sopenharmony_ci if (pi->enable_nb_dpm && !pi->nb_dpm_enabled) { 17998c2ecf20Sopenharmony_ci ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_NBDPM_Enable); 18008c2ecf20Sopenharmony_ci if (ret == 0) 18018c2ecf20Sopenharmony_ci pi->nb_dpm_enabled = true; 18028c2ecf20Sopenharmony_ci } 18038c2ecf20Sopenharmony_ci } else { 18048c2ecf20Sopenharmony_ci if (pi->enable_nb_dpm && pi->nb_dpm_enabled) { 18058c2ecf20Sopenharmony_ci ret = kv_notify_message_to_smu(rdev, PPSMC_MSG_NBDPM_Disable); 18068c2ecf20Sopenharmony_ci if (ret == 0) 18078c2ecf20Sopenharmony_ci pi->nb_dpm_enabled = false; 18088c2ecf20Sopenharmony_ci } 18098c2ecf20Sopenharmony_ci } 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci return ret; 18128c2ecf20Sopenharmony_ci} 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_ciint kv_dpm_force_performance_level(struct radeon_device *rdev, 18158c2ecf20Sopenharmony_ci enum radeon_dpm_forced_level level) 18168c2ecf20Sopenharmony_ci{ 18178c2ecf20Sopenharmony_ci int ret; 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { 18208c2ecf20Sopenharmony_ci ret = kv_force_dpm_highest(rdev); 18218c2ecf20Sopenharmony_ci if (ret) 18228c2ecf20Sopenharmony_ci return ret; 18238c2ecf20Sopenharmony_ci } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { 18248c2ecf20Sopenharmony_ci ret = kv_force_dpm_lowest(rdev); 18258c2ecf20Sopenharmony_ci if (ret) 18268c2ecf20Sopenharmony_ci return ret; 18278c2ecf20Sopenharmony_ci } else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) { 18288c2ecf20Sopenharmony_ci ret = kv_unforce_levels(rdev); 18298c2ecf20Sopenharmony_ci if (ret) 18308c2ecf20Sopenharmony_ci return ret; 18318c2ecf20Sopenharmony_ci } 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci rdev->pm.dpm.forced_level = level; 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci return 0; 18368c2ecf20Sopenharmony_ci} 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ciint kv_dpm_pre_set_power_state(struct radeon_device *rdev) 18398c2ecf20Sopenharmony_ci{ 18408c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 18418c2ecf20Sopenharmony_ci struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps; 18428c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &requested_ps; 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci kv_update_requested_ps(rdev, new_ps); 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci kv_apply_state_adjust_rules(rdev, 18478c2ecf20Sopenharmony_ci &pi->requested_rps, 18488c2ecf20Sopenharmony_ci &pi->current_rps); 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci return 0; 18518c2ecf20Sopenharmony_ci} 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ciint kv_dpm_set_power_state(struct radeon_device *rdev) 18548c2ecf20Sopenharmony_ci{ 18558c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 18568c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 18578c2ecf20Sopenharmony_ci struct radeon_ps *old_ps = &pi->current_rps; 18588c2ecf20Sopenharmony_ci int ret; 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci if (pi->bapm_enable) { 18618c2ecf20Sopenharmony_ci ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power); 18628c2ecf20Sopenharmony_ci if (ret) { 18638c2ecf20Sopenharmony_ci DRM_ERROR("kv_smc_bapm_enable failed\n"); 18648c2ecf20Sopenharmony_ci return ret; 18658c2ecf20Sopenharmony_ci } 18668c2ecf20Sopenharmony_ci } 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { 18698c2ecf20Sopenharmony_ci if (pi->enable_dpm) { 18708c2ecf20Sopenharmony_ci kv_set_valid_clock_range(rdev, new_ps); 18718c2ecf20Sopenharmony_ci kv_update_dfs_bypass_settings(rdev, new_ps); 18728c2ecf20Sopenharmony_ci ret = kv_calculate_ds_divider(rdev); 18738c2ecf20Sopenharmony_ci if (ret) { 18748c2ecf20Sopenharmony_ci DRM_ERROR("kv_calculate_ds_divider failed\n"); 18758c2ecf20Sopenharmony_ci return ret; 18768c2ecf20Sopenharmony_ci } 18778c2ecf20Sopenharmony_ci kv_calculate_nbps_level_settings(rdev); 18788c2ecf20Sopenharmony_ci kv_calculate_dpm_settings(rdev); 18798c2ecf20Sopenharmony_ci kv_force_lowest_valid(rdev); 18808c2ecf20Sopenharmony_ci kv_enable_new_levels(rdev); 18818c2ecf20Sopenharmony_ci kv_upload_dpm_settings(rdev); 18828c2ecf20Sopenharmony_ci kv_program_nbps_index_settings(rdev, new_ps); 18838c2ecf20Sopenharmony_ci kv_unforce_levels(rdev); 18848c2ecf20Sopenharmony_ci kv_set_enabled_levels(rdev); 18858c2ecf20Sopenharmony_ci kv_force_lowest_valid(rdev); 18868c2ecf20Sopenharmony_ci kv_unforce_levels(rdev); 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_ci ret = kv_update_vce_dpm(rdev, new_ps, old_ps); 18898c2ecf20Sopenharmony_ci if (ret) { 18908c2ecf20Sopenharmony_ci DRM_ERROR("kv_update_vce_dpm failed\n"); 18918c2ecf20Sopenharmony_ci return ret; 18928c2ecf20Sopenharmony_ci } 18938c2ecf20Sopenharmony_ci kv_update_sclk_t(rdev); 18948c2ecf20Sopenharmony_ci if (rdev->family == CHIP_MULLINS) 18958c2ecf20Sopenharmony_ci kv_enable_nb_dpm(rdev, true); 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci } else { 18988c2ecf20Sopenharmony_ci if (pi->enable_dpm) { 18998c2ecf20Sopenharmony_ci kv_set_valid_clock_range(rdev, new_ps); 19008c2ecf20Sopenharmony_ci kv_update_dfs_bypass_settings(rdev, new_ps); 19018c2ecf20Sopenharmony_ci ret = kv_calculate_ds_divider(rdev); 19028c2ecf20Sopenharmony_ci if (ret) { 19038c2ecf20Sopenharmony_ci DRM_ERROR("kv_calculate_ds_divider failed\n"); 19048c2ecf20Sopenharmony_ci return ret; 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci kv_calculate_nbps_level_settings(rdev); 19078c2ecf20Sopenharmony_ci kv_calculate_dpm_settings(rdev); 19088c2ecf20Sopenharmony_ci kv_freeze_sclk_dpm(rdev, true); 19098c2ecf20Sopenharmony_ci kv_upload_dpm_settings(rdev); 19108c2ecf20Sopenharmony_ci kv_program_nbps_index_settings(rdev, new_ps); 19118c2ecf20Sopenharmony_ci kv_freeze_sclk_dpm(rdev, false); 19128c2ecf20Sopenharmony_ci kv_set_enabled_levels(rdev); 19138c2ecf20Sopenharmony_ci ret = kv_update_vce_dpm(rdev, new_ps, old_ps); 19148c2ecf20Sopenharmony_ci if (ret) { 19158c2ecf20Sopenharmony_ci DRM_ERROR("kv_update_vce_dpm failed\n"); 19168c2ecf20Sopenharmony_ci return ret; 19178c2ecf20Sopenharmony_ci } 19188c2ecf20Sopenharmony_ci kv_update_acp_boot_level(rdev); 19198c2ecf20Sopenharmony_ci kv_update_sclk_t(rdev); 19208c2ecf20Sopenharmony_ci kv_enable_nb_dpm(rdev, true); 19218c2ecf20Sopenharmony_ci } 19228c2ecf20Sopenharmony_ci } 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci return 0; 19258c2ecf20Sopenharmony_ci} 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_civoid kv_dpm_post_set_power_state(struct radeon_device *rdev) 19288c2ecf20Sopenharmony_ci{ 19298c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 19308c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci kv_update_current_ps(rdev, new_ps); 19338c2ecf20Sopenharmony_ci} 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_civoid kv_dpm_setup_asic(struct radeon_device *rdev) 19368c2ecf20Sopenharmony_ci{ 19378c2ecf20Sopenharmony_ci sumo_take_smu_control(rdev, true); 19388c2ecf20Sopenharmony_ci kv_init_powergate_state(rdev); 19398c2ecf20Sopenharmony_ci kv_init_sclk_t(rdev); 19408c2ecf20Sopenharmony_ci} 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci#if 0 19438c2ecf20Sopenharmony_civoid kv_dpm_reset_asic(struct radeon_device *rdev) 19448c2ecf20Sopenharmony_ci{ 19458c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { 19488c2ecf20Sopenharmony_ci kv_force_lowest_valid(rdev); 19498c2ecf20Sopenharmony_ci kv_init_graphics_levels(rdev); 19508c2ecf20Sopenharmony_ci kv_program_bootup_state(rdev); 19518c2ecf20Sopenharmony_ci kv_upload_dpm_settings(rdev); 19528c2ecf20Sopenharmony_ci kv_force_lowest_valid(rdev); 19538c2ecf20Sopenharmony_ci kv_unforce_levels(rdev); 19548c2ecf20Sopenharmony_ci } else { 19558c2ecf20Sopenharmony_ci kv_init_graphics_levels(rdev); 19568c2ecf20Sopenharmony_ci kv_program_bootup_state(rdev); 19578c2ecf20Sopenharmony_ci kv_freeze_sclk_dpm(rdev, true); 19588c2ecf20Sopenharmony_ci kv_upload_dpm_settings(rdev); 19598c2ecf20Sopenharmony_ci kv_freeze_sclk_dpm(rdev, false); 19608c2ecf20Sopenharmony_ci kv_set_enabled_level(rdev, pi->graphics_boot_level); 19618c2ecf20Sopenharmony_ci } 19628c2ecf20Sopenharmony_ci} 19638c2ecf20Sopenharmony_ci#endif 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci//XXX use sumo_dpm_display_configuration_changed 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_cistatic void kv_construct_max_power_limits_table(struct radeon_device *rdev, 19688c2ecf20Sopenharmony_ci struct radeon_clock_and_voltage_limits *table) 19698c2ecf20Sopenharmony_ci{ 19708c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci if (pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries > 0) { 19738c2ecf20Sopenharmony_ci int idx = pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1; 19748c2ecf20Sopenharmony_ci table->sclk = 19758c2ecf20Sopenharmony_ci pi->sys_info.sclk_voltage_mapping_table.entries[idx].sclk_frequency; 19768c2ecf20Sopenharmony_ci table->vddc = 19778c2ecf20Sopenharmony_ci kv_convert_2bit_index_to_voltage(rdev, 19788c2ecf20Sopenharmony_ci pi->sys_info.sclk_voltage_mapping_table.entries[idx].vid_2bit); 19798c2ecf20Sopenharmony_ci } 19808c2ecf20Sopenharmony_ci 19818c2ecf20Sopenharmony_ci table->mclk = pi->sys_info.nbp_memory_clock[0]; 19828c2ecf20Sopenharmony_ci} 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_cistatic void kv_patch_voltage_values(struct radeon_device *rdev) 19858c2ecf20Sopenharmony_ci{ 19868c2ecf20Sopenharmony_ci int i; 19878c2ecf20Sopenharmony_ci struct radeon_uvd_clock_voltage_dependency_table *uvd_table = 19888c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; 19898c2ecf20Sopenharmony_ci struct radeon_vce_clock_voltage_dependency_table *vce_table = 19908c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 19918c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *samu_table = 19928c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; 19938c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *acp_table = 19948c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci if (uvd_table->count) { 19978c2ecf20Sopenharmony_ci for (i = 0; i < uvd_table->count; i++) 19988c2ecf20Sopenharmony_ci uvd_table->entries[i].v = 19998c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, 20008c2ecf20Sopenharmony_ci uvd_table->entries[i].v); 20018c2ecf20Sopenharmony_ci } 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci if (vce_table->count) { 20048c2ecf20Sopenharmony_ci for (i = 0; i < vce_table->count; i++) 20058c2ecf20Sopenharmony_ci vce_table->entries[i].v = 20068c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, 20078c2ecf20Sopenharmony_ci vce_table->entries[i].v); 20088c2ecf20Sopenharmony_ci } 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci if (samu_table->count) { 20118c2ecf20Sopenharmony_ci for (i = 0; i < samu_table->count; i++) 20128c2ecf20Sopenharmony_ci samu_table->entries[i].v = 20138c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, 20148c2ecf20Sopenharmony_ci samu_table->entries[i].v); 20158c2ecf20Sopenharmony_ci } 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci if (acp_table->count) { 20188c2ecf20Sopenharmony_ci for (i = 0; i < acp_table->count; i++) 20198c2ecf20Sopenharmony_ci acp_table->entries[i].v = 20208c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, 20218c2ecf20Sopenharmony_ci acp_table->entries[i].v); 20228c2ecf20Sopenharmony_ci } 20238c2ecf20Sopenharmony_ci 20248c2ecf20Sopenharmony_ci} 20258c2ecf20Sopenharmony_ci 20268c2ecf20Sopenharmony_cistatic void kv_construct_boot_state(struct radeon_device *rdev) 20278c2ecf20Sopenharmony_ci{ 20288c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci pi->boot_pl.sclk = pi->sys_info.bootup_sclk; 20318c2ecf20Sopenharmony_ci pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; 20328c2ecf20Sopenharmony_ci pi->boot_pl.ds_divider_index = 0; 20338c2ecf20Sopenharmony_ci pi->boot_pl.ss_divider_index = 0; 20348c2ecf20Sopenharmony_ci pi->boot_pl.allow_gnb_slow = 1; 20358c2ecf20Sopenharmony_ci pi->boot_pl.force_nbp_state = 0; 20368c2ecf20Sopenharmony_ci pi->boot_pl.display_wm = 0; 20378c2ecf20Sopenharmony_ci pi->boot_pl.vce_wm = 0; 20388c2ecf20Sopenharmony_ci} 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_cistatic int kv_force_dpm_highest(struct radeon_device *rdev) 20418c2ecf20Sopenharmony_ci{ 20428c2ecf20Sopenharmony_ci int ret; 20438c2ecf20Sopenharmony_ci u32 enable_mask, i; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci ret = kv_dpm_get_enable_mask(rdev, &enable_mask); 20468c2ecf20Sopenharmony_ci if (ret) 20478c2ecf20Sopenharmony_ci return ret; 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_ci for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i > 0; i--) { 20508c2ecf20Sopenharmony_ci if (enable_mask & (1 << i)) 20518c2ecf20Sopenharmony_ci break; 20528c2ecf20Sopenharmony_ci } 20538c2ecf20Sopenharmony_ci 20548c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) 20558c2ecf20Sopenharmony_ci return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); 20568c2ecf20Sopenharmony_ci else 20578c2ecf20Sopenharmony_ci return kv_set_enabled_level(rdev, i); 20588c2ecf20Sopenharmony_ci} 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_cistatic int kv_force_dpm_lowest(struct radeon_device *rdev) 20618c2ecf20Sopenharmony_ci{ 20628c2ecf20Sopenharmony_ci int ret; 20638c2ecf20Sopenharmony_ci u32 enable_mask, i; 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci ret = kv_dpm_get_enable_mask(rdev, &enable_mask); 20668c2ecf20Sopenharmony_ci if (ret) 20678c2ecf20Sopenharmony_ci return ret; 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_ci for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) { 20708c2ecf20Sopenharmony_ci if (enable_mask & (1 << i)) 20718c2ecf20Sopenharmony_ci break; 20728c2ecf20Sopenharmony_ci } 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) 20758c2ecf20Sopenharmony_ci return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i); 20768c2ecf20Sopenharmony_ci else 20778c2ecf20Sopenharmony_ci return kv_set_enabled_level(rdev, i); 20788c2ecf20Sopenharmony_ci} 20798c2ecf20Sopenharmony_ci 20808c2ecf20Sopenharmony_cistatic u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev, 20818c2ecf20Sopenharmony_ci u32 sclk, u32 min_sclk_in_sr) 20828c2ecf20Sopenharmony_ci{ 20838c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 20848c2ecf20Sopenharmony_ci u32 i; 20858c2ecf20Sopenharmony_ci u32 temp; 20868c2ecf20Sopenharmony_ci u32 min = (min_sclk_in_sr > KV_MINIMUM_ENGINE_CLOCK) ? 20878c2ecf20Sopenharmony_ci min_sclk_in_sr : KV_MINIMUM_ENGINE_CLOCK; 20888c2ecf20Sopenharmony_ci 20898c2ecf20Sopenharmony_ci if (sclk < min) 20908c2ecf20Sopenharmony_ci return 0; 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci if (!pi->caps_sclk_ds) 20938c2ecf20Sopenharmony_ci return 0; 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_ci for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) { 20968c2ecf20Sopenharmony_ci temp = sclk / sumo_get_sleep_divider_from_id(i); 20978c2ecf20Sopenharmony_ci if (temp >= min) 20988c2ecf20Sopenharmony_ci break; 20998c2ecf20Sopenharmony_ci } 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci return (u8)i; 21028c2ecf20Sopenharmony_ci} 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_cistatic int kv_get_high_voltage_limit(struct radeon_device *rdev, int *limit) 21058c2ecf20Sopenharmony_ci{ 21068c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 21078c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 21088c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 21098c2ecf20Sopenharmony_ci int i; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci if (table && table->count) { 21128c2ecf20Sopenharmony_ci for (i = table->count - 1; i >= 0; i--) { 21138c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 21148c2ecf20Sopenharmony_ci (kv_convert_8bit_index_to_voltage(rdev, table->entries[i].v) <= 21158c2ecf20Sopenharmony_ci pi->high_voltage_t)) { 21168c2ecf20Sopenharmony_ci *limit = i; 21178c2ecf20Sopenharmony_ci return 0; 21188c2ecf20Sopenharmony_ci } 21198c2ecf20Sopenharmony_ci } 21208c2ecf20Sopenharmony_ci } else { 21218c2ecf20Sopenharmony_ci struct sumo_sclk_voltage_mapping_table *table = 21228c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci for (i = table->num_max_dpm_entries - 1; i >= 0; i--) { 21258c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 21268c2ecf20Sopenharmony_ci (kv_convert_2bit_index_to_voltage(rdev, table->entries[i].vid_2bit) <= 21278c2ecf20Sopenharmony_ci pi->high_voltage_t)) { 21288c2ecf20Sopenharmony_ci *limit = i; 21298c2ecf20Sopenharmony_ci return 0; 21308c2ecf20Sopenharmony_ci } 21318c2ecf20Sopenharmony_ci } 21328c2ecf20Sopenharmony_ci } 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_ci *limit = 0; 21358c2ecf20Sopenharmony_ci return 0; 21368c2ecf20Sopenharmony_ci} 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_cistatic void kv_apply_state_adjust_rules(struct radeon_device *rdev, 21398c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 21408c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 21418c2ecf20Sopenharmony_ci{ 21428c2ecf20Sopenharmony_ci struct kv_ps *ps = kv_get_ps(new_rps); 21438c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 21448c2ecf20Sopenharmony_ci u32 min_sclk = 10000; /* ??? */ 21458c2ecf20Sopenharmony_ci u32 sclk, mclk = 0; 21468c2ecf20Sopenharmony_ci int i, limit; 21478c2ecf20Sopenharmony_ci bool force_high; 21488c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 21498c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 21508c2ecf20Sopenharmony_ci u32 stable_p_state_sclk = 0; 21518c2ecf20Sopenharmony_ci struct radeon_clock_and_voltage_limits *max_limits = 21528c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_ci if (new_rps->vce_active) { 21558c2ecf20Sopenharmony_ci new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; 21568c2ecf20Sopenharmony_ci new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk; 21578c2ecf20Sopenharmony_ci } else { 21588c2ecf20Sopenharmony_ci new_rps->evclk = 0; 21598c2ecf20Sopenharmony_ci new_rps->ecclk = 0; 21608c2ecf20Sopenharmony_ci } 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci mclk = max_limits->mclk; 21638c2ecf20Sopenharmony_ci sclk = min_sclk; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) { 21668c2ecf20Sopenharmony_ci stable_p_state_sclk = (max_limits->sclk * 75) / 100; 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci for (i = table->count - 1; i >= 0; i--) { 21698c2ecf20Sopenharmony_ci if (stable_p_state_sclk >= table->entries[i].clk) { 21708c2ecf20Sopenharmony_ci stable_p_state_sclk = table->entries[i].clk; 21718c2ecf20Sopenharmony_ci break; 21728c2ecf20Sopenharmony_ci } 21738c2ecf20Sopenharmony_ci } 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_ci if (i > 0) 21768c2ecf20Sopenharmony_ci stable_p_state_sclk = table->entries[0].clk; 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci sclk = stable_p_state_sclk; 21798c2ecf20Sopenharmony_ci } 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci if (new_rps->vce_active) { 21828c2ecf20Sopenharmony_ci if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk) 21838c2ecf20Sopenharmony_ci sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci ps->need_dfs_bypass = true; 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 21898c2ecf20Sopenharmony_ci if (ps->levels[i].sclk < sclk) 21908c2ecf20Sopenharmony_ci ps->levels[i].sclk = sclk; 21918c2ecf20Sopenharmony_ci } 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci if (table && table->count) { 21948c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 21958c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 21968c2ecf20Sopenharmony_ci (pi->high_voltage_t < 21978c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, ps->levels[i].vddc_index))) { 21988c2ecf20Sopenharmony_ci kv_get_high_voltage_limit(rdev, &limit); 21998c2ecf20Sopenharmony_ci ps->levels[i].sclk = table->entries[limit].clk; 22008c2ecf20Sopenharmony_ci } 22018c2ecf20Sopenharmony_ci } 22028c2ecf20Sopenharmony_ci } else { 22038c2ecf20Sopenharmony_ci struct sumo_sclk_voltage_mapping_table *table = 22048c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table; 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 22078c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 22088c2ecf20Sopenharmony_ci (pi->high_voltage_t < 22098c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, ps->levels[i].vddc_index))) { 22108c2ecf20Sopenharmony_ci kv_get_high_voltage_limit(rdev, &limit); 22118c2ecf20Sopenharmony_ci ps->levels[i].sclk = table->entries[limit].sclk_frequency; 22128c2ecf20Sopenharmony_ci } 22138c2ecf20Sopenharmony_ci } 22148c2ecf20Sopenharmony_ci } 22158c2ecf20Sopenharmony_ci 22168c2ecf20Sopenharmony_ci if (pi->caps_stable_p_state) { 22178c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 22188c2ecf20Sopenharmony_ci ps->levels[i].sclk = stable_p_state_sclk; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci } 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_ci pi->video_start = new_rps->dclk || new_rps->vclk || 22238c2ecf20Sopenharmony_ci new_rps->evclk || new_rps->ecclk; 22248c2ecf20Sopenharmony_ci 22258c2ecf20Sopenharmony_ci if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 22268c2ecf20Sopenharmony_ci ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) 22278c2ecf20Sopenharmony_ci pi->battery_state = true; 22288c2ecf20Sopenharmony_ci else 22298c2ecf20Sopenharmony_ci pi->battery_state = false; 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { 22328c2ecf20Sopenharmony_ci ps->dpm0_pg_nb_ps_lo = 0x1; 22338c2ecf20Sopenharmony_ci ps->dpm0_pg_nb_ps_hi = 0x0; 22348c2ecf20Sopenharmony_ci ps->dpmx_nb_ps_lo = 0x1; 22358c2ecf20Sopenharmony_ci ps->dpmx_nb_ps_hi = 0x0; 22368c2ecf20Sopenharmony_ci } else { 22378c2ecf20Sopenharmony_ci ps->dpm0_pg_nb_ps_lo = 0x3; 22388c2ecf20Sopenharmony_ci ps->dpm0_pg_nb_ps_hi = 0x0; 22398c2ecf20Sopenharmony_ci ps->dpmx_nb_ps_lo = 0x3; 22408c2ecf20Sopenharmony_ci ps->dpmx_nb_ps_hi = 0x0; 22418c2ecf20Sopenharmony_ci 22428c2ecf20Sopenharmony_ci if (pi->sys_info.nb_dpm_enable) { 22438c2ecf20Sopenharmony_ci force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) || 22448c2ecf20Sopenharmony_ci pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) || 22458c2ecf20Sopenharmony_ci pi->disable_nb_ps3_in_battery; 22468c2ecf20Sopenharmony_ci ps->dpm0_pg_nb_ps_lo = force_high ? 0x2 : 0x3; 22478c2ecf20Sopenharmony_ci ps->dpm0_pg_nb_ps_hi = 0x2; 22488c2ecf20Sopenharmony_ci ps->dpmx_nb_ps_lo = force_high ? 0x2 : 0x3; 22498c2ecf20Sopenharmony_ci ps->dpmx_nb_ps_hi = 0x2; 22508c2ecf20Sopenharmony_ci } 22518c2ecf20Sopenharmony_ci } 22528c2ecf20Sopenharmony_ci} 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_cistatic void kv_dpm_power_level_enabled_for_throttle(struct radeon_device *rdev, 22558c2ecf20Sopenharmony_ci u32 index, bool enable) 22568c2ecf20Sopenharmony_ci{ 22578c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci pi->graphics_level[index].EnabledForThrottle = enable ? 1 : 0; 22608c2ecf20Sopenharmony_ci} 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_cistatic int kv_calculate_ds_divider(struct radeon_device *rdev) 22638c2ecf20Sopenharmony_ci{ 22648c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 22658c2ecf20Sopenharmony_ci u32 sclk_in_sr = 10000; /* ??? */ 22668c2ecf20Sopenharmony_ci u32 i; 22678c2ecf20Sopenharmony_ci 22688c2ecf20Sopenharmony_ci if (pi->lowest_valid > pi->highest_valid) 22698c2ecf20Sopenharmony_ci return -EINVAL; 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { 22728c2ecf20Sopenharmony_ci pi->graphics_level[i].DeepSleepDivId = 22738c2ecf20Sopenharmony_ci kv_get_sleep_divider_id_from_clock(rdev, 22748c2ecf20Sopenharmony_ci be32_to_cpu(pi->graphics_level[i].SclkFrequency), 22758c2ecf20Sopenharmony_ci sclk_in_sr); 22768c2ecf20Sopenharmony_ci } 22778c2ecf20Sopenharmony_ci return 0; 22788c2ecf20Sopenharmony_ci} 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_cistatic int kv_calculate_nbps_level_settings(struct radeon_device *rdev) 22818c2ecf20Sopenharmony_ci{ 22828c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 22838c2ecf20Sopenharmony_ci u32 i; 22848c2ecf20Sopenharmony_ci bool force_high; 22858c2ecf20Sopenharmony_ci struct radeon_clock_and_voltage_limits *max_limits = 22868c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; 22878c2ecf20Sopenharmony_ci u32 mclk = max_limits->mclk; 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci if (pi->lowest_valid > pi->highest_valid) 22908c2ecf20Sopenharmony_ci return -EINVAL; 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) { 22938c2ecf20Sopenharmony_ci for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { 22948c2ecf20Sopenharmony_ci pi->graphics_level[i].GnbSlow = 1; 22958c2ecf20Sopenharmony_ci pi->graphics_level[i].ForceNbPs1 = 0; 22968c2ecf20Sopenharmony_ci pi->graphics_level[i].UpH = 0; 22978c2ecf20Sopenharmony_ci } 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci if (!pi->sys_info.nb_dpm_enable) 23008c2ecf20Sopenharmony_ci return 0; 23018c2ecf20Sopenharmony_ci 23028c2ecf20Sopenharmony_ci force_high = ((mclk >= pi->sys_info.nbp_memory_clock[3]) || 23038c2ecf20Sopenharmony_ci (rdev->pm.dpm.new_active_crtc_count >= 3) || pi->video_start); 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci if (force_high) { 23068c2ecf20Sopenharmony_ci for (i = pi->lowest_valid; i <= pi->highest_valid; i++) 23078c2ecf20Sopenharmony_ci pi->graphics_level[i].GnbSlow = 0; 23088c2ecf20Sopenharmony_ci } else { 23098c2ecf20Sopenharmony_ci if (pi->battery_state) 23108c2ecf20Sopenharmony_ci pi->graphics_level[0].ForceNbPs1 = 1; 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci pi->graphics_level[1].GnbSlow = 0; 23138c2ecf20Sopenharmony_ci pi->graphics_level[2].GnbSlow = 0; 23148c2ecf20Sopenharmony_ci pi->graphics_level[3].GnbSlow = 0; 23158c2ecf20Sopenharmony_ci pi->graphics_level[4].GnbSlow = 0; 23168c2ecf20Sopenharmony_ci } 23178c2ecf20Sopenharmony_ci } else { 23188c2ecf20Sopenharmony_ci for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { 23198c2ecf20Sopenharmony_ci pi->graphics_level[i].GnbSlow = 1; 23208c2ecf20Sopenharmony_ci pi->graphics_level[i].ForceNbPs1 = 0; 23218c2ecf20Sopenharmony_ci pi->graphics_level[i].UpH = 0; 23228c2ecf20Sopenharmony_ci } 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_ci if (pi->sys_info.nb_dpm_enable && pi->battery_state) { 23258c2ecf20Sopenharmony_ci pi->graphics_level[pi->lowest_valid].UpH = 0x28; 23268c2ecf20Sopenharmony_ci pi->graphics_level[pi->lowest_valid].GnbSlow = 0; 23278c2ecf20Sopenharmony_ci if (pi->lowest_valid != pi->highest_valid) 23288c2ecf20Sopenharmony_ci pi->graphics_level[pi->lowest_valid].ForceNbPs1 = 1; 23298c2ecf20Sopenharmony_ci } 23308c2ecf20Sopenharmony_ci } 23318c2ecf20Sopenharmony_ci return 0; 23328c2ecf20Sopenharmony_ci} 23338c2ecf20Sopenharmony_ci 23348c2ecf20Sopenharmony_cistatic int kv_calculate_dpm_settings(struct radeon_device *rdev) 23358c2ecf20Sopenharmony_ci{ 23368c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 23378c2ecf20Sopenharmony_ci u32 i; 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci if (pi->lowest_valid > pi->highest_valid) 23408c2ecf20Sopenharmony_ci return -EINVAL; 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci for (i = pi->lowest_valid; i <= pi->highest_valid; i++) 23438c2ecf20Sopenharmony_ci pi->graphics_level[i].DisplayWatermark = (i == pi->highest_valid) ? 1 : 0; 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_ci return 0; 23468c2ecf20Sopenharmony_ci} 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_cistatic void kv_init_graphics_levels(struct radeon_device *rdev) 23498c2ecf20Sopenharmony_ci{ 23508c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 23518c2ecf20Sopenharmony_ci u32 i; 23528c2ecf20Sopenharmony_ci struct radeon_clock_voltage_dependency_table *table = 23538c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci if (table && table->count) { 23568c2ecf20Sopenharmony_ci u32 vid_2bit; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci pi->graphics_dpm_level_count = 0; 23598c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 23608c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 23618c2ecf20Sopenharmony_ci (pi->high_voltage_t < 23628c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, table->entries[i].v))) 23638c2ecf20Sopenharmony_ci break; 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci kv_set_divider_value(rdev, i, table->entries[i].clk); 23668c2ecf20Sopenharmony_ci vid_2bit = kv_convert_vid7_to_vid2(rdev, 23678c2ecf20Sopenharmony_ci &pi->sys_info.vid_mapping_table, 23688c2ecf20Sopenharmony_ci table->entries[i].v); 23698c2ecf20Sopenharmony_ci kv_set_vid(rdev, i, vid_2bit); 23708c2ecf20Sopenharmony_ci kv_set_at(rdev, i, pi->at[i]); 23718c2ecf20Sopenharmony_ci kv_dpm_power_level_enabled_for_throttle(rdev, i, true); 23728c2ecf20Sopenharmony_ci pi->graphics_dpm_level_count++; 23738c2ecf20Sopenharmony_ci } 23748c2ecf20Sopenharmony_ci } else { 23758c2ecf20Sopenharmony_ci struct sumo_sclk_voltage_mapping_table *table = 23768c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table; 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci pi->graphics_dpm_level_count = 0; 23798c2ecf20Sopenharmony_ci for (i = 0; i < table->num_max_dpm_entries; i++) { 23808c2ecf20Sopenharmony_ci if (pi->high_voltage_t && 23818c2ecf20Sopenharmony_ci pi->high_voltage_t < 23828c2ecf20Sopenharmony_ci kv_convert_2bit_index_to_voltage(rdev, table->entries[i].vid_2bit)) 23838c2ecf20Sopenharmony_ci break; 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci kv_set_divider_value(rdev, i, table->entries[i].sclk_frequency); 23868c2ecf20Sopenharmony_ci kv_set_vid(rdev, i, table->entries[i].vid_2bit); 23878c2ecf20Sopenharmony_ci kv_set_at(rdev, i, pi->at[i]); 23888c2ecf20Sopenharmony_ci kv_dpm_power_level_enabled_for_throttle(rdev, i, true); 23898c2ecf20Sopenharmony_ci pi->graphics_dpm_level_count++; 23908c2ecf20Sopenharmony_ci } 23918c2ecf20Sopenharmony_ci } 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_ci for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) 23948c2ecf20Sopenharmony_ci kv_dpm_power_level_enable(rdev, i, false); 23958c2ecf20Sopenharmony_ci} 23968c2ecf20Sopenharmony_ci 23978c2ecf20Sopenharmony_cistatic void kv_enable_new_levels(struct radeon_device *rdev) 23988c2ecf20Sopenharmony_ci{ 23998c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 24008c2ecf20Sopenharmony_ci u32 i; 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) { 24038c2ecf20Sopenharmony_ci if (i >= pi->lowest_valid && i <= pi->highest_valid) 24048c2ecf20Sopenharmony_ci kv_dpm_power_level_enable(rdev, i, true); 24058c2ecf20Sopenharmony_ci } 24068c2ecf20Sopenharmony_ci} 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_cistatic int kv_set_enabled_level(struct radeon_device *rdev, u32 level) 24098c2ecf20Sopenharmony_ci{ 24108c2ecf20Sopenharmony_ci u32 new_mask = (1 << level); 24118c2ecf20Sopenharmony_ci 24128c2ecf20Sopenharmony_ci return kv_send_msg_to_smc_with_parameter(rdev, 24138c2ecf20Sopenharmony_ci PPSMC_MSG_SCLKDPM_SetEnabledMask, 24148c2ecf20Sopenharmony_ci new_mask); 24158c2ecf20Sopenharmony_ci} 24168c2ecf20Sopenharmony_ci 24178c2ecf20Sopenharmony_cistatic int kv_set_enabled_levels(struct radeon_device *rdev) 24188c2ecf20Sopenharmony_ci{ 24198c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 24208c2ecf20Sopenharmony_ci u32 i, new_mask = 0; 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_ci for (i = pi->lowest_valid; i <= pi->highest_valid; i++) 24238c2ecf20Sopenharmony_ci new_mask |= (1 << i); 24248c2ecf20Sopenharmony_ci 24258c2ecf20Sopenharmony_ci return kv_send_msg_to_smc_with_parameter(rdev, 24268c2ecf20Sopenharmony_ci PPSMC_MSG_SCLKDPM_SetEnabledMask, 24278c2ecf20Sopenharmony_ci new_mask); 24288c2ecf20Sopenharmony_ci} 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_cistatic void kv_program_nbps_index_settings(struct radeon_device *rdev, 24318c2ecf20Sopenharmony_ci struct radeon_ps *new_rps) 24328c2ecf20Sopenharmony_ci{ 24338c2ecf20Sopenharmony_ci struct kv_ps *new_ps = kv_get_ps(new_rps); 24348c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 24358c2ecf20Sopenharmony_ci u32 nbdpmconfig1; 24368c2ecf20Sopenharmony_ci 24378c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) 24388c2ecf20Sopenharmony_ci return; 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci if (pi->sys_info.nb_dpm_enable) { 24418c2ecf20Sopenharmony_ci nbdpmconfig1 = RREG32_SMC(NB_DPM_CONFIG_1); 24428c2ecf20Sopenharmony_ci nbdpmconfig1 &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | 24438c2ecf20Sopenharmony_ci DpmXNbPsLo_MASK | DpmXNbPsHi_MASK); 24448c2ecf20Sopenharmony_ci nbdpmconfig1 |= (Dpm0PgNbPsLo(new_ps->dpm0_pg_nb_ps_lo) | 24458c2ecf20Sopenharmony_ci Dpm0PgNbPsHi(new_ps->dpm0_pg_nb_ps_hi) | 24468c2ecf20Sopenharmony_ci DpmXNbPsLo(new_ps->dpmx_nb_ps_lo) | 24478c2ecf20Sopenharmony_ci DpmXNbPsHi(new_ps->dpmx_nb_ps_hi)); 24488c2ecf20Sopenharmony_ci WREG32_SMC(NB_DPM_CONFIG_1, nbdpmconfig1); 24498c2ecf20Sopenharmony_ci } 24508c2ecf20Sopenharmony_ci} 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_cistatic int kv_set_thermal_temperature_range(struct radeon_device *rdev, 24538c2ecf20Sopenharmony_ci int min_temp, int max_temp) 24548c2ecf20Sopenharmony_ci{ 24558c2ecf20Sopenharmony_ci int low_temp = 0 * 1000; 24568c2ecf20Sopenharmony_ci int high_temp = 255 * 1000; 24578c2ecf20Sopenharmony_ci u32 tmp; 24588c2ecf20Sopenharmony_ci 24598c2ecf20Sopenharmony_ci if (low_temp < min_temp) 24608c2ecf20Sopenharmony_ci low_temp = min_temp; 24618c2ecf20Sopenharmony_ci if (high_temp > max_temp) 24628c2ecf20Sopenharmony_ci high_temp = max_temp; 24638c2ecf20Sopenharmony_ci if (high_temp < low_temp) { 24648c2ecf20Sopenharmony_ci DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); 24658c2ecf20Sopenharmony_ci return -EINVAL; 24668c2ecf20Sopenharmony_ci } 24678c2ecf20Sopenharmony_ci 24688c2ecf20Sopenharmony_ci tmp = RREG32_SMC(CG_THERMAL_INT_CTRL); 24698c2ecf20Sopenharmony_ci tmp &= ~(DIG_THERM_INTH_MASK | DIG_THERM_INTL_MASK); 24708c2ecf20Sopenharmony_ci tmp |= (DIG_THERM_INTH(49 + (high_temp / 1000)) | 24718c2ecf20Sopenharmony_ci DIG_THERM_INTL(49 + (low_temp / 1000))); 24728c2ecf20Sopenharmony_ci WREG32_SMC(CG_THERMAL_INT_CTRL, tmp); 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.min_temp = low_temp; 24758c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.max_temp = high_temp; 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_ci return 0; 24788c2ecf20Sopenharmony_ci} 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_ciunion igp_info { 24818c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO info; 24828c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; 24838c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; 24848c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; 24858c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; 24868c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; 24878c2ecf20Sopenharmony_ci}; 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_cistatic int kv_parse_sys_info_table(struct radeon_device *rdev) 24908c2ecf20Sopenharmony_ci{ 24918c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 24928c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 24938c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 24948c2ecf20Sopenharmony_ci union igp_info *igp_info; 24958c2ecf20Sopenharmony_ci u8 frev, crev; 24968c2ecf20Sopenharmony_ci u16 data_offset; 24978c2ecf20Sopenharmony_ci int i; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci if (atom_parse_data_header(mode_info->atom_context, index, NULL, 25008c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) { 25018c2ecf20Sopenharmony_ci igp_info = (union igp_info *)(mode_info->atom_context->bios + 25028c2ecf20Sopenharmony_ci data_offset); 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci if (crev != 8) { 25058c2ecf20Sopenharmony_ci DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 25068c2ecf20Sopenharmony_ci return -EINVAL; 25078c2ecf20Sopenharmony_ci } 25088c2ecf20Sopenharmony_ci pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_8.ulBootUpEngineClock); 25098c2ecf20Sopenharmony_ci pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_8.ulBootUpUMAClock); 25108c2ecf20Sopenharmony_ci pi->sys_info.bootup_nb_voltage_index = 25118c2ecf20Sopenharmony_ci le16_to_cpu(igp_info->info_8.usBootUpNBVoltage); 25128c2ecf20Sopenharmony_ci if (igp_info->info_8.ucHtcTmpLmt == 0) 25138c2ecf20Sopenharmony_ci pi->sys_info.htc_tmp_lmt = 203; 25148c2ecf20Sopenharmony_ci else 25158c2ecf20Sopenharmony_ci pi->sys_info.htc_tmp_lmt = igp_info->info_8.ucHtcTmpLmt; 25168c2ecf20Sopenharmony_ci if (igp_info->info_8.ucHtcHystLmt == 0) 25178c2ecf20Sopenharmony_ci pi->sys_info.htc_hyst_lmt = 5; 25188c2ecf20Sopenharmony_ci else 25198c2ecf20Sopenharmony_ci pi->sys_info.htc_hyst_lmt = igp_info->info_8.ucHtcHystLmt; 25208c2ecf20Sopenharmony_ci if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { 25218c2ecf20Sopenharmony_ci DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); 25228c2ecf20Sopenharmony_ci } 25238c2ecf20Sopenharmony_ci 25248c2ecf20Sopenharmony_ci if (le32_to_cpu(igp_info->info_8.ulSystemConfig) & (1 << 3)) 25258c2ecf20Sopenharmony_ci pi->sys_info.nb_dpm_enable = true; 25268c2ecf20Sopenharmony_ci else 25278c2ecf20Sopenharmony_ci pi->sys_info.nb_dpm_enable = false; 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci for (i = 0; i < KV_NUM_NBPSTATES; i++) { 25308c2ecf20Sopenharmony_ci pi->sys_info.nbp_memory_clock[i] = 25318c2ecf20Sopenharmony_ci le32_to_cpu(igp_info->info_8.ulNbpStateMemclkFreq[i]); 25328c2ecf20Sopenharmony_ci pi->sys_info.nbp_n_clock[i] = 25338c2ecf20Sopenharmony_ci le32_to_cpu(igp_info->info_8.ulNbpStateNClkFreq[i]); 25348c2ecf20Sopenharmony_ci } 25358c2ecf20Sopenharmony_ci if (le32_to_cpu(igp_info->info_8.ulGPUCapInfo) & 25368c2ecf20Sopenharmony_ci SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) 25378c2ecf20Sopenharmony_ci pi->caps_enable_dfs_bypass = true; 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_ci sumo_construct_sclk_voltage_mapping_table(rdev, 25408c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table, 25418c2ecf20Sopenharmony_ci igp_info->info_8.sAvail_SCLK); 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_ci sumo_construct_vid_mapping_table(rdev, 25448c2ecf20Sopenharmony_ci &pi->sys_info.vid_mapping_table, 25458c2ecf20Sopenharmony_ci igp_info->info_8.sAvail_SCLK); 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci kv_construct_max_power_limits_table(rdev, 25488c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac); 25498c2ecf20Sopenharmony_ci } 25508c2ecf20Sopenharmony_ci return 0; 25518c2ecf20Sopenharmony_ci} 25528c2ecf20Sopenharmony_ci 25538c2ecf20Sopenharmony_ciunion power_info { 25548c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO info; 25558c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V2 info_2; 25568c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V3 info_3; 25578c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 25588c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 25598c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 25608c2ecf20Sopenharmony_ci}; 25618c2ecf20Sopenharmony_ci 25628c2ecf20Sopenharmony_ciunion pplib_clock_info { 25638c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_R600_CLOCK_INFO r600; 25648c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; 25658c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; 25668c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; 25678c2ecf20Sopenharmony_ci}; 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ciunion pplib_power_state { 25708c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_STATE v1; 25718c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_STATE_V2 v2; 25728c2ecf20Sopenharmony_ci}; 25738c2ecf20Sopenharmony_ci 25748c2ecf20Sopenharmony_cistatic void kv_patch_boot_state(struct radeon_device *rdev, 25758c2ecf20Sopenharmony_ci struct kv_ps *ps) 25768c2ecf20Sopenharmony_ci{ 25778c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_ci ps->num_levels = 1; 25808c2ecf20Sopenharmony_ci ps->levels[0] = pi->boot_pl; 25818c2ecf20Sopenharmony_ci} 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_cistatic void kv_parse_pplib_non_clock_info(struct radeon_device *rdev, 25848c2ecf20Sopenharmony_ci struct radeon_ps *rps, 25858c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, 25868c2ecf20Sopenharmony_ci u8 table_rev) 25878c2ecf20Sopenharmony_ci{ 25888c2ecf20Sopenharmony_ci struct kv_ps *ps = kv_get_ps(rps); 25898c2ecf20Sopenharmony_ci 25908c2ecf20Sopenharmony_ci rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); 25918c2ecf20Sopenharmony_ci rps->class = le16_to_cpu(non_clock_info->usClassification); 25928c2ecf20Sopenharmony_ci rps->class2 = le16_to_cpu(non_clock_info->usClassification2); 25938c2ecf20Sopenharmony_ci 25948c2ecf20Sopenharmony_ci if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { 25958c2ecf20Sopenharmony_ci rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); 25968c2ecf20Sopenharmony_ci rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); 25978c2ecf20Sopenharmony_ci } else { 25988c2ecf20Sopenharmony_ci rps->vclk = 0; 25998c2ecf20Sopenharmony_ci rps->dclk = 0; 26008c2ecf20Sopenharmony_ci } 26018c2ecf20Sopenharmony_ci 26028c2ecf20Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { 26038c2ecf20Sopenharmony_ci rdev->pm.dpm.boot_ps = rps; 26048c2ecf20Sopenharmony_ci kv_patch_boot_state(rdev, ps); 26058c2ecf20Sopenharmony_ci } 26068c2ecf20Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 26078c2ecf20Sopenharmony_ci rdev->pm.dpm.uvd_ps = rps; 26088c2ecf20Sopenharmony_ci} 26098c2ecf20Sopenharmony_ci 26108c2ecf20Sopenharmony_cistatic void kv_parse_pplib_clock_info(struct radeon_device *rdev, 26118c2ecf20Sopenharmony_ci struct radeon_ps *rps, int index, 26128c2ecf20Sopenharmony_ci union pplib_clock_info *clock_info) 26138c2ecf20Sopenharmony_ci{ 26148c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 26158c2ecf20Sopenharmony_ci struct kv_ps *ps = kv_get_ps(rps); 26168c2ecf20Sopenharmony_ci struct kv_pl *pl = &ps->levels[index]; 26178c2ecf20Sopenharmony_ci u32 sclk; 26188c2ecf20Sopenharmony_ci 26198c2ecf20Sopenharmony_ci sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 26208c2ecf20Sopenharmony_ci sclk |= clock_info->sumo.ucEngineClockHigh << 16; 26218c2ecf20Sopenharmony_ci pl->sclk = sclk; 26228c2ecf20Sopenharmony_ci pl->vddc_index = clock_info->sumo.vddcIndex; 26238c2ecf20Sopenharmony_ci 26248c2ecf20Sopenharmony_ci ps->num_levels = index + 1; 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci if (pi->caps_sclk_ds) { 26278c2ecf20Sopenharmony_ci pl->ds_divider_index = 5; 26288c2ecf20Sopenharmony_ci pl->ss_divider_index = 5; 26298c2ecf20Sopenharmony_ci } 26308c2ecf20Sopenharmony_ci} 26318c2ecf20Sopenharmony_ci 26328c2ecf20Sopenharmony_cistatic int kv_parse_power_table(struct radeon_device *rdev) 26338c2ecf20Sopenharmony_ci{ 26348c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 26358c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 26368c2ecf20Sopenharmony_ci union pplib_power_state *power_state; 26378c2ecf20Sopenharmony_ci int i, j, k, non_clock_array_index, clock_array_index; 26388c2ecf20Sopenharmony_ci union pplib_clock_info *clock_info; 26398c2ecf20Sopenharmony_ci struct _StateArray *state_array; 26408c2ecf20Sopenharmony_ci struct _ClockInfoArray *clock_info_array; 26418c2ecf20Sopenharmony_ci struct _NonClockInfoArray *non_clock_info_array; 26428c2ecf20Sopenharmony_ci union power_info *power_info; 26438c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 26448c2ecf20Sopenharmony_ci u16 data_offset; 26458c2ecf20Sopenharmony_ci u8 frev, crev; 26468c2ecf20Sopenharmony_ci u8 *power_state_offset; 26478c2ecf20Sopenharmony_ci struct kv_ps *ps; 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 26508c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) 26518c2ecf20Sopenharmony_ci return -EINVAL; 26528c2ecf20Sopenharmony_ci power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 26538c2ecf20Sopenharmony_ci 26548c2ecf20Sopenharmony_ci state_array = (struct _StateArray *) 26558c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 26568c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usStateArrayOffset)); 26578c2ecf20Sopenharmony_ci clock_info_array = (struct _ClockInfoArray *) 26588c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 26598c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); 26608c2ecf20Sopenharmony_ci non_clock_info_array = (struct _NonClockInfoArray *) 26618c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 26628c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_ci rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, 26658c2ecf20Sopenharmony_ci sizeof(struct radeon_ps), 26668c2ecf20Sopenharmony_ci GFP_KERNEL); 26678c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.ps) 26688c2ecf20Sopenharmony_ci return -ENOMEM; 26698c2ecf20Sopenharmony_ci power_state_offset = (u8 *)state_array->states; 26708c2ecf20Sopenharmony_ci for (i = 0; i < state_array->ucNumEntries; i++) { 26718c2ecf20Sopenharmony_ci u8 *idx; 26728c2ecf20Sopenharmony_ci power_state = (union pplib_power_state *)power_state_offset; 26738c2ecf20Sopenharmony_ci non_clock_array_index = power_state->v2.nonClockInfoIndex; 26748c2ecf20Sopenharmony_ci non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 26758c2ecf20Sopenharmony_ci &non_clock_info_array->nonClockInfo[non_clock_array_index]; 26768c2ecf20Sopenharmony_ci if (!rdev->pm.power_state[i].clock_info) 26778c2ecf20Sopenharmony_ci return -EINVAL; 26788c2ecf20Sopenharmony_ci ps = kzalloc(sizeof(struct kv_ps), GFP_KERNEL); 26798c2ecf20Sopenharmony_ci if (ps == NULL) { 26808c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 26818c2ecf20Sopenharmony_ci return -ENOMEM; 26828c2ecf20Sopenharmony_ci } 26838c2ecf20Sopenharmony_ci rdev->pm.dpm.ps[i].ps_priv = ps; 26848c2ecf20Sopenharmony_ci k = 0; 26858c2ecf20Sopenharmony_ci idx = (u8 *)&power_state->v2.clockInfoIndex[0]; 26868c2ecf20Sopenharmony_ci for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { 26878c2ecf20Sopenharmony_ci clock_array_index = idx[j]; 26888c2ecf20Sopenharmony_ci if (clock_array_index >= clock_info_array->ucNumEntries) 26898c2ecf20Sopenharmony_ci continue; 26908c2ecf20Sopenharmony_ci if (k >= SUMO_MAX_HARDWARE_POWERLEVELS) 26918c2ecf20Sopenharmony_ci break; 26928c2ecf20Sopenharmony_ci clock_info = (union pplib_clock_info *) 26938c2ecf20Sopenharmony_ci ((u8 *)&clock_info_array->clockInfo[0] + 26948c2ecf20Sopenharmony_ci (clock_array_index * clock_info_array->ucEntrySize)); 26958c2ecf20Sopenharmony_ci kv_parse_pplib_clock_info(rdev, 26968c2ecf20Sopenharmony_ci &rdev->pm.dpm.ps[i], k, 26978c2ecf20Sopenharmony_ci clock_info); 26988c2ecf20Sopenharmony_ci k++; 26998c2ecf20Sopenharmony_ci } 27008c2ecf20Sopenharmony_ci kv_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], 27018c2ecf20Sopenharmony_ci non_clock_info, 27028c2ecf20Sopenharmony_ci non_clock_info_array->ucEntrySize); 27038c2ecf20Sopenharmony_ci power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 27048c2ecf20Sopenharmony_ci } 27058c2ecf20Sopenharmony_ci rdev->pm.dpm.num_ps = state_array->ucNumEntries; 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci /* fill in the vce power states */ 27088c2ecf20Sopenharmony_ci for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) { 27098c2ecf20Sopenharmony_ci u32 sclk; 27108c2ecf20Sopenharmony_ci clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx; 27118c2ecf20Sopenharmony_ci clock_info = (union pplib_clock_info *) 27128c2ecf20Sopenharmony_ci &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; 27138c2ecf20Sopenharmony_ci sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 27148c2ecf20Sopenharmony_ci sclk |= clock_info->sumo.ucEngineClockHigh << 16; 27158c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].sclk = sclk; 27168c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].mclk = 0; 27178c2ecf20Sopenharmony_ci } 27188c2ecf20Sopenharmony_ci 27198c2ecf20Sopenharmony_ci return 0; 27208c2ecf20Sopenharmony_ci} 27218c2ecf20Sopenharmony_ci 27228c2ecf20Sopenharmony_ciint kv_dpm_init(struct radeon_device *rdev) 27238c2ecf20Sopenharmony_ci{ 27248c2ecf20Sopenharmony_ci struct kv_power_info *pi; 27258c2ecf20Sopenharmony_ci int ret, i; 27268c2ecf20Sopenharmony_ci 27278c2ecf20Sopenharmony_ci pi = kzalloc(sizeof(struct kv_power_info), GFP_KERNEL); 27288c2ecf20Sopenharmony_ci if (pi == NULL) 27298c2ecf20Sopenharmony_ci return -ENOMEM; 27308c2ecf20Sopenharmony_ci rdev->pm.dpm.priv = pi; 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci ret = r600_get_platform_caps(rdev); 27338c2ecf20Sopenharmony_ci if (ret) 27348c2ecf20Sopenharmony_ci return ret; 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci ret = r600_parse_extended_power_table(rdev); 27378c2ecf20Sopenharmony_ci if (ret) 27388c2ecf20Sopenharmony_ci return ret; 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) 27418c2ecf20Sopenharmony_ci pi->at[i] = TRINITY_AT_DFLT; 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_ci pi->sram_end = SMC_RAM_END; 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_ci /* Enabling nb dpm on an asrock system prevents dpm from working */ 27468c2ecf20Sopenharmony_ci if (rdev->pdev->subsystem_vendor == 0x1849) 27478c2ecf20Sopenharmony_ci pi->enable_nb_dpm = false; 27488c2ecf20Sopenharmony_ci else 27498c2ecf20Sopenharmony_ci pi->enable_nb_dpm = true; 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci pi->caps_power_containment = true; 27528c2ecf20Sopenharmony_ci pi->caps_cac = true; 27538c2ecf20Sopenharmony_ci pi->enable_didt = false; 27548c2ecf20Sopenharmony_ci if (pi->enable_didt) { 27558c2ecf20Sopenharmony_ci pi->caps_sq_ramping = true; 27568c2ecf20Sopenharmony_ci pi->caps_db_ramping = true; 27578c2ecf20Sopenharmony_ci pi->caps_td_ramping = true; 27588c2ecf20Sopenharmony_ci pi->caps_tcp_ramping = true; 27598c2ecf20Sopenharmony_ci } 27608c2ecf20Sopenharmony_ci 27618c2ecf20Sopenharmony_ci pi->caps_sclk_ds = true; 27628c2ecf20Sopenharmony_ci pi->enable_auto_thermal_throttling = true; 27638c2ecf20Sopenharmony_ci pi->disable_nb_ps3_in_battery = false; 27648c2ecf20Sopenharmony_ci if (radeon_bapm == -1) { 27658c2ecf20Sopenharmony_ci /* only enable bapm on KB, ML by default */ 27668c2ecf20Sopenharmony_ci if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) 27678c2ecf20Sopenharmony_ci pi->bapm_enable = true; 27688c2ecf20Sopenharmony_ci else 27698c2ecf20Sopenharmony_ci pi->bapm_enable = false; 27708c2ecf20Sopenharmony_ci } else if (radeon_bapm == 0) { 27718c2ecf20Sopenharmony_ci pi->bapm_enable = false; 27728c2ecf20Sopenharmony_ci } else { 27738c2ecf20Sopenharmony_ci pi->bapm_enable = true; 27748c2ecf20Sopenharmony_ci } 27758c2ecf20Sopenharmony_ci pi->voltage_drop_t = 0; 27768c2ecf20Sopenharmony_ci pi->caps_sclk_throttle_low_notification = false; 27778c2ecf20Sopenharmony_ci pi->caps_fps = false; /* true? */ 27788c2ecf20Sopenharmony_ci pi->caps_uvd_pg = true; 27798c2ecf20Sopenharmony_ci pi->caps_uvd_dpm = true; 27808c2ecf20Sopenharmony_ci pi->caps_vce_pg = false; /* XXX true */ 27818c2ecf20Sopenharmony_ci pi->caps_samu_pg = false; 27828c2ecf20Sopenharmony_ci pi->caps_acp_pg = false; 27838c2ecf20Sopenharmony_ci pi->caps_stable_p_state = false; 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci ret = kv_parse_sys_info_table(rdev); 27868c2ecf20Sopenharmony_ci if (ret) 27878c2ecf20Sopenharmony_ci return ret; 27888c2ecf20Sopenharmony_ci 27898c2ecf20Sopenharmony_ci kv_patch_voltage_values(rdev); 27908c2ecf20Sopenharmony_ci kv_construct_boot_state(rdev); 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci ret = kv_parse_power_table(rdev); 27938c2ecf20Sopenharmony_ci if (ret) 27948c2ecf20Sopenharmony_ci return ret; 27958c2ecf20Sopenharmony_ci 27968c2ecf20Sopenharmony_ci pi->enable_dpm = true; 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci return 0; 27998c2ecf20Sopenharmony_ci} 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_civoid kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 28028c2ecf20Sopenharmony_ci struct seq_file *m) 28038c2ecf20Sopenharmony_ci{ 28048c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 28058c2ecf20Sopenharmony_ci u32 current_index = 28068c2ecf20Sopenharmony_ci (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) >> 28078c2ecf20Sopenharmony_ci CURR_SCLK_INDEX_SHIFT; 28088c2ecf20Sopenharmony_ci u32 sclk, tmp; 28098c2ecf20Sopenharmony_ci u16 vddc; 28108c2ecf20Sopenharmony_ci 28118c2ecf20Sopenharmony_ci if (current_index >= SMU__NUM_SCLK_DPM_STATE) { 28128c2ecf20Sopenharmony_ci seq_printf(m, "invalid dpm profile %d\n", current_index); 28138c2ecf20Sopenharmony_ci } else { 28148c2ecf20Sopenharmony_ci sclk = be32_to_cpu(pi->graphics_level[current_index].SclkFrequency); 28158c2ecf20Sopenharmony_ci tmp = (RREG32_SMC(SMU_VOLTAGE_STATUS) & SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> 28168c2ecf20Sopenharmony_ci SMU_VOLTAGE_CURRENT_LEVEL_SHIFT; 28178c2ecf20Sopenharmony_ci vddc = kv_convert_8bit_index_to_voltage(rdev, (u16)tmp); 28188c2ecf20Sopenharmony_ci seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en"); 28198c2ecf20Sopenharmony_ci seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en"); 28208c2ecf20Sopenharmony_ci seq_printf(m, "power level %d sclk: %u vddc: %u\n", 28218c2ecf20Sopenharmony_ci current_index, sclk, vddc); 28228c2ecf20Sopenharmony_ci } 28238c2ecf20Sopenharmony_ci} 28248c2ecf20Sopenharmony_ci 28258c2ecf20Sopenharmony_ciu32 kv_dpm_get_current_sclk(struct radeon_device *rdev) 28268c2ecf20Sopenharmony_ci{ 28278c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 28288c2ecf20Sopenharmony_ci u32 current_index = 28298c2ecf20Sopenharmony_ci (RREG32_SMC(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) >> 28308c2ecf20Sopenharmony_ci CURR_SCLK_INDEX_SHIFT; 28318c2ecf20Sopenharmony_ci u32 sclk; 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_ci if (current_index >= SMU__NUM_SCLK_DPM_STATE) { 28348c2ecf20Sopenharmony_ci return 0; 28358c2ecf20Sopenharmony_ci } else { 28368c2ecf20Sopenharmony_ci sclk = be32_to_cpu(pi->graphics_level[current_index].SclkFrequency); 28378c2ecf20Sopenharmony_ci return sclk; 28388c2ecf20Sopenharmony_ci } 28398c2ecf20Sopenharmony_ci} 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ciu32 kv_dpm_get_current_mclk(struct radeon_device *rdev) 28428c2ecf20Sopenharmony_ci{ 28438c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 28468c2ecf20Sopenharmony_ci} 28478c2ecf20Sopenharmony_ci 28488c2ecf20Sopenharmony_civoid kv_dpm_print_power_state(struct radeon_device *rdev, 28498c2ecf20Sopenharmony_ci struct radeon_ps *rps) 28508c2ecf20Sopenharmony_ci{ 28518c2ecf20Sopenharmony_ci int i; 28528c2ecf20Sopenharmony_ci struct kv_ps *ps = kv_get_ps(rps); 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_ci r600_dpm_print_class_info(rps->class, rps->class2); 28558c2ecf20Sopenharmony_ci r600_dpm_print_cap_info(rps->caps); 28568c2ecf20Sopenharmony_ci printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 28578c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 28588c2ecf20Sopenharmony_ci struct kv_pl *pl = &ps->levels[i]; 28598c2ecf20Sopenharmony_ci printk("\t\tpower level %d sclk: %u vddc: %u\n", 28608c2ecf20Sopenharmony_ci i, pl->sclk, 28618c2ecf20Sopenharmony_ci kv_convert_8bit_index_to_voltage(rdev, pl->vddc_index)); 28628c2ecf20Sopenharmony_ci } 28638c2ecf20Sopenharmony_ci r600_dpm_print_ps_status(rdev, rps); 28648c2ecf20Sopenharmony_ci} 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_civoid kv_dpm_fini(struct radeon_device *rdev) 28678c2ecf20Sopenharmony_ci{ 28688c2ecf20Sopenharmony_ci int i; 28698c2ecf20Sopenharmony_ci 28708c2ecf20Sopenharmony_ci for (i = 0; i < rdev->pm.dpm.num_ps; i++) { 28718c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps[i].ps_priv); 28728c2ecf20Sopenharmony_ci } 28738c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 28748c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.priv); 28758c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 28768c2ecf20Sopenharmony_ci} 28778c2ecf20Sopenharmony_ci 28788c2ecf20Sopenharmony_civoid kv_dpm_display_configuration_changed(struct radeon_device *rdev) 28798c2ecf20Sopenharmony_ci{ 28808c2ecf20Sopenharmony_ci 28818c2ecf20Sopenharmony_ci} 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ciu32 kv_dpm_get_sclk(struct radeon_device *rdev, bool low) 28848c2ecf20Sopenharmony_ci{ 28858c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 28868c2ecf20Sopenharmony_ci struct kv_ps *requested_state = kv_get_ps(&pi->requested_rps); 28878c2ecf20Sopenharmony_ci 28888c2ecf20Sopenharmony_ci if (low) 28898c2ecf20Sopenharmony_ci return requested_state->levels[0].sclk; 28908c2ecf20Sopenharmony_ci else 28918c2ecf20Sopenharmony_ci return requested_state->levels[requested_state->num_levels - 1].sclk; 28928c2ecf20Sopenharmony_ci} 28938c2ecf20Sopenharmony_ci 28948c2ecf20Sopenharmony_ciu32 kv_dpm_get_mclk(struct radeon_device *rdev, bool low) 28958c2ecf20Sopenharmony_ci{ 28968c2ecf20Sopenharmony_ci struct kv_power_info *pi = kv_get_pi(rdev); 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 28998c2ecf20Sopenharmony_ci} 29008c2ecf20Sopenharmony_ci 2901