18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2012 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 "r600_dpm.h" 288c2ecf20Sopenharmony_ci#include "radeon.h" 298c2ecf20Sopenharmony_ci#include "radeon_asic.h" 308c2ecf20Sopenharmony_ci#include "trinity_dpm.h" 318c2ecf20Sopenharmony_ci#include "trinityd.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5 348c2ecf20Sopenharmony_ci#define TRINITY_MINIMUM_ENGINE_CLOCK 800 358c2ecf20Sopenharmony_ci#define SCLK_MIN_DIV_INTV_SHIFT 12 368c2ecf20Sopenharmony_ci#define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#ifndef TRINITY_MGCG_SEQUENCE 398c2ecf20Sopenharmony_ci#define TRINITY_MGCG_SEQUENCE 100 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic const u32 trinity_mgcg_shls_default[] = 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci /* Register, Value, Mask */ 448c2ecf20Sopenharmony_ci 0x0000802c, 0xc0000000, 0xffffffff, 458c2ecf20Sopenharmony_ci 0x00003fc4, 0xc0000000, 0xffffffff, 468c2ecf20Sopenharmony_ci 0x00005448, 0x00000100, 0xffffffff, 478c2ecf20Sopenharmony_ci 0x000055e4, 0x00000100, 0xffffffff, 488c2ecf20Sopenharmony_ci 0x0000160c, 0x00000100, 0xffffffff, 498c2ecf20Sopenharmony_ci 0x00008984, 0x06000100, 0xffffffff, 508c2ecf20Sopenharmony_ci 0x0000c164, 0x00000100, 0xffffffff, 518c2ecf20Sopenharmony_ci 0x00008a18, 0x00000100, 0xffffffff, 528c2ecf20Sopenharmony_ci 0x0000897c, 0x06000100, 0xffffffff, 538c2ecf20Sopenharmony_ci 0x00008b28, 0x00000100, 0xffffffff, 548c2ecf20Sopenharmony_ci 0x00009144, 0x00800200, 0xffffffff, 558c2ecf20Sopenharmony_ci 0x00009a60, 0x00000100, 0xffffffff, 568c2ecf20Sopenharmony_ci 0x00009868, 0x00000100, 0xffffffff, 578c2ecf20Sopenharmony_ci 0x00008d58, 0x00000100, 0xffffffff, 588c2ecf20Sopenharmony_ci 0x00009510, 0x00000100, 0xffffffff, 598c2ecf20Sopenharmony_ci 0x0000949c, 0x00000100, 0xffffffff, 608c2ecf20Sopenharmony_ci 0x00009654, 0x00000100, 0xffffffff, 618c2ecf20Sopenharmony_ci 0x00009030, 0x00000100, 0xffffffff, 628c2ecf20Sopenharmony_ci 0x00009034, 0x00000100, 0xffffffff, 638c2ecf20Sopenharmony_ci 0x00009038, 0x00000100, 0xffffffff, 648c2ecf20Sopenharmony_ci 0x0000903c, 0x00000100, 0xffffffff, 658c2ecf20Sopenharmony_ci 0x00009040, 0x00000100, 0xffffffff, 668c2ecf20Sopenharmony_ci 0x0000a200, 0x00000100, 0xffffffff, 678c2ecf20Sopenharmony_ci 0x0000a204, 0x00000100, 0xffffffff, 688c2ecf20Sopenharmony_ci 0x0000a208, 0x00000100, 0xffffffff, 698c2ecf20Sopenharmony_ci 0x0000a20c, 0x00000100, 0xffffffff, 708c2ecf20Sopenharmony_ci 0x00009744, 0x00000100, 0xffffffff, 718c2ecf20Sopenharmony_ci 0x00003f80, 0x00000100, 0xffffffff, 728c2ecf20Sopenharmony_ci 0x0000a210, 0x00000100, 0xffffffff, 738c2ecf20Sopenharmony_ci 0x0000a214, 0x00000100, 0xffffffff, 748c2ecf20Sopenharmony_ci 0x000004d8, 0x00000100, 0xffffffff, 758c2ecf20Sopenharmony_ci 0x00009664, 0x00000100, 0xffffffff, 768c2ecf20Sopenharmony_ci 0x00009698, 0x00000100, 0xffffffff, 778c2ecf20Sopenharmony_ci 0x000004d4, 0x00000200, 0xffffffff, 788c2ecf20Sopenharmony_ci 0x000004d0, 0x00000000, 0xffffffff, 798c2ecf20Sopenharmony_ci 0x000030cc, 0x00000104, 0xffffffff, 808c2ecf20Sopenharmony_ci 0x0000d0c0, 0x00000100, 0xffffffff, 818c2ecf20Sopenharmony_ci 0x0000d8c0, 0x00000100, 0xffffffff, 828c2ecf20Sopenharmony_ci 0x0000951c, 0x00010000, 0xffffffff, 838c2ecf20Sopenharmony_ci 0x00009160, 0x00030002, 0xffffffff, 848c2ecf20Sopenharmony_ci 0x00009164, 0x00050004, 0xffffffff, 858c2ecf20Sopenharmony_ci 0x00009168, 0x00070006, 0xffffffff, 868c2ecf20Sopenharmony_ci 0x00009178, 0x00070000, 0xffffffff, 878c2ecf20Sopenharmony_ci 0x0000917c, 0x00030002, 0xffffffff, 888c2ecf20Sopenharmony_ci 0x00009180, 0x00050004, 0xffffffff, 898c2ecf20Sopenharmony_ci 0x0000918c, 0x00010006, 0xffffffff, 908c2ecf20Sopenharmony_ci 0x00009190, 0x00090008, 0xffffffff, 918c2ecf20Sopenharmony_ci 0x00009194, 0x00070000, 0xffffffff, 928c2ecf20Sopenharmony_ci 0x00009198, 0x00030002, 0xffffffff, 938c2ecf20Sopenharmony_ci 0x0000919c, 0x00050004, 0xffffffff, 948c2ecf20Sopenharmony_ci 0x000091a8, 0x00010006, 0xffffffff, 958c2ecf20Sopenharmony_ci 0x000091ac, 0x00090008, 0xffffffff, 968c2ecf20Sopenharmony_ci 0x000091b0, 0x00070000, 0xffffffff, 978c2ecf20Sopenharmony_ci 0x000091b4, 0x00030002, 0xffffffff, 988c2ecf20Sopenharmony_ci 0x000091b8, 0x00050004, 0xffffffff, 998c2ecf20Sopenharmony_ci 0x000091c4, 0x00010006, 0xffffffff, 1008c2ecf20Sopenharmony_ci 0x000091c8, 0x00090008, 0xffffffff, 1018c2ecf20Sopenharmony_ci 0x000091cc, 0x00070000, 0xffffffff, 1028c2ecf20Sopenharmony_ci 0x000091d0, 0x00030002, 0xffffffff, 1038c2ecf20Sopenharmony_ci 0x000091d4, 0x00050004, 0xffffffff, 1048c2ecf20Sopenharmony_ci 0x000091e0, 0x00010006, 0xffffffff, 1058c2ecf20Sopenharmony_ci 0x000091e4, 0x00090008, 0xffffffff, 1068c2ecf20Sopenharmony_ci 0x000091e8, 0x00000000, 0xffffffff, 1078c2ecf20Sopenharmony_ci 0x000091ec, 0x00070000, 0xffffffff, 1088c2ecf20Sopenharmony_ci 0x000091f0, 0x00030002, 0xffffffff, 1098c2ecf20Sopenharmony_ci 0x000091f4, 0x00050004, 0xffffffff, 1108c2ecf20Sopenharmony_ci 0x00009200, 0x00010006, 0xffffffff, 1118c2ecf20Sopenharmony_ci 0x00009204, 0x00090008, 0xffffffff, 1128c2ecf20Sopenharmony_ci 0x00009208, 0x00070000, 0xffffffff, 1138c2ecf20Sopenharmony_ci 0x0000920c, 0x00030002, 0xffffffff, 1148c2ecf20Sopenharmony_ci 0x00009210, 0x00050004, 0xffffffff, 1158c2ecf20Sopenharmony_ci 0x0000921c, 0x00010006, 0xffffffff, 1168c2ecf20Sopenharmony_ci 0x00009220, 0x00090008, 0xffffffff, 1178c2ecf20Sopenharmony_ci 0x00009294, 0x00000000, 0xffffffff 1188c2ecf20Sopenharmony_ci}; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic const u32 trinity_mgcg_shls_enable[] = 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci /* Register, Value, Mask */ 1238c2ecf20Sopenharmony_ci 0x0000802c, 0xc0000000, 0xffffffff, 1248c2ecf20Sopenharmony_ci 0x000008f8, 0x00000000, 0xffffffff, 1258c2ecf20Sopenharmony_ci 0x000008fc, 0x00000000, 0x000133FF, 1268c2ecf20Sopenharmony_ci 0x000008f8, 0x00000001, 0xffffffff, 1278c2ecf20Sopenharmony_ci 0x000008fc, 0x00000000, 0xE00B03FC, 1288c2ecf20Sopenharmony_ci 0x00009150, 0x96944200, 0xffffffff 1298c2ecf20Sopenharmony_ci}; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic const u32 trinity_mgcg_shls_disable[] = 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci /* Register, Value, Mask */ 1348c2ecf20Sopenharmony_ci 0x0000802c, 0xc0000000, 0xffffffff, 1358c2ecf20Sopenharmony_ci 0x00009150, 0x00600000, 0xffffffff, 1368c2ecf20Sopenharmony_ci 0x000008f8, 0x00000000, 0xffffffff, 1378c2ecf20Sopenharmony_ci 0x000008fc, 0xffffffff, 0x000133FF, 1388c2ecf20Sopenharmony_ci 0x000008f8, 0x00000001, 0xffffffff, 1398c2ecf20Sopenharmony_ci 0x000008fc, 0xffffffff, 0xE00B03FC 1408c2ecf20Sopenharmony_ci}; 1418c2ecf20Sopenharmony_ci#endif 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci#ifndef TRINITY_SYSLS_SEQUENCE 1448c2ecf20Sopenharmony_ci#define TRINITY_SYSLS_SEQUENCE 100 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic const u32 trinity_sysls_default[] = 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci /* Register, Value, Mask */ 1498c2ecf20Sopenharmony_ci 0x000055e8, 0x00000000, 0xffffffff, 1508c2ecf20Sopenharmony_ci 0x0000d0bc, 0x00000000, 0xffffffff, 1518c2ecf20Sopenharmony_ci 0x0000d8bc, 0x00000000, 0xffffffff, 1528c2ecf20Sopenharmony_ci 0x000015c0, 0x000c1401, 0xffffffff, 1538c2ecf20Sopenharmony_ci 0x0000264c, 0x000c0400, 0xffffffff, 1548c2ecf20Sopenharmony_ci 0x00002648, 0x000c0400, 0xffffffff, 1558c2ecf20Sopenharmony_ci 0x00002650, 0x000c0400, 0xffffffff, 1568c2ecf20Sopenharmony_ci 0x000020b8, 0x000c0400, 0xffffffff, 1578c2ecf20Sopenharmony_ci 0x000020bc, 0x000c0400, 0xffffffff, 1588c2ecf20Sopenharmony_ci 0x000020c0, 0x000c0c80, 0xffffffff, 1598c2ecf20Sopenharmony_ci 0x0000f4a0, 0x000000c0, 0xffffffff, 1608c2ecf20Sopenharmony_ci 0x0000f4a4, 0x00680fff, 0xffffffff, 1618c2ecf20Sopenharmony_ci 0x00002f50, 0x00000404, 0xffffffff, 1628c2ecf20Sopenharmony_ci 0x000004c8, 0x00000001, 0xffffffff, 1638c2ecf20Sopenharmony_ci 0x0000641c, 0x00000000, 0xffffffff, 1648c2ecf20Sopenharmony_ci 0x00000c7c, 0x00000000, 0xffffffff, 1658c2ecf20Sopenharmony_ci 0x00006dfc, 0x00000000, 0xffffffff 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic const u32 trinity_sysls_disable[] = 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci /* Register, Value, Mask */ 1718c2ecf20Sopenharmony_ci 0x0000d0c0, 0x00000000, 0xffffffff, 1728c2ecf20Sopenharmony_ci 0x0000d8c0, 0x00000000, 0xffffffff, 1738c2ecf20Sopenharmony_ci 0x000055e8, 0x00000000, 0xffffffff, 1748c2ecf20Sopenharmony_ci 0x0000d0bc, 0x00000000, 0xffffffff, 1758c2ecf20Sopenharmony_ci 0x0000d8bc, 0x00000000, 0xffffffff, 1768c2ecf20Sopenharmony_ci 0x000015c0, 0x00041401, 0xffffffff, 1778c2ecf20Sopenharmony_ci 0x0000264c, 0x00040400, 0xffffffff, 1788c2ecf20Sopenharmony_ci 0x00002648, 0x00040400, 0xffffffff, 1798c2ecf20Sopenharmony_ci 0x00002650, 0x00040400, 0xffffffff, 1808c2ecf20Sopenharmony_ci 0x000020b8, 0x00040400, 0xffffffff, 1818c2ecf20Sopenharmony_ci 0x000020bc, 0x00040400, 0xffffffff, 1828c2ecf20Sopenharmony_ci 0x000020c0, 0x00040c80, 0xffffffff, 1838c2ecf20Sopenharmony_ci 0x0000f4a0, 0x000000c0, 0xffffffff, 1848c2ecf20Sopenharmony_ci 0x0000f4a4, 0x00680000, 0xffffffff, 1858c2ecf20Sopenharmony_ci 0x00002f50, 0x00000404, 0xffffffff, 1868c2ecf20Sopenharmony_ci 0x000004c8, 0x00000001, 0xffffffff, 1878c2ecf20Sopenharmony_ci 0x0000641c, 0x00007ffd, 0xffffffff, 1888c2ecf20Sopenharmony_ci 0x00000c7c, 0x0000ff00, 0xffffffff, 1898c2ecf20Sopenharmony_ci 0x00006dfc, 0x0000007f, 0xffffffff 1908c2ecf20Sopenharmony_ci}; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic const u32 trinity_sysls_enable[] = 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci /* Register, Value, Mask */ 1958c2ecf20Sopenharmony_ci 0x000055e8, 0x00000001, 0xffffffff, 1968c2ecf20Sopenharmony_ci 0x0000d0bc, 0x00000100, 0xffffffff, 1978c2ecf20Sopenharmony_ci 0x0000d8bc, 0x00000100, 0xffffffff, 1988c2ecf20Sopenharmony_ci 0x000015c0, 0x000c1401, 0xffffffff, 1998c2ecf20Sopenharmony_ci 0x0000264c, 0x000c0400, 0xffffffff, 2008c2ecf20Sopenharmony_ci 0x00002648, 0x000c0400, 0xffffffff, 2018c2ecf20Sopenharmony_ci 0x00002650, 0x000c0400, 0xffffffff, 2028c2ecf20Sopenharmony_ci 0x000020b8, 0x000c0400, 0xffffffff, 2038c2ecf20Sopenharmony_ci 0x000020bc, 0x000c0400, 0xffffffff, 2048c2ecf20Sopenharmony_ci 0x000020c0, 0x000c0c80, 0xffffffff, 2058c2ecf20Sopenharmony_ci 0x0000f4a0, 0x000000c0, 0xffffffff, 2068c2ecf20Sopenharmony_ci 0x0000f4a4, 0x00680fff, 0xffffffff, 2078c2ecf20Sopenharmony_ci 0x00002f50, 0x00000903, 0xffffffff, 2088c2ecf20Sopenharmony_ci 0x000004c8, 0x00000000, 0xffffffff, 2098c2ecf20Sopenharmony_ci 0x0000641c, 0x00000000, 0xffffffff, 2108c2ecf20Sopenharmony_ci 0x00000c7c, 0x00000000, 0xffffffff, 2118c2ecf20Sopenharmony_ci 0x00006dfc, 0x00000000, 0xffffffff 2128c2ecf20Sopenharmony_ci}; 2138c2ecf20Sopenharmony_ci#endif 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic const u32 trinity_override_mgpg_sequences[] = 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci /* Register, Value */ 2188c2ecf20Sopenharmony_ci 0x00000200, 0xE030032C, 2198c2ecf20Sopenharmony_ci 0x00000204, 0x00000FFF, 2208c2ecf20Sopenharmony_ci 0x00000200, 0xE0300058, 2218c2ecf20Sopenharmony_ci 0x00000204, 0x00030301, 2228c2ecf20Sopenharmony_ci 0x00000200, 0xE0300054, 2238c2ecf20Sopenharmony_ci 0x00000204, 0x500010FF, 2248c2ecf20Sopenharmony_ci 0x00000200, 0xE0300074, 2258c2ecf20Sopenharmony_ci 0x00000204, 0x00030301, 2268c2ecf20Sopenharmony_ci 0x00000200, 0xE0300070, 2278c2ecf20Sopenharmony_ci 0x00000204, 0x500010FF, 2288c2ecf20Sopenharmony_ci 0x00000200, 0xE0300090, 2298c2ecf20Sopenharmony_ci 0x00000204, 0x00030301, 2308c2ecf20Sopenharmony_ci 0x00000200, 0xE030008C, 2318c2ecf20Sopenharmony_ci 0x00000204, 0x500010FF, 2328c2ecf20Sopenharmony_ci 0x00000200, 0xE03000AC, 2338c2ecf20Sopenharmony_ci 0x00000204, 0x00030301, 2348c2ecf20Sopenharmony_ci 0x00000200, 0xE03000A8, 2358c2ecf20Sopenharmony_ci 0x00000204, 0x500010FF, 2368c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C8, 2378c2ecf20Sopenharmony_ci 0x00000204, 0x00030301, 2388c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C4, 2398c2ecf20Sopenharmony_ci 0x00000204, 0x500010FF, 2408c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E4, 2418c2ecf20Sopenharmony_ci 0x00000204, 0x00030301, 2428c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E0, 2438c2ecf20Sopenharmony_ci 0x00000204, 0x500010FF, 2448c2ecf20Sopenharmony_ci 0x00000200, 0xE0300100, 2458c2ecf20Sopenharmony_ci 0x00000204, 0x00030301, 2468c2ecf20Sopenharmony_ci 0x00000200, 0xE03000FC, 2478c2ecf20Sopenharmony_ci 0x00000204, 0x500010FF, 2488c2ecf20Sopenharmony_ci 0x00000200, 0xE0300058, 2498c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2508c2ecf20Sopenharmony_ci 0x00000200, 0xE0300054, 2518c2ecf20Sopenharmony_ci 0x00000204, 0x600010FF, 2528c2ecf20Sopenharmony_ci 0x00000200, 0xE0300074, 2538c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2548c2ecf20Sopenharmony_ci 0x00000200, 0xE0300070, 2558c2ecf20Sopenharmony_ci 0x00000204, 0x600010FF, 2568c2ecf20Sopenharmony_ci 0x00000200, 0xE0300090, 2578c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2588c2ecf20Sopenharmony_ci 0x00000200, 0xE030008C, 2598c2ecf20Sopenharmony_ci 0x00000204, 0x600010FF, 2608c2ecf20Sopenharmony_ci 0x00000200, 0xE03000AC, 2618c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2628c2ecf20Sopenharmony_ci 0x00000200, 0xE03000A8, 2638c2ecf20Sopenharmony_ci 0x00000204, 0x600010FF, 2648c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C8, 2658c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2668c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C4, 2678c2ecf20Sopenharmony_ci 0x00000204, 0x600010FF, 2688c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E4, 2698c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2708c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E0, 2718c2ecf20Sopenharmony_ci 0x00000204, 0x600010FF, 2728c2ecf20Sopenharmony_ci 0x00000200, 0xE0300100, 2738c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2748c2ecf20Sopenharmony_ci 0x00000200, 0xE03000FC, 2758c2ecf20Sopenharmony_ci 0x00000204, 0x600010FF, 2768c2ecf20Sopenharmony_ci 0x00000200, 0xE0300058, 2778c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2788c2ecf20Sopenharmony_ci 0x00000200, 0xE0300054, 2798c2ecf20Sopenharmony_ci 0x00000204, 0x700010FF, 2808c2ecf20Sopenharmony_ci 0x00000200, 0xE0300074, 2818c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2828c2ecf20Sopenharmony_ci 0x00000200, 0xE0300070, 2838c2ecf20Sopenharmony_ci 0x00000204, 0x700010FF, 2848c2ecf20Sopenharmony_ci 0x00000200, 0xE0300090, 2858c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2868c2ecf20Sopenharmony_ci 0x00000200, 0xE030008C, 2878c2ecf20Sopenharmony_ci 0x00000204, 0x700010FF, 2888c2ecf20Sopenharmony_ci 0x00000200, 0xE03000AC, 2898c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2908c2ecf20Sopenharmony_ci 0x00000200, 0xE03000A8, 2918c2ecf20Sopenharmony_ci 0x00000204, 0x700010FF, 2928c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C8, 2938c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2948c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C4, 2958c2ecf20Sopenharmony_ci 0x00000204, 0x700010FF, 2968c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E4, 2978c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 2988c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E0, 2998c2ecf20Sopenharmony_ci 0x00000204, 0x700010FF, 3008c2ecf20Sopenharmony_ci 0x00000200, 0xE0300100, 3018c2ecf20Sopenharmony_ci 0x00000204, 0x00030303, 3028c2ecf20Sopenharmony_ci 0x00000200, 0xE03000FC, 3038c2ecf20Sopenharmony_ci 0x00000204, 0x700010FF, 3048c2ecf20Sopenharmony_ci 0x00000200, 0xE0300058, 3058c2ecf20Sopenharmony_ci 0x00000204, 0x00010303, 3068c2ecf20Sopenharmony_ci 0x00000200, 0xE0300054, 3078c2ecf20Sopenharmony_ci 0x00000204, 0x800010FF, 3088c2ecf20Sopenharmony_ci 0x00000200, 0xE0300074, 3098c2ecf20Sopenharmony_ci 0x00000204, 0x00010303, 3108c2ecf20Sopenharmony_ci 0x00000200, 0xE0300070, 3118c2ecf20Sopenharmony_ci 0x00000204, 0x800010FF, 3128c2ecf20Sopenharmony_ci 0x00000200, 0xE0300090, 3138c2ecf20Sopenharmony_ci 0x00000204, 0x00010303, 3148c2ecf20Sopenharmony_ci 0x00000200, 0xE030008C, 3158c2ecf20Sopenharmony_ci 0x00000204, 0x800010FF, 3168c2ecf20Sopenharmony_ci 0x00000200, 0xE03000AC, 3178c2ecf20Sopenharmony_ci 0x00000204, 0x00010303, 3188c2ecf20Sopenharmony_ci 0x00000200, 0xE03000A8, 3198c2ecf20Sopenharmony_ci 0x00000204, 0x800010FF, 3208c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C4, 3218c2ecf20Sopenharmony_ci 0x00000204, 0x800010FF, 3228c2ecf20Sopenharmony_ci 0x00000200, 0xE03000C8, 3238c2ecf20Sopenharmony_ci 0x00000204, 0x00010303, 3248c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E4, 3258c2ecf20Sopenharmony_ci 0x00000204, 0x00010303, 3268c2ecf20Sopenharmony_ci 0x00000200, 0xE03000E0, 3278c2ecf20Sopenharmony_ci 0x00000204, 0x800010FF, 3288c2ecf20Sopenharmony_ci 0x00000200, 0xE0300100, 3298c2ecf20Sopenharmony_ci 0x00000204, 0x00010303, 3308c2ecf20Sopenharmony_ci 0x00000200, 0xE03000FC, 3318c2ecf20Sopenharmony_ci 0x00000204, 0x800010FF, 3328c2ecf20Sopenharmony_ci 0x00000200, 0x0001f198, 3338c2ecf20Sopenharmony_ci 0x00000204, 0x0003ffff, 3348c2ecf20Sopenharmony_ci 0x00000200, 0x0001f19C, 3358c2ecf20Sopenharmony_ci 0x00000204, 0x3fffffff, 3368c2ecf20Sopenharmony_ci 0x00000200, 0xE030032C, 3378c2ecf20Sopenharmony_ci 0x00000204, 0x00000000, 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ciextern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable); 3418c2ecf20Sopenharmony_cistatic void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev, 3428c2ecf20Sopenharmony_ci const u32 *seq, u32 count); 3438c2ecf20Sopenharmony_cistatic void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev); 3448c2ecf20Sopenharmony_cistatic void trinity_apply_state_adjust_rules(struct radeon_device *rdev, 3458c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 3468c2ecf20Sopenharmony_ci struct radeon_ps *old_rps); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic struct trinity_ps *trinity_get_ps(struct radeon_ps *rps) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci struct trinity_ps *ps = rps->ps_priv; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci return ps; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci struct trinity_power_info *pi = rdev->pm.dpm.priv; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci return pi; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic void trinity_gfx_powergating_initialize(struct radeon_device *rdev) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 3658c2ecf20Sopenharmony_ci u32 p, u; 3668c2ecf20Sopenharmony_ci u32 value; 3678c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 3688c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 3698c2ecf20Sopenharmony_ci u32 sssd = 1; 3708c2ecf20Sopenharmony_ci int ret; 3718c2ecf20Sopenharmony_ci u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 3748c2ecf20Sopenharmony_ci 25000, false, ÷rs); 3758c2ecf20Sopenharmony_ci if (ret) 3768c2ecf20Sopenharmony_ci return; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci value = RREG32_SMC(GFX_POWER_GATING_CNTL); 3798c2ecf20Sopenharmony_ci value &= ~(SSSD_MASK | PDS_DIV_MASK); 3808c2ecf20Sopenharmony_ci if (sssd) 3818c2ecf20Sopenharmony_ci value |= SSSD(1); 3828c2ecf20Sopenharmony_ci value |= PDS_DIV(dividers.post_div); 3838c2ecf20Sopenharmony_ci WREG32_SMC(GFX_POWER_GATING_CNTL, value); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci r600_calculate_u_and_p(500, xclk, 16, &p, &u); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci WREG32(CG_PG_CTRL, SP(p) | SU(u)); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci /* XXX double check hw_rev */ 3928c2ecf20Sopenharmony_ci if (pi->override_dynamic_mgpg && (hw_rev == 0)) 3938c2ecf20Sopenharmony_ci trinity_override_dynamic_mg_powergating(rdev); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci#define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF 3988c2ecf20Sopenharmony_ci#define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE 3998c2ecf20Sopenharmony_ci#define CGTS_SM_CTRL_REG_DISABLE 0x00600000 4008c2ecf20Sopenharmony_ci#define CGTS_SM_CTRL_REG_ENABLE 0x96944200 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic void trinity_mg_clockgating_enable(struct radeon_device *rdev, 4038c2ecf20Sopenharmony_ci bool enable) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci u32 local0; 4068c2ecf20Sopenharmony_ci u32 local1; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (enable) { 4098c2ecf20Sopenharmony_ci local0 = RREG32_CG(CG_CGTT_LOCAL_0); 4108c2ecf20Sopenharmony_ci local1 = RREG32_CG(CG_CGTT_LOCAL_1); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_0, 4138c2ecf20Sopenharmony_ci (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 4148c2ecf20Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_1, 4158c2ecf20Sopenharmony_ci (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE); 4188c2ecf20Sopenharmony_ci } else { 4198c2ecf20Sopenharmony_ci WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE); 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci local0 = RREG32_CG(CG_CGTT_LOCAL_0); 4228c2ecf20Sopenharmony_ci local1 = RREG32_CG(CG_CGTT_LOCAL_1); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_0, 4258c2ecf20Sopenharmony_ci CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 4268c2ecf20Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_1, 4278c2ecf20Sopenharmony_ci CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci} 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cistatic void trinity_mg_clockgating_initialize(struct radeon_device *rdev) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci u32 count; 4348c2ecf20Sopenharmony_ci const u32 *seq = NULL; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci seq = &trinity_mgcg_shls_default[0]; 4378c2ecf20Sopenharmony_ci count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32)); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci trinity_program_clk_gating_hw_sequence(rdev, seq, count); 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic void trinity_gfx_clockgating_enable(struct radeon_device *rdev, 4438c2ecf20Sopenharmony_ci bool enable) 4448c2ecf20Sopenharmony_ci{ 4458c2ecf20Sopenharmony_ci if (enable) { 4468c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); 4478c2ecf20Sopenharmony_ci } else { 4488c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); 4498c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON); 4508c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON); 4518c2ecf20Sopenharmony_ci RREG32(GB_ADDR_CONFIG); 4528c2ecf20Sopenharmony_ci } 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev, 4568c2ecf20Sopenharmony_ci const u32 *seq, u32 count) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci u32 i, length = count * 3; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci for (i = 0; i < length; i += 3) 4618c2ecf20Sopenharmony_ci WREG32_P(seq[i], seq[i+1], ~seq[i+2]); 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic void trinity_program_override_mgpg_sequences(struct radeon_device *rdev, 4658c2ecf20Sopenharmony_ci const u32 *seq, u32 count) 4668c2ecf20Sopenharmony_ci{ 4678c2ecf20Sopenharmony_ci u32 i, length = count * 2; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci for (i = 0; i < length; i += 2) 4708c2ecf20Sopenharmony_ci WREG32(seq[i], seq[i+1]); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci u32 count; 4778c2ecf20Sopenharmony_ci const u32 *seq = NULL; 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci seq = &trinity_override_mgpg_sequences[0]; 4808c2ecf20Sopenharmony_ci count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32)); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci trinity_program_override_mgpg_sequences(rdev, seq, count); 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic void trinity_ls_clockgating_enable(struct radeon_device *rdev, 4868c2ecf20Sopenharmony_ci bool enable) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci u32 count; 4898c2ecf20Sopenharmony_ci const u32 *seq = NULL; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci if (enable) { 4928c2ecf20Sopenharmony_ci seq = &trinity_sysls_enable[0]; 4938c2ecf20Sopenharmony_ci count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32)); 4948c2ecf20Sopenharmony_ci } else { 4958c2ecf20Sopenharmony_ci seq = &trinity_sysls_disable[0]; 4968c2ecf20Sopenharmony_ci count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32)); 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci trinity_program_clk_gating_hw_sequence(rdev, seq, count); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistatic void trinity_gfx_powergating_enable(struct radeon_device *rdev, 5038c2ecf20Sopenharmony_ci bool enable) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci if (enable) { 5068c2ecf20Sopenharmony_ci if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK) 5078c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01)); 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN); 5108c2ecf20Sopenharmony_ci } else { 5118c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN); 5128c2ecf20Sopenharmony_ci RREG32(GB_ADDR_CONFIG); 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev, 5178c2ecf20Sopenharmony_ci bool enable) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci u32 value; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci if (enable) { 5228c2ecf20Sopenharmony_ci value = RREG32_SMC(PM_I_CNTL_1); 5238c2ecf20Sopenharmony_ci value &= ~DS_PG_CNTL_MASK; 5248c2ecf20Sopenharmony_ci value |= DS_PG_CNTL(1); 5258c2ecf20Sopenharmony_ci WREG32_SMC(PM_I_CNTL_1, value); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_S_PG_CNTL); 5288c2ecf20Sopenharmony_ci value &= ~DS_PG_EN_MASK; 5298c2ecf20Sopenharmony_ci value |= DS_PG_EN(1); 5308c2ecf20Sopenharmony_ci WREG32_SMC(SMU_S_PG_CNTL, value); 5318c2ecf20Sopenharmony_ci } else { 5328c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_S_PG_CNTL); 5338c2ecf20Sopenharmony_ci value &= ~DS_PG_EN_MASK; 5348c2ecf20Sopenharmony_ci WREG32_SMC(SMU_S_PG_CNTL, value); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci value = RREG32_SMC(PM_I_CNTL_1); 5378c2ecf20Sopenharmony_ci value &= ~DS_PG_CNTL_MASK; 5388c2ecf20Sopenharmony_ci WREG32_SMC(PM_I_CNTL_1, value); 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci trinity_gfx_dynamic_mgpg_config(rdev); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci} 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_cistatic void trinity_enable_clock_power_gating(struct radeon_device *rdev) 5468c2ecf20Sopenharmony_ci{ 5478c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (pi->enable_gfx_clock_gating) 5508c2ecf20Sopenharmony_ci sumo_gfx_clockgating_initialize(rdev); 5518c2ecf20Sopenharmony_ci if (pi->enable_mg_clock_gating) 5528c2ecf20Sopenharmony_ci trinity_mg_clockgating_initialize(rdev); 5538c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) 5548c2ecf20Sopenharmony_ci trinity_gfx_powergating_initialize(rdev); 5558c2ecf20Sopenharmony_ci if (pi->enable_mg_clock_gating) { 5568c2ecf20Sopenharmony_ci trinity_ls_clockgating_enable(rdev, true); 5578c2ecf20Sopenharmony_ci trinity_mg_clockgating_enable(rdev, true); 5588c2ecf20Sopenharmony_ci } 5598c2ecf20Sopenharmony_ci if (pi->enable_gfx_clock_gating) 5608c2ecf20Sopenharmony_ci trinity_gfx_clockgating_enable(rdev, true); 5618c2ecf20Sopenharmony_ci if (pi->enable_gfx_dynamic_mgpg) 5628c2ecf20Sopenharmony_ci trinity_gfx_dynamic_mgpg_enable(rdev, true); 5638c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) 5648c2ecf20Sopenharmony_ci trinity_gfx_powergating_enable(rdev, true); 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic void trinity_disable_clock_power_gating(struct radeon_device *rdev) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) 5728c2ecf20Sopenharmony_ci trinity_gfx_powergating_enable(rdev, false); 5738c2ecf20Sopenharmony_ci if (pi->enable_gfx_dynamic_mgpg) 5748c2ecf20Sopenharmony_ci trinity_gfx_dynamic_mgpg_enable(rdev, false); 5758c2ecf20Sopenharmony_ci if (pi->enable_gfx_clock_gating) 5768c2ecf20Sopenharmony_ci trinity_gfx_clockgating_enable(rdev, false); 5778c2ecf20Sopenharmony_ci if (pi->enable_mg_clock_gating) { 5788c2ecf20Sopenharmony_ci trinity_mg_clockgating_enable(rdev, false); 5798c2ecf20Sopenharmony_ci trinity_ls_clockgating_enable(rdev, false); 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cistatic void trinity_set_divider_value(struct radeon_device *rdev, 5848c2ecf20Sopenharmony_ci u32 index, u32 sclk) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci struct atom_clock_dividers dividers; 5878c2ecf20Sopenharmony_ci int ret; 5888c2ecf20Sopenharmony_ci u32 value; 5898c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 5928c2ecf20Sopenharmony_ci sclk, false, ÷rs); 5938c2ecf20Sopenharmony_ci if (ret) 5948c2ecf20Sopenharmony_ci return; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 5978c2ecf20Sopenharmony_ci value &= ~CLK_DIVIDER_MASK; 5988c2ecf20Sopenharmony_ci value |= CLK_DIVIDER(dividers.post_div); 5998c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 6028c2ecf20Sopenharmony_ci sclk/2, false, ÷rs); 6038c2ecf20Sopenharmony_ci if (ret) 6048c2ecf20Sopenharmony_ci return; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix); 6078c2ecf20Sopenharmony_ci value &= ~PD_SCLK_DIVIDER_MASK; 6088c2ecf20Sopenharmony_ci value |= PD_SCLK_DIVIDER(dividers.post_div); 6098c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value); 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cistatic void trinity_set_ds_dividers(struct radeon_device *rdev, 6138c2ecf20Sopenharmony_ci u32 index, u32 divider) 6148c2ecf20Sopenharmony_ci{ 6158c2ecf20Sopenharmony_ci u32 value; 6168c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 6198c2ecf20Sopenharmony_ci value &= ~DS_DIV_MASK; 6208c2ecf20Sopenharmony_ci value |= DS_DIV(divider); 6218c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_cistatic void trinity_set_ss_dividers(struct radeon_device *rdev, 6258c2ecf20Sopenharmony_ci u32 index, u32 divider) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci u32 value; 6288c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 6318c2ecf20Sopenharmony_ci value &= ~DS_SH_DIV_MASK; 6328c2ecf20Sopenharmony_ci value |= DS_SH_DIV(divider); 6338c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 6398c2ecf20Sopenharmony_ci u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid); 6408c2ecf20Sopenharmony_ci u32 value; 6418c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 6448c2ecf20Sopenharmony_ci value &= ~VID_MASK; 6458c2ecf20Sopenharmony_ci value |= VID(vid_7bit); 6468c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 6498c2ecf20Sopenharmony_ci value &= ~LVRT_MASK; 6508c2ecf20Sopenharmony_ci value |= LVRT(0); 6518c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 6528c2ecf20Sopenharmony_ci} 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_cistatic void trinity_set_allos_gnb_slow(struct radeon_device *rdev, 6558c2ecf20Sopenharmony_ci u32 index, u32 gnb_slow) 6568c2ecf20Sopenharmony_ci{ 6578c2ecf20Sopenharmony_ci u32 value; 6588c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix); 6618c2ecf20Sopenharmony_ci value &= ~GNB_SLOW_MASK; 6628c2ecf20Sopenharmony_ci value |= GNB_SLOW(gnb_slow); 6638c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value); 6648c2ecf20Sopenharmony_ci} 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_cistatic void trinity_set_force_nbp_state(struct radeon_device *rdev, 6678c2ecf20Sopenharmony_ci u32 index, u32 force_nbp_state) 6688c2ecf20Sopenharmony_ci{ 6698c2ecf20Sopenharmony_ci u32 value; 6708c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix); 6738c2ecf20Sopenharmony_ci value &= ~FORCE_NBPS1_MASK; 6748c2ecf20Sopenharmony_ci value |= FORCE_NBPS1(force_nbp_state); 6758c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value); 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_cistatic void trinity_set_display_wm(struct radeon_device *rdev, 6798c2ecf20Sopenharmony_ci u32 index, u32 wm) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci u32 value; 6828c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 6858c2ecf20Sopenharmony_ci value &= ~DISPLAY_WM_MASK; 6868c2ecf20Sopenharmony_ci value |= DISPLAY_WM(wm); 6878c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 6888c2ecf20Sopenharmony_ci} 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_cistatic void trinity_set_vce_wm(struct radeon_device *rdev, 6918c2ecf20Sopenharmony_ci u32 index, u32 wm) 6928c2ecf20Sopenharmony_ci{ 6938c2ecf20Sopenharmony_ci u32 value; 6948c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 6978c2ecf20Sopenharmony_ci value &= ~VCE_WM_MASK; 6988c2ecf20Sopenharmony_ci value |= VCE_WM(wm); 6998c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 7008c2ecf20Sopenharmony_ci} 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_cistatic void trinity_set_at(struct radeon_device *rdev, 7038c2ecf20Sopenharmony_ci u32 index, u32 at) 7048c2ecf20Sopenharmony_ci{ 7058c2ecf20Sopenharmony_ci u32 value; 7068c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix); 7098c2ecf20Sopenharmony_ci value &= ~AT_MASK; 7108c2ecf20Sopenharmony_ci value |= AT(at); 7118c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value); 7128c2ecf20Sopenharmony_ci} 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_cistatic void trinity_program_power_level(struct radeon_device *rdev, 7158c2ecf20Sopenharmony_ci struct trinity_pl *pl, u32 index) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci if (index >= SUMO_MAX_HARDWARE_POWERLEVELS) 7208c2ecf20Sopenharmony_ci return; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci trinity_set_divider_value(rdev, index, pl->sclk); 7238c2ecf20Sopenharmony_ci trinity_set_vid(rdev, index, pl->vddc_index); 7248c2ecf20Sopenharmony_ci trinity_set_ss_dividers(rdev, index, pl->ss_divider_index); 7258c2ecf20Sopenharmony_ci trinity_set_ds_dividers(rdev, index, pl->ds_divider_index); 7268c2ecf20Sopenharmony_ci trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow); 7278c2ecf20Sopenharmony_ci trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state); 7288c2ecf20Sopenharmony_ci trinity_set_display_wm(rdev, index, pl->display_wm); 7298c2ecf20Sopenharmony_ci trinity_set_vce_wm(rdev, index, pl->vce_wm); 7308c2ecf20Sopenharmony_ci trinity_set_at(rdev, index, pi->at[index]); 7318c2ecf20Sopenharmony_ci} 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_cistatic void trinity_power_level_enable_disable(struct radeon_device *rdev, 7348c2ecf20Sopenharmony_ci u32 index, bool enable) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci u32 value; 7378c2ecf20Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 7408c2ecf20Sopenharmony_ci value &= ~STATE_VALID_MASK; 7418c2ecf20Sopenharmony_ci if (enable) 7428c2ecf20Sopenharmony_ci value |= STATE_VALID(1); 7438c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_cistatic bool trinity_dpm_enabled(struct radeon_device *rdev) 7478c2ecf20Sopenharmony_ci{ 7488c2ecf20Sopenharmony_ci if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1)) 7498c2ecf20Sopenharmony_ci return true; 7508c2ecf20Sopenharmony_ci else 7518c2ecf20Sopenharmony_ci return false; 7528c2ecf20Sopenharmony_ci} 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_cistatic void trinity_start_dpm(struct radeon_device *rdev) 7558c2ecf20Sopenharmony_ci{ 7568c2ecf20Sopenharmony_ci u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK); 7598c2ecf20Sopenharmony_ci value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1); 7608c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_CNTL, value); 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); 7638c2ecf20Sopenharmony_ci WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN); 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci trinity_dpm_config(rdev, true); 7668c2ecf20Sopenharmony_ci} 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_cistatic void trinity_wait_for_dpm_enabled(struct radeon_device *rdev) 7698c2ecf20Sopenharmony_ci{ 7708c2ecf20Sopenharmony_ci int i; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 7738c2ecf20Sopenharmony_ci if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN) 7748c2ecf20Sopenharmony_ci break; 7758c2ecf20Sopenharmony_ci udelay(1); 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 7788c2ecf20Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0) 7798c2ecf20Sopenharmony_ci break; 7808c2ecf20Sopenharmony_ci udelay(1); 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 7838c2ecf20Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0) 7848c2ecf20Sopenharmony_ci break; 7858c2ecf20Sopenharmony_ci udelay(1); 7868c2ecf20Sopenharmony_ci } 7878c2ecf20Sopenharmony_ci} 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_cistatic void trinity_stop_dpm(struct radeon_device *rdev) 7908c2ecf20Sopenharmony_ci{ 7918c2ecf20Sopenharmony_ci u32 sclk_dpm_cntl; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL); 7968c2ecf20Sopenharmony_ci sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK); 7978c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl); 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci trinity_dpm_config(rdev, false); 8008c2ecf20Sopenharmony_ci} 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_cistatic void trinity_start_am(struct radeon_device *rdev) 8038c2ecf20Sopenharmony_ci{ 8048c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT)); 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic void trinity_reset_am(struct radeon_device *rdev) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT, 8108c2ecf20Sopenharmony_ci ~(RESET_SCLK_CNT | RESET_BUSY_CNT)); 8118c2ecf20Sopenharmony_ci} 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_cistatic void trinity_wait_for_level_0(struct radeon_device *rdev) 8148c2ecf20Sopenharmony_ci{ 8158c2ecf20Sopenharmony_ci int i; 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 8188c2ecf20Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0) 8198c2ecf20Sopenharmony_ci break; 8208c2ecf20Sopenharmony_ci udelay(1); 8218c2ecf20Sopenharmony_ci } 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_cistatic void trinity_enable_power_level_0(struct radeon_device *rdev) 8258c2ecf20Sopenharmony_ci{ 8268c2ecf20Sopenharmony_ci trinity_power_level_enable_disable(rdev, 0, true); 8278c2ecf20Sopenharmony_ci} 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic void trinity_force_level_0(struct radeon_device *rdev) 8308c2ecf20Sopenharmony_ci{ 8318c2ecf20Sopenharmony_ci trinity_dpm_force_state(rdev, 0); 8328c2ecf20Sopenharmony_ci} 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_cistatic void trinity_unforce_levels(struct radeon_device *rdev) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci trinity_dpm_no_forced_level(rdev); 8378c2ecf20Sopenharmony_ci} 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_cistatic void trinity_program_power_levels_0_to_n(struct radeon_device *rdev, 8408c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 8418c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 8428c2ecf20Sopenharmony_ci{ 8438c2ecf20Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(new_rps); 8448c2ecf20Sopenharmony_ci struct trinity_ps *old_ps = trinity_get_ps(old_rps); 8458c2ecf20Sopenharmony_ci u32 i; 8468c2ecf20Sopenharmony_ci u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci for (i = 0; i < new_ps->num_levels; i++) { 8498c2ecf20Sopenharmony_ci trinity_program_power_level(rdev, &new_ps->levels[i], i); 8508c2ecf20Sopenharmony_ci trinity_power_level_enable_disable(rdev, i, true); 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci for (i = new_ps->num_levels; i < n_current_state_levels; i++) 8548c2ecf20Sopenharmony_ci trinity_power_level_enable_disable(rdev, i, false); 8558c2ecf20Sopenharmony_ci} 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_cistatic void trinity_program_bootup_state(struct radeon_device *rdev) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 8608c2ecf20Sopenharmony_ci u32 i; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci trinity_program_power_level(rdev, &pi->boot_pl, 0); 8638c2ecf20Sopenharmony_ci trinity_power_level_enable_disable(rdev, 0, true); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci for (i = 1; i < 8; i++) 8668c2ecf20Sopenharmony_ci trinity_power_level_enable_disable(rdev, i, false); 8678c2ecf20Sopenharmony_ci} 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_cistatic void trinity_setup_uvd_clock_table(struct radeon_device *rdev, 8708c2ecf20Sopenharmony_ci struct radeon_ps *rps) 8718c2ecf20Sopenharmony_ci{ 8728c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 8738c2ecf20Sopenharmony_ci u32 uvdstates = (ps->vclk_low_divider | 8748c2ecf20Sopenharmony_ci ps->vclk_high_divider << 8 | 8758c2ecf20Sopenharmony_ci ps->dclk_low_divider << 16 | 8768c2ecf20Sopenharmony_ci ps->dclk_high_divider << 24); 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates); 8798c2ecf20Sopenharmony_ci} 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_cistatic void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev, 8828c2ecf20Sopenharmony_ci u32 interval) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci u32 p, u; 8858c2ecf20Sopenharmony_ci u32 tp = RREG32_SMC(PM_TP); 8868c2ecf20Sopenharmony_ci u32 val; 8878c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci r600_calculate_u_and_p(interval, xclk, 16, &p, &u); 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci val = (p + tp - 1) / tp; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci WREG32_SMC(SMU_UVD_DPM_CNTL, val); 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic bool trinity_uvd_clocks_zero(struct radeon_ps *rps) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci if ((rps->vclk == 0) && (rps->dclk == 0)) 8998c2ecf20Sopenharmony_ci return true; 9008c2ecf20Sopenharmony_ci else 9018c2ecf20Sopenharmony_ci return false; 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_cistatic bool trinity_uvd_clocks_equal(struct radeon_ps *rps1, 9058c2ecf20Sopenharmony_ci struct radeon_ps *rps2) 9068c2ecf20Sopenharmony_ci{ 9078c2ecf20Sopenharmony_ci struct trinity_ps *ps1 = trinity_get_ps(rps1); 9088c2ecf20Sopenharmony_ci struct trinity_ps *ps2 = trinity_get_ps(rps2); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci if ((rps1->vclk == rps2->vclk) && 9118c2ecf20Sopenharmony_ci (rps1->dclk == rps2->dclk) && 9128c2ecf20Sopenharmony_ci (ps1->vclk_low_divider == ps2->vclk_low_divider) && 9138c2ecf20Sopenharmony_ci (ps1->vclk_high_divider == ps2->vclk_high_divider) && 9148c2ecf20Sopenharmony_ci (ps1->dclk_low_divider == ps2->dclk_low_divider) && 9158c2ecf20Sopenharmony_ci (ps1->dclk_high_divider == ps2->dclk_high_divider)) 9168c2ecf20Sopenharmony_ci return true; 9178c2ecf20Sopenharmony_ci else 9188c2ecf20Sopenharmony_ci return false; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_cistatic void trinity_setup_uvd_clocks(struct radeon_device *rdev, 9228c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 9238c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) { 9288c2ecf20Sopenharmony_ci trinity_gfx_powergating_enable(rdev, false); 9298c2ecf20Sopenharmony_ci } 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci if (pi->uvd_dpm) { 9328c2ecf20Sopenharmony_ci if (trinity_uvd_clocks_zero(new_rps) && 9338c2ecf20Sopenharmony_ci !trinity_uvd_clocks_zero(old_rps)) { 9348c2ecf20Sopenharmony_ci trinity_setup_uvd_dpm_interval(rdev, 0); 9358c2ecf20Sopenharmony_ci } else if (!trinity_uvd_clocks_zero(new_rps)) { 9368c2ecf20Sopenharmony_ci trinity_setup_uvd_clock_table(rdev, new_rps); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (trinity_uvd_clocks_zero(old_rps)) { 9398c2ecf20Sopenharmony_ci u32 tmp = RREG32(CG_MISC_REG); 9408c2ecf20Sopenharmony_ci tmp &= 0xfffffffd; 9418c2ecf20Sopenharmony_ci WREG32(CG_MISC_REG, tmp); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci trinity_setup_uvd_dpm_interval(rdev, 3000); 9468c2ecf20Sopenharmony_ci } 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci trinity_uvd_dpm_config(rdev); 9498c2ecf20Sopenharmony_ci } else { 9508c2ecf20Sopenharmony_ci if (trinity_uvd_clocks_zero(new_rps) || 9518c2ecf20Sopenharmony_ci trinity_uvd_clocks_equal(new_rps, old_rps)) 9528c2ecf20Sopenharmony_ci return; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk); 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci if (pi->enable_gfx_power_gating) { 9588c2ecf20Sopenharmony_ci trinity_gfx_powergating_enable(rdev, true); 9598c2ecf20Sopenharmony_ci } 9608c2ecf20Sopenharmony_ci} 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_cistatic void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev, 9638c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 9648c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 9658c2ecf20Sopenharmony_ci{ 9668c2ecf20Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(new_rps); 9678c2ecf20Sopenharmony_ci struct trinity_ps *current_ps = trinity_get_ps(new_rps); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (new_ps->levels[new_ps->num_levels - 1].sclk >= 9708c2ecf20Sopenharmony_ci current_ps->levels[current_ps->num_levels - 1].sclk) 9718c2ecf20Sopenharmony_ci return; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci trinity_setup_uvd_clocks(rdev, new_rps, old_rps); 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, 9778c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 9788c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(new_rps); 9818c2ecf20Sopenharmony_ci struct trinity_ps *current_ps = trinity_get_ps(old_rps); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci if (new_ps->levels[new_ps->num_levels - 1].sclk < 9848c2ecf20Sopenharmony_ci current_ps->levels[current_ps->num_levels - 1].sclk) 9858c2ecf20Sopenharmony_ci return; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci trinity_setup_uvd_clocks(rdev, new_rps, old_rps); 9888c2ecf20Sopenharmony_ci} 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_cistatic void trinity_set_vce_clock(struct radeon_device *rdev, 9918c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 9928c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 9938c2ecf20Sopenharmony_ci{ 9948c2ecf20Sopenharmony_ci if ((old_rps->evclk != new_rps->evclk) || 9958c2ecf20Sopenharmony_ci (old_rps->ecclk != new_rps->ecclk)) { 9968c2ecf20Sopenharmony_ci /* turn the clocks on when encoding, off otherwise */ 9978c2ecf20Sopenharmony_ci if (new_rps->evclk || new_rps->ecclk) 9988c2ecf20Sopenharmony_ci vce_v1_0_enable_mgcg(rdev, false); 9998c2ecf20Sopenharmony_ci else 10008c2ecf20Sopenharmony_ci vce_v1_0_enable_mgcg(rdev, true); 10018c2ecf20Sopenharmony_ci radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk); 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_cistatic void trinity_program_ttt(struct radeon_device *rdev) 10068c2ecf20Sopenharmony_ci{ 10078c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 10088c2ecf20Sopenharmony_ci u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci value &= ~(HT_MASK | LT_MASK); 10118c2ecf20Sopenharmony_ci value |= HT((pi->thermal_auto_throttling + 49) * 8); 10128c2ecf20Sopenharmony_ci value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8); 10138c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_TTT, value); 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_cistatic void trinity_enable_att(struct radeon_device *rdev) 10178c2ecf20Sopenharmony_ci{ 10188c2ecf20Sopenharmony_ci u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci value &= ~SCLK_TT_EN_MASK; 10218c2ecf20Sopenharmony_ci value |= SCLK_TT_EN(1); 10228c2ecf20Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value); 10238c2ecf20Sopenharmony_ci} 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_cistatic void trinity_program_sclk_dpm(struct radeon_device *rdev) 10268c2ecf20Sopenharmony_ci{ 10278c2ecf20Sopenharmony_ci u32 p, u; 10288c2ecf20Sopenharmony_ci u32 tp = RREG32_SMC(PM_TP); 10298c2ecf20Sopenharmony_ci u32 ni; 10308c2ecf20Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 10318c2ecf20Sopenharmony_ci u32 value; 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci r600_calculate_u_and_p(400, xclk, 16, &p, &u); 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci ni = (p + tp - 1) / tp; 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci value = RREG32_SMC(PM_I_CNTL_1); 10388c2ecf20Sopenharmony_ci value &= ~SCLK_DPM_MASK; 10398c2ecf20Sopenharmony_ci value |= SCLK_DPM(ni); 10408c2ecf20Sopenharmony_ci WREG32_SMC(PM_I_CNTL_1, value); 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_cistatic int trinity_set_thermal_temperature_range(struct radeon_device *rdev, 10448c2ecf20Sopenharmony_ci int min_temp, int max_temp) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci int low_temp = 0 * 1000; 10478c2ecf20Sopenharmony_ci int high_temp = 255 * 1000; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci if (low_temp < min_temp) 10508c2ecf20Sopenharmony_ci low_temp = min_temp; 10518c2ecf20Sopenharmony_ci if (high_temp > max_temp) 10528c2ecf20Sopenharmony_ci high_temp = max_temp; 10538c2ecf20Sopenharmony_ci if (high_temp < low_temp) { 10548c2ecf20Sopenharmony_ci DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); 10558c2ecf20Sopenharmony_ci return -EINVAL; 10568c2ecf20Sopenharmony_ci } 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK); 10598c2ecf20Sopenharmony_ci WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.min_temp = low_temp; 10628c2ecf20Sopenharmony_ci rdev->pm.dpm.thermal.max_temp = high_temp; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci return 0; 10658c2ecf20Sopenharmony_ci} 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_cistatic void trinity_update_current_ps(struct radeon_device *rdev, 10688c2ecf20Sopenharmony_ci struct radeon_ps *rps) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(rps); 10718c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci pi->current_rps = *rps; 10748c2ecf20Sopenharmony_ci pi->current_ps = *new_ps; 10758c2ecf20Sopenharmony_ci pi->current_rps.ps_priv = &pi->current_ps; 10768c2ecf20Sopenharmony_ci} 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_cistatic void trinity_update_requested_ps(struct radeon_device *rdev, 10798c2ecf20Sopenharmony_ci struct radeon_ps *rps) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(rps); 10828c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci pi->requested_rps = *rps; 10858c2ecf20Sopenharmony_ci pi->requested_ps = *new_ps; 10868c2ecf20Sopenharmony_ci pi->requested_rps.ps_priv = &pi->requested_ps; 10878c2ecf20Sopenharmony_ci} 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_civoid trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable) 10908c2ecf20Sopenharmony_ci{ 10918c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci if (pi->enable_bapm) { 10948c2ecf20Sopenharmony_ci trinity_acquire_mutex(rdev); 10958c2ecf20Sopenharmony_ci trinity_dpm_bapm_enable(rdev, enable); 10968c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci} 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ciint trinity_dpm_enable(struct radeon_device *rdev) 11018c2ecf20Sopenharmony_ci{ 11028c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci trinity_acquire_mutex(rdev); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (trinity_dpm_enabled(rdev)) { 11078c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 11088c2ecf20Sopenharmony_ci return -EINVAL; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci trinity_program_bootup_state(rdev); 11128c2ecf20Sopenharmony_ci sumo_program_vc(rdev, 0x00C00033); 11138c2ecf20Sopenharmony_ci trinity_start_am(rdev); 11148c2ecf20Sopenharmony_ci if (pi->enable_auto_thermal_throttling) { 11158c2ecf20Sopenharmony_ci trinity_program_ttt(rdev); 11168c2ecf20Sopenharmony_ci trinity_enable_att(rdev); 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci trinity_program_sclk_dpm(rdev); 11198c2ecf20Sopenharmony_ci trinity_start_dpm(rdev); 11208c2ecf20Sopenharmony_ci trinity_wait_for_dpm_enabled(rdev); 11218c2ecf20Sopenharmony_ci trinity_dpm_bapm_enable(rdev, false); 11228c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci return 0; 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ciint trinity_dpm_late_enable(struct radeon_device *rdev) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci int ret; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci trinity_acquire_mutex(rdev); 11348c2ecf20Sopenharmony_ci trinity_enable_clock_power_gating(rdev); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (rdev->irq.installed && 11378c2ecf20Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 11388c2ecf20Sopenharmony_ci ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 11398c2ecf20Sopenharmony_ci if (ret) { 11408c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 11418c2ecf20Sopenharmony_ci return ret; 11428c2ecf20Sopenharmony_ci } 11438c2ecf20Sopenharmony_ci rdev->irq.dpm_thermal = true; 11448c2ecf20Sopenharmony_ci radeon_irq_set(rdev); 11458c2ecf20Sopenharmony_ci } 11468c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci return 0; 11498c2ecf20Sopenharmony_ci} 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_civoid trinity_dpm_disable(struct radeon_device *rdev) 11528c2ecf20Sopenharmony_ci{ 11538c2ecf20Sopenharmony_ci trinity_acquire_mutex(rdev); 11548c2ecf20Sopenharmony_ci if (!trinity_dpm_enabled(rdev)) { 11558c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 11568c2ecf20Sopenharmony_ci return; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci trinity_dpm_bapm_enable(rdev, false); 11598c2ecf20Sopenharmony_ci trinity_disable_clock_power_gating(rdev); 11608c2ecf20Sopenharmony_ci sumo_clear_vc(rdev); 11618c2ecf20Sopenharmony_ci trinity_wait_for_level_0(rdev); 11628c2ecf20Sopenharmony_ci trinity_stop_dpm(rdev); 11638c2ecf20Sopenharmony_ci trinity_reset_am(rdev); 11648c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (rdev->irq.installed && 11678c2ecf20Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 11688c2ecf20Sopenharmony_ci rdev->irq.dpm_thermal = false; 11698c2ecf20Sopenharmony_ci radeon_irq_set(rdev); 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 11738c2ecf20Sopenharmony_ci} 11748c2ecf20Sopenharmony_ci 11758c2ecf20Sopenharmony_cistatic void trinity_get_min_sclk_divider(struct radeon_device *rdev) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci pi->min_sclk_did = 11808c2ecf20Sopenharmony_ci (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT; 11818c2ecf20Sopenharmony_ci} 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_cistatic void trinity_setup_nbp_sim(struct radeon_device *rdev, 11848c2ecf20Sopenharmony_ci struct radeon_ps *rps) 11858c2ecf20Sopenharmony_ci{ 11868c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 11878c2ecf20Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(rps); 11888c2ecf20Sopenharmony_ci u32 nbpsconfig; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci if (pi->sys_info.nb_dpm_enable) { 11918c2ecf20Sopenharmony_ci nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG); 11928c2ecf20Sopenharmony_ci nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK); 11938c2ecf20Sopenharmony_ci nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) | 11948c2ecf20Sopenharmony_ci Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) | 11958c2ecf20Sopenharmony_ci DpmXNbPsLo(new_ps->DpmXNbPsLo) | 11968c2ecf20Sopenharmony_ci DpmXNbPsHi(new_ps->DpmXNbPsHi)); 11978c2ecf20Sopenharmony_ci WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig); 11988c2ecf20Sopenharmony_ci } 11998c2ecf20Sopenharmony_ci} 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ciint trinity_dpm_force_performance_level(struct radeon_device *rdev, 12028c2ecf20Sopenharmony_ci enum radeon_dpm_forced_level level) 12038c2ecf20Sopenharmony_ci{ 12048c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 12058c2ecf20Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 12068c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 12078c2ecf20Sopenharmony_ci int i, ret; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci if (ps->num_levels <= 1) 12108c2ecf20Sopenharmony_ci return 0; 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { 12138c2ecf20Sopenharmony_ci /* not supported by the hw */ 12148c2ecf20Sopenharmony_ci return -EINVAL; 12158c2ecf20Sopenharmony_ci } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { 12168c2ecf20Sopenharmony_ci ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1); 12178c2ecf20Sopenharmony_ci if (ret) 12188c2ecf20Sopenharmony_ci return ret; 12198c2ecf20Sopenharmony_ci } else { 12208c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 12218c2ecf20Sopenharmony_ci ret = trinity_dpm_n_levels_disabled(rdev, 0); 12228c2ecf20Sopenharmony_ci if (ret) 12238c2ecf20Sopenharmony_ci return ret; 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci } 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci rdev->pm.dpm.forced_level = level; 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci return 0; 12308c2ecf20Sopenharmony_ci} 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ciint trinity_dpm_pre_set_power_state(struct radeon_device *rdev) 12338c2ecf20Sopenharmony_ci{ 12348c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 12358c2ecf20Sopenharmony_ci struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps; 12368c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &requested_ps; 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci trinity_update_requested_ps(rdev, new_ps); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci trinity_apply_state_adjust_rules(rdev, 12418c2ecf20Sopenharmony_ci &pi->requested_rps, 12428c2ecf20Sopenharmony_ci &pi->current_rps); 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci return 0; 12458c2ecf20Sopenharmony_ci} 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ciint trinity_dpm_set_power_state(struct radeon_device *rdev) 12488c2ecf20Sopenharmony_ci{ 12498c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 12508c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 12518c2ecf20Sopenharmony_ci struct radeon_ps *old_ps = &pi->current_rps; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci trinity_acquire_mutex(rdev); 12548c2ecf20Sopenharmony_ci if (pi->enable_dpm) { 12558c2ecf20Sopenharmony_ci if (pi->enable_bapm) 12568c2ecf20Sopenharmony_ci trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power); 12578c2ecf20Sopenharmony_ci trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); 12588c2ecf20Sopenharmony_ci trinity_enable_power_level_0(rdev); 12598c2ecf20Sopenharmony_ci trinity_force_level_0(rdev); 12608c2ecf20Sopenharmony_ci trinity_wait_for_level_0(rdev); 12618c2ecf20Sopenharmony_ci trinity_setup_nbp_sim(rdev, new_ps); 12628c2ecf20Sopenharmony_ci trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps); 12638c2ecf20Sopenharmony_ci trinity_force_level_0(rdev); 12648c2ecf20Sopenharmony_ci trinity_unforce_levels(rdev); 12658c2ecf20Sopenharmony_ci trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 12668c2ecf20Sopenharmony_ci trinity_set_vce_clock(rdev, new_ps, old_ps); 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci return 0; 12718c2ecf20Sopenharmony_ci} 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_civoid trinity_dpm_post_set_power_state(struct radeon_device *rdev) 12748c2ecf20Sopenharmony_ci{ 12758c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 12768c2ecf20Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci trinity_update_current_ps(rdev, new_ps); 12798c2ecf20Sopenharmony_ci} 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_civoid trinity_dpm_setup_asic(struct radeon_device *rdev) 12828c2ecf20Sopenharmony_ci{ 12838c2ecf20Sopenharmony_ci trinity_acquire_mutex(rdev); 12848c2ecf20Sopenharmony_ci sumo_program_sstp(rdev); 12858c2ecf20Sopenharmony_ci sumo_take_smu_control(rdev, true); 12868c2ecf20Sopenharmony_ci trinity_get_min_sclk_divider(rdev); 12878c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 12888c2ecf20Sopenharmony_ci} 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci#if 0 12918c2ecf20Sopenharmony_civoid trinity_dpm_reset_asic(struct radeon_device *rdev) 12928c2ecf20Sopenharmony_ci{ 12938c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci trinity_acquire_mutex(rdev); 12968c2ecf20Sopenharmony_ci if (pi->enable_dpm) { 12978c2ecf20Sopenharmony_ci trinity_enable_power_level_0(rdev); 12988c2ecf20Sopenharmony_ci trinity_force_level_0(rdev); 12998c2ecf20Sopenharmony_ci trinity_wait_for_level_0(rdev); 13008c2ecf20Sopenharmony_ci trinity_program_bootup_state(rdev); 13018c2ecf20Sopenharmony_ci trinity_force_level_0(rdev); 13028c2ecf20Sopenharmony_ci trinity_unforce_levels(rdev); 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci trinity_release_mutex(rdev); 13058c2ecf20Sopenharmony_ci} 13068c2ecf20Sopenharmony_ci#endif 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_cistatic u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev, 13098c2ecf20Sopenharmony_ci u32 vid_2bit) 13108c2ecf20Sopenharmony_ci{ 13118c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 13128c2ecf20Sopenharmony_ci u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit); 13138c2ecf20Sopenharmony_ci u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0; 13148c2ecf20Sopenharmony_ci u32 step = (svi_mode == 0) ? 1250 : 625; 13158c2ecf20Sopenharmony_ci u32 delta = vid_7bit * step + 50; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci if (delta > 155000) 13188c2ecf20Sopenharmony_ci return 0; 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci return (155000 - delta) / 100; 13218c2ecf20Sopenharmony_ci} 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_cistatic void trinity_patch_boot_state(struct radeon_device *rdev, 13248c2ecf20Sopenharmony_ci struct trinity_ps *ps) 13258c2ecf20Sopenharmony_ci{ 13268c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci ps->num_levels = 1; 13298c2ecf20Sopenharmony_ci ps->nbps_flags = 0; 13308c2ecf20Sopenharmony_ci ps->bapm_flags = 0; 13318c2ecf20Sopenharmony_ci ps->levels[0] = pi->boot_pl; 13328c2ecf20Sopenharmony_ci} 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_cistatic u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk) 13358c2ecf20Sopenharmony_ci{ 13368c2ecf20Sopenharmony_ci if (sclk < 20000) 13378c2ecf20Sopenharmony_ci return 1; 13388c2ecf20Sopenharmony_ci return 0; 13398c2ecf20Sopenharmony_ci} 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_cistatic void trinity_construct_boot_state(struct radeon_device *rdev) 13428c2ecf20Sopenharmony_ci{ 13438c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci pi->boot_pl.sclk = pi->sys_info.bootup_sclk; 13468c2ecf20Sopenharmony_ci pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; 13478c2ecf20Sopenharmony_ci pi->boot_pl.ds_divider_index = 0; 13488c2ecf20Sopenharmony_ci pi->boot_pl.ss_divider_index = 0; 13498c2ecf20Sopenharmony_ci pi->boot_pl.allow_gnb_slow = 1; 13508c2ecf20Sopenharmony_ci pi->boot_pl.force_nbp_state = 0; 13518c2ecf20Sopenharmony_ci pi->boot_pl.display_wm = 0; 13528c2ecf20Sopenharmony_ci pi->boot_pl.vce_wm = 0; 13538c2ecf20Sopenharmony_ci pi->current_ps.num_levels = 1; 13548c2ecf20Sopenharmony_ci pi->current_ps.levels[0] = pi->boot_pl; 13558c2ecf20Sopenharmony_ci} 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_cistatic u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev, 13588c2ecf20Sopenharmony_ci u32 sclk, u32 min_sclk_in_sr) 13598c2ecf20Sopenharmony_ci{ 13608c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 13618c2ecf20Sopenharmony_ci u32 i; 13628c2ecf20Sopenharmony_ci u32 temp; 13638c2ecf20Sopenharmony_ci u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ? 13648c2ecf20Sopenharmony_ci min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci if (sclk < min) 13678c2ecf20Sopenharmony_ci return 0; 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci if (!pi->enable_sclk_ds) 13708c2ecf20Sopenharmony_ci return 0; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { 13738c2ecf20Sopenharmony_ci temp = sclk / sumo_get_sleep_divider_from_id(i); 13748c2ecf20Sopenharmony_ci if (temp >= min || i == 0) 13758c2ecf20Sopenharmony_ci break; 13768c2ecf20Sopenharmony_ci } 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci return (u8)i; 13798c2ecf20Sopenharmony_ci} 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_cistatic u32 trinity_get_valid_engine_clock(struct radeon_device *rdev, 13828c2ecf20Sopenharmony_ci u32 lower_limit) 13838c2ecf20Sopenharmony_ci{ 13848c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 13858c2ecf20Sopenharmony_ci u32 i; 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) { 13888c2ecf20Sopenharmony_ci if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit) 13898c2ecf20Sopenharmony_ci return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency; 13908c2ecf20Sopenharmony_ci } 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries) 13938c2ecf20Sopenharmony_ci DRM_ERROR("engine clock out of range!"); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci return 0; 13968c2ecf20Sopenharmony_ci} 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_cistatic void trinity_patch_thermal_state(struct radeon_device *rdev, 13998c2ecf20Sopenharmony_ci struct trinity_ps *ps, 14008c2ecf20Sopenharmony_ci struct trinity_ps *current_ps) 14018c2ecf20Sopenharmony_ci{ 14028c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 14038c2ecf20Sopenharmony_ci u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 14048c2ecf20Sopenharmony_ci u32 current_vddc; 14058c2ecf20Sopenharmony_ci u32 current_sclk; 14068c2ecf20Sopenharmony_ci u32 current_index = 0; 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci if (current_ps) { 14098c2ecf20Sopenharmony_ci current_vddc = current_ps->levels[current_index].vddc_index; 14108c2ecf20Sopenharmony_ci current_sclk = current_ps->levels[current_index].sclk; 14118c2ecf20Sopenharmony_ci } else { 14128c2ecf20Sopenharmony_ci current_vddc = pi->boot_pl.vddc_index; 14138c2ecf20Sopenharmony_ci current_sclk = pi->boot_pl.sclk; 14148c2ecf20Sopenharmony_ci } 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci ps->levels[0].vddc_index = current_vddc; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci if (ps->levels[0].sclk > current_sclk) 14198c2ecf20Sopenharmony_ci ps->levels[0].sclk = current_sclk; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci ps->levels[0].ds_divider_index = 14228c2ecf20Sopenharmony_ci trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr); 14238c2ecf20Sopenharmony_ci ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index; 14248c2ecf20Sopenharmony_ci ps->levels[0].allow_gnb_slow = 1; 14258c2ecf20Sopenharmony_ci ps->levels[0].force_nbp_state = 0; 14268c2ecf20Sopenharmony_ci ps->levels[0].display_wm = 0; 14278c2ecf20Sopenharmony_ci ps->levels[0].vce_wm = 14288c2ecf20Sopenharmony_ci trinity_calculate_vce_wm(rdev, ps->levels[0].sclk); 14298c2ecf20Sopenharmony_ci} 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_cistatic u8 trinity_calculate_display_wm(struct radeon_device *rdev, 14328c2ecf20Sopenharmony_ci struct trinity_ps *ps, u32 index) 14338c2ecf20Sopenharmony_ci{ 14348c2ecf20Sopenharmony_ci if (ps == NULL || ps->num_levels <= 1) 14358c2ecf20Sopenharmony_ci return 0; 14368c2ecf20Sopenharmony_ci else if (ps->num_levels == 2) { 14378c2ecf20Sopenharmony_ci if (index == 0) 14388c2ecf20Sopenharmony_ci return 0; 14398c2ecf20Sopenharmony_ci else 14408c2ecf20Sopenharmony_ci return 1; 14418c2ecf20Sopenharmony_ci } else { 14428c2ecf20Sopenharmony_ci if (index == 0) 14438c2ecf20Sopenharmony_ci return 0; 14448c2ecf20Sopenharmony_ci else if (ps->levels[index].sclk < 30000) 14458c2ecf20Sopenharmony_ci return 0; 14468c2ecf20Sopenharmony_ci else 14478c2ecf20Sopenharmony_ci return 1; 14488c2ecf20Sopenharmony_ci } 14498c2ecf20Sopenharmony_ci} 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_cistatic u32 trinity_get_uvd_clock_index(struct radeon_device *rdev, 14528c2ecf20Sopenharmony_ci struct radeon_ps *rps) 14538c2ecf20Sopenharmony_ci{ 14548c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 14558c2ecf20Sopenharmony_ci u32 i = 0; 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 14588c2ecf20Sopenharmony_ci if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) && 14598c2ecf20Sopenharmony_ci (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk)) 14608c2ecf20Sopenharmony_ci break; 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci if (i >= 4) { 14648c2ecf20Sopenharmony_ci DRM_ERROR("UVD clock index not found!\n"); 14658c2ecf20Sopenharmony_ci i = 3; 14668c2ecf20Sopenharmony_ci } 14678c2ecf20Sopenharmony_ci return i; 14688c2ecf20Sopenharmony_ci} 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_cistatic void trinity_adjust_uvd_state(struct radeon_device *rdev, 14718c2ecf20Sopenharmony_ci struct radeon_ps *rps) 14728c2ecf20Sopenharmony_ci{ 14738c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 14748c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 14758c2ecf20Sopenharmony_ci u32 high_index = 0; 14768c2ecf20Sopenharmony_ci u32 low_index = 0; 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) { 14798c2ecf20Sopenharmony_ci high_index = trinity_get_uvd_clock_index(rdev, rps); 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci switch(high_index) { 14828c2ecf20Sopenharmony_ci case 3: 14838c2ecf20Sopenharmony_ci case 2: 14848c2ecf20Sopenharmony_ci low_index = 1; 14858c2ecf20Sopenharmony_ci break; 14868c2ecf20Sopenharmony_ci case 1: 14878c2ecf20Sopenharmony_ci case 0: 14888c2ecf20Sopenharmony_ci default: 14898c2ecf20Sopenharmony_ci low_index = 0; 14908c2ecf20Sopenharmony_ci break; 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci ps->vclk_low_divider = 14948c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[high_index].vclk_did; 14958c2ecf20Sopenharmony_ci ps->dclk_low_divider = 14968c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[high_index].dclk_did; 14978c2ecf20Sopenharmony_ci ps->vclk_high_divider = 14988c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[low_index].vclk_did; 14998c2ecf20Sopenharmony_ci ps->dclk_high_divider = 15008c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[low_index].dclk_did; 15018c2ecf20Sopenharmony_ci } 15028c2ecf20Sopenharmony_ci} 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_cistatic int trinity_get_vce_clock_voltage(struct radeon_device *rdev, 15058c2ecf20Sopenharmony_ci u32 evclk, u32 ecclk, u16 *voltage) 15068c2ecf20Sopenharmony_ci{ 15078c2ecf20Sopenharmony_ci u32 i; 15088c2ecf20Sopenharmony_ci int ret = -EINVAL; 15098c2ecf20Sopenharmony_ci struct radeon_vce_clock_voltage_dependency_table *table = 15108c2ecf20Sopenharmony_ci &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci if (((evclk == 0) && (ecclk == 0)) || 15138c2ecf20Sopenharmony_ci (table && (table->count == 0))) { 15148c2ecf20Sopenharmony_ci *voltage = 0; 15158c2ecf20Sopenharmony_ci return 0; 15168c2ecf20Sopenharmony_ci } 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci for (i = 0; i < table->count; i++) { 15198c2ecf20Sopenharmony_ci if ((evclk <= table->entries[i].evclk) && 15208c2ecf20Sopenharmony_ci (ecclk <= table->entries[i].ecclk)) { 15218c2ecf20Sopenharmony_ci *voltage = table->entries[i].v; 15228c2ecf20Sopenharmony_ci ret = 0; 15238c2ecf20Sopenharmony_ci break; 15248c2ecf20Sopenharmony_ci } 15258c2ecf20Sopenharmony_ci } 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci /* if no match return the highest voltage */ 15288c2ecf20Sopenharmony_ci if (ret) 15298c2ecf20Sopenharmony_ci *voltage = table->entries[table->count - 1].v; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci return ret; 15328c2ecf20Sopenharmony_ci} 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_cistatic void trinity_apply_state_adjust_rules(struct radeon_device *rdev, 15358c2ecf20Sopenharmony_ci struct radeon_ps *new_rps, 15368c2ecf20Sopenharmony_ci struct radeon_ps *old_rps) 15378c2ecf20Sopenharmony_ci{ 15388c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(new_rps); 15398c2ecf20Sopenharmony_ci struct trinity_ps *current_ps = trinity_get_ps(old_rps); 15408c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 15418c2ecf20Sopenharmony_ci u32 min_voltage = 0; /* ??? */ 15428c2ecf20Sopenharmony_ci u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */ 15438c2ecf20Sopenharmony_ci u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 15448c2ecf20Sopenharmony_ci u32 i; 15458c2ecf20Sopenharmony_ci u16 min_vce_voltage; 15468c2ecf20Sopenharmony_ci bool force_high; 15478c2ecf20Sopenharmony_ci u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 15508c2ecf20Sopenharmony_ci return trinity_patch_thermal_state(rdev, ps, current_ps); 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci trinity_adjust_uvd_state(rdev, new_rps); 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci if (new_rps->vce_active) { 15558c2ecf20Sopenharmony_ci new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; 15568c2ecf20Sopenharmony_ci new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk; 15578c2ecf20Sopenharmony_ci } else { 15588c2ecf20Sopenharmony_ci new_rps->evclk = 0; 15598c2ecf20Sopenharmony_ci new_rps->ecclk = 0; 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 15638c2ecf20Sopenharmony_ci if (ps->levels[i].vddc_index < min_voltage) 15648c2ecf20Sopenharmony_ci ps->levels[i].vddc_index = min_voltage; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci if (ps->levels[i].sclk < min_sclk) 15678c2ecf20Sopenharmony_ci ps->levels[i].sclk = 15688c2ecf20Sopenharmony_ci trinity_get_valid_engine_clock(rdev, min_sclk); 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci /* patch in vce limits */ 15718c2ecf20Sopenharmony_ci if (new_rps->vce_active) { 15728c2ecf20Sopenharmony_ci /* sclk */ 15738c2ecf20Sopenharmony_ci if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk) 15748c2ecf20Sopenharmony_ci ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk; 15758c2ecf20Sopenharmony_ci /* vddc */ 15768c2ecf20Sopenharmony_ci trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage); 15778c2ecf20Sopenharmony_ci if (ps->levels[i].vddc_index < min_vce_voltage) 15788c2ecf20Sopenharmony_ci ps->levels[i].vddc_index = min_vce_voltage; 15798c2ecf20Sopenharmony_ci } 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci ps->levels[i].ds_divider_index = 15828c2ecf20Sopenharmony_ci sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr); 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index; 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci ps->levels[i].allow_gnb_slow = 1; 15878c2ecf20Sopenharmony_ci ps->levels[i].force_nbp_state = 0; 15888c2ecf20Sopenharmony_ci ps->levels[i].display_wm = 15898c2ecf20Sopenharmony_ci trinity_calculate_display_wm(rdev, ps, i); 15908c2ecf20Sopenharmony_ci ps->levels[i].vce_wm = 15918c2ecf20Sopenharmony_ci trinity_calculate_vce_wm(rdev, ps->levels[0].sclk); 15928c2ecf20Sopenharmony_ci } 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) || 15958c2ecf20Sopenharmony_ci ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) 15968c2ecf20Sopenharmony_ci ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci if (pi->sys_info.nb_dpm_enable) { 15998c2ecf20Sopenharmony_ci ps->Dpm0PgNbPsLo = 0x1; 16008c2ecf20Sopenharmony_ci ps->Dpm0PgNbPsHi = 0x0; 16018c2ecf20Sopenharmony_ci ps->DpmXNbPsLo = 0x2; 16028c2ecf20Sopenharmony_ci ps->DpmXNbPsHi = 0x1; 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) || 16058c2ecf20Sopenharmony_ci ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) { 16068c2ecf20Sopenharmony_ci force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) || 16078c2ecf20Sopenharmony_ci ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) && 16088c2ecf20Sopenharmony_ci (pi->sys_info.uma_channel_number == 1))); 16098c2ecf20Sopenharmony_ci force_high = (num_active_displays >= 3) || force_high; 16108c2ecf20Sopenharmony_ci ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3; 16118c2ecf20Sopenharmony_ci ps->Dpm0PgNbPsHi = 0x1; 16128c2ecf20Sopenharmony_ci ps->DpmXNbPsLo = force_high ? 0x2 : 0x3; 16138c2ecf20Sopenharmony_ci ps->DpmXNbPsHi = 0x2; 16148c2ecf20Sopenharmony_ci ps->levels[ps->num_levels - 1].allow_gnb_slow = 0; 16158c2ecf20Sopenharmony_ci } 16168c2ecf20Sopenharmony_ci } 16178c2ecf20Sopenharmony_ci} 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_cistatic void trinity_cleanup_asic(struct radeon_device *rdev) 16208c2ecf20Sopenharmony_ci{ 16218c2ecf20Sopenharmony_ci sumo_take_smu_control(rdev, false); 16228c2ecf20Sopenharmony_ci} 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci#if 0 16258c2ecf20Sopenharmony_cistatic void trinity_pre_display_configuration_change(struct radeon_device *rdev) 16268c2ecf20Sopenharmony_ci{ 16278c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci if (pi->voltage_drop_in_dce) 16308c2ecf20Sopenharmony_ci trinity_dce_enable_voltage_adjustment(rdev, false); 16318c2ecf20Sopenharmony_ci} 16328c2ecf20Sopenharmony_ci#endif 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_cistatic void trinity_add_dccac_value(struct radeon_device *rdev) 16358c2ecf20Sopenharmony_ci{ 16368c2ecf20Sopenharmony_ci u32 gpu_cac_avrg_cntl_window_size; 16378c2ecf20Sopenharmony_ci u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 16388c2ecf20Sopenharmony_ci u64 disp_clk = rdev->clock.default_dispclk / 100; 16398c2ecf20Sopenharmony_ci u32 dc_cac_value; 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci gpu_cac_avrg_cntl_window_size = 16428c2ecf20Sopenharmony_ci (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >> 16458c2ecf20Sopenharmony_ci (32 - gpu_cac_avrg_cntl_window_size)); 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci WREG32_SMC(DC_CAC_VALUE, dc_cac_value); 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_civoid trinity_dpm_display_configuration_changed(struct radeon_device *rdev) 16518c2ecf20Sopenharmony_ci{ 16528c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci if (pi->voltage_drop_in_dce) 16558c2ecf20Sopenharmony_ci trinity_dce_enable_voltage_adjustment(rdev, true); 16568c2ecf20Sopenharmony_ci trinity_add_dccac_value(rdev); 16578c2ecf20Sopenharmony_ci} 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ciunion power_info { 16608c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO info; 16618c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V2 info_2; 16628c2ecf20Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V3 info_3; 16638c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 16648c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 16658c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 16668c2ecf20Sopenharmony_ci}; 16678c2ecf20Sopenharmony_ci 16688c2ecf20Sopenharmony_ciunion pplib_clock_info { 16698c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_R600_CLOCK_INFO r600; 16708c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; 16718c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; 16728c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; 16738c2ecf20Sopenharmony_ci}; 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ciunion pplib_power_state { 16768c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_STATE v1; 16778c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_STATE_V2 v2; 16788c2ecf20Sopenharmony_ci}; 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_cistatic void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev, 16818c2ecf20Sopenharmony_ci struct radeon_ps *rps, 16828c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, 16838c2ecf20Sopenharmony_ci u8 table_rev) 16848c2ecf20Sopenharmony_ci{ 16858c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); 16888c2ecf20Sopenharmony_ci rps->class = le16_to_cpu(non_clock_info->usClassification); 16898c2ecf20Sopenharmony_ci rps->class2 = le16_to_cpu(non_clock_info->usClassification2); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { 16928c2ecf20Sopenharmony_ci rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); 16938c2ecf20Sopenharmony_ci rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); 16948c2ecf20Sopenharmony_ci } else { 16958c2ecf20Sopenharmony_ci rps->vclk = 0; 16968c2ecf20Sopenharmony_ci rps->dclk = 0; 16978c2ecf20Sopenharmony_ci } 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { 17008c2ecf20Sopenharmony_ci rdev->pm.dpm.boot_ps = rps; 17018c2ecf20Sopenharmony_ci trinity_patch_boot_state(rdev, ps); 17028c2ecf20Sopenharmony_ci } 17038c2ecf20Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 17048c2ecf20Sopenharmony_ci rdev->pm.dpm.uvd_ps = rps; 17058c2ecf20Sopenharmony_ci} 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_cistatic void trinity_parse_pplib_clock_info(struct radeon_device *rdev, 17088c2ecf20Sopenharmony_ci struct radeon_ps *rps, int index, 17098c2ecf20Sopenharmony_ci union pplib_clock_info *clock_info) 17108c2ecf20Sopenharmony_ci{ 17118c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 17128c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 17138c2ecf20Sopenharmony_ci struct trinity_pl *pl = &ps->levels[index]; 17148c2ecf20Sopenharmony_ci u32 sclk; 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 17178c2ecf20Sopenharmony_ci sclk |= clock_info->sumo.ucEngineClockHigh << 16; 17188c2ecf20Sopenharmony_ci pl->sclk = sclk; 17198c2ecf20Sopenharmony_ci pl->vddc_index = clock_info->sumo.vddcIndex; 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci ps->num_levels = index + 1; 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci if (pi->enable_sclk_ds) { 17248c2ecf20Sopenharmony_ci pl->ds_divider_index = 5; 17258c2ecf20Sopenharmony_ci pl->ss_divider_index = 5; 17268c2ecf20Sopenharmony_ci } 17278c2ecf20Sopenharmony_ci} 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_cistatic int trinity_parse_power_table(struct radeon_device *rdev) 17308c2ecf20Sopenharmony_ci{ 17318c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 17328c2ecf20Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 17338c2ecf20Sopenharmony_ci union pplib_power_state *power_state; 17348c2ecf20Sopenharmony_ci int i, j, k, non_clock_array_index, clock_array_index; 17358c2ecf20Sopenharmony_ci union pplib_clock_info *clock_info; 17368c2ecf20Sopenharmony_ci struct _StateArray *state_array; 17378c2ecf20Sopenharmony_ci struct _ClockInfoArray *clock_info_array; 17388c2ecf20Sopenharmony_ci struct _NonClockInfoArray *non_clock_info_array; 17398c2ecf20Sopenharmony_ci union power_info *power_info; 17408c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 17418c2ecf20Sopenharmony_ci u16 data_offset; 17428c2ecf20Sopenharmony_ci u8 frev, crev; 17438c2ecf20Sopenharmony_ci u8 *power_state_offset; 17448c2ecf20Sopenharmony_ci struct sumo_ps *ps; 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 17478c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) 17488c2ecf20Sopenharmony_ci return -EINVAL; 17498c2ecf20Sopenharmony_ci power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci state_array = (struct _StateArray *) 17528c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 17538c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usStateArrayOffset)); 17548c2ecf20Sopenharmony_ci clock_info_array = (struct _ClockInfoArray *) 17558c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 17568c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); 17578c2ecf20Sopenharmony_ci non_clock_info_array = (struct _NonClockInfoArray *) 17588c2ecf20Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 17598c2ecf20Sopenharmony_ci le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, 17628c2ecf20Sopenharmony_ci sizeof(struct radeon_ps), 17638c2ecf20Sopenharmony_ci GFP_KERNEL); 17648c2ecf20Sopenharmony_ci if (!rdev->pm.dpm.ps) 17658c2ecf20Sopenharmony_ci return -ENOMEM; 17668c2ecf20Sopenharmony_ci power_state_offset = (u8 *)state_array->states; 17678c2ecf20Sopenharmony_ci for (i = 0; i < state_array->ucNumEntries; i++) { 17688c2ecf20Sopenharmony_ci u8 *idx; 17698c2ecf20Sopenharmony_ci power_state = (union pplib_power_state *)power_state_offset; 17708c2ecf20Sopenharmony_ci non_clock_array_index = power_state->v2.nonClockInfoIndex; 17718c2ecf20Sopenharmony_ci non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 17728c2ecf20Sopenharmony_ci &non_clock_info_array->nonClockInfo[non_clock_array_index]; 17738c2ecf20Sopenharmony_ci if (!rdev->pm.power_state[i].clock_info) { 17748c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 17758c2ecf20Sopenharmony_ci return -EINVAL; 17768c2ecf20Sopenharmony_ci } 17778c2ecf20Sopenharmony_ci ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL); 17788c2ecf20Sopenharmony_ci if (ps == NULL) { 17798c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 17808c2ecf20Sopenharmony_ci return -ENOMEM; 17818c2ecf20Sopenharmony_ci } 17828c2ecf20Sopenharmony_ci rdev->pm.dpm.ps[i].ps_priv = ps; 17838c2ecf20Sopenharmony_ci k = 0; 17848c2ecf20Sopenharmony_ci idx = (u8 *)&power_state->v2.clockInfoIndex[0]; 17858c2ecf20Sopenharmony_ci for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { 17868c2ecf20Sopenharmony_ci clock_array_index = idx[j]; 17878c2ecf20Sopenharmony_ci if (clock_array_index >= clock_info_array->ucNumEntries) 17888c2ecf20Sopenharmony_ci continue; 17898c2ecf20Sopenharmony_ci if (k >= SUMO_MAX_HARDWARE_POWERLEVELS) 17908c2ecf20Sopenharmony_ci break; 17918c2ecf20Sopenharmony_ci clock_info = (union pplib_clock_info *) 17928c2ecf20Sopenharmony_ci ((u8 *)&clock_info_array->clockInfo[0] + 17938c2ecf20Sopenharmony_ci (clock_array_index * clock_info_array->ucEntrySize)); 17948c2ecf20Sopenharmony_ci trinity_parse_pplib_clock_info(rdev, 17958c2ecf20Sopenharmony_ci &rdev->pm.dpm.ps[i], k, 17968c2ecf20Sopenharmony_ci clock_info); 17978c2ecf20Sopenharmony_ci k++; 17988c2ecf20Sopenharmony_ci } 17998c2ecf20Sopenharmony_ci trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], 18008c2ecf20Sopenharmony_ci non_clock_info, 18018c2ecf20Sopenharmony_ci non_clock_info_array->ucEntrySize); 18028c2ecf20Sopenharmony_ci power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 18038c2ecf20Sopenharmony_ci } 18048c2ecf20Sopenharmony_ci rdev->pm.dpm.num_ps = state_array->ucNumEntries; 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_ci /* fill in the vce power states */ 18078c2ecf20Sopenharmony_ci for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) { 18088c2ecf20Sopenharmony_ci u32 sclk; 18098c2ecf20Sopenharmony_ci clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx; 18108c2ecf20Sopenharmony_ci clock_info = (union pplib_clock_info *) 18118c2ecf20Sopenharmony_ci &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; 18128c2ecf20Sopenharmony_ci sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 18138c2ecf20Sopenharmony_ci sclk |= clock_info->sumo.ucEngineClockHigh << 16; 18148c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].sclk = sclk; 18158c2ecf20Sopenharmony_ci rdev->pm.dpm.vce_states[i].mclk = 0; 18168c2ecf20Sopenharmony_ci } 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci return 0; 18198c2ecf20Sopenharmony_ci} 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ciunion igp_info { 18228c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO info; 18238c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; 18248c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; 18258c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; 18268c2ecf20Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; 18278c2ecf20Sopenharmony_ci}; 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_cistatic u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did) 18308c2ecf20Sopenharmony_ci{ 18318c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 18328c2ecf20Sopenharmony_ci u32 divider; 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci if (did >= 8 && did <= 0x3f) 18358c2ecf20Sopenharmony_ci divider = did * 25; 18368c2ecf20Sopenharmony_ci else if (did > 0x3f && did <= 0x5f) 18378c2ecf20Sopenharmony_ci divider = (did - 64) * 50 + 1600; 18388c2ecf20Sopenharmony_ci else if (did > 0x5f && did <= 0x7e) 18398c2ecf20Sopenharmony_ci divider = (did - 96) * 100 + 3200; 18408c2ecf20Sopenharmony_ci else if (did == 0x7f) 18418c2ecf20Sopenharmony_ci divider = 128 * 100; 18428c2ecf20Sopenharmony_ci else 18438c2ecf20Sopenharmony_ci return 10000; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider; 18468c2ecf20Sopenharmony_ci} 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_cistatic int trinity_parse_sys_info_table(struct radeon_device *rdev) 18498c2ecf20Sopenharmony_ci{ 18508c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 18518c2ecf20Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 18528c2ecf20Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 18538c2ecf20Sopenharmony_ci union igp_info *igp_info; 18548c2ecf20Sopenharmony_ci u8 frev, crev; 18558c2ecf20Sopenharmony_ci u16 data_offset; 18568c2ecf20Sopenharmony_ci int i; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci if (atom_parse_data_header(mode_info->atom_context, index, NULL, 18598c2ecf20Sopenharmony_ci &frev, &crev, &data_offset)) { 18608c2ecf20Sopenharmony_ci igp_info = (union igp_info *)(mode_info->atom_context->bios + 18618c2ecf20Sopenharmony_ci data_offset); 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci if (crev != 7) { 18648c2ecf20Sopenharmony_ci DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 18658c2ecf20Sopenharmony_ci return -EINVAL; 18668c2ecf20Sopenharmony_ci } 18678c2ecf20Sopenharmony_ci pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock); 18688c2ecf20Sopenharmony_ci pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock); 18698c2ecf20Sopenharmony_ci pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock); 18708c2ecf20Sopenharmony_ci pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq); 18718c2ecf20Sopenharmony_ci pi->sys_info.bootup_nb_voltage_index = 18728c2ecf20Sopenharmony_ci le16_to_cpu(igp_info->info_7.usBootUpNBVoltage); 18738c2ecf20Sopenharmony_ci if (igp_info->info_7.ucHtcTmpLmt == 0) 18748c2ecf20Sopenharmony_ci pi->sys_info.htc_tmp_lmt = 203; 18758c2ecf20Sopenharmony_ci else 18768c2ecf20Sopenharmony_ci pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt; 18778c2ecf20Sopenharmony_ci if (igp_info->info_7.ucHtcHystLmt == 0) 18788c2ecf20Sopenharmony_ci pi->sys_info.htc_hyst_lmt = 5; 18798c2ecf20Sopenharmony_ci else 18808c2ecf20Sopenharmony_ci pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt; 18818c2ecf20Sopenharmony_ci if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { 18828c2ecf20Sopenharmony_ci DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); 18838c2ecf20Sopenharmony_ci } 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci if (pi->enable_nbps_policy) 18868c2ecf20Sopenharmony_ci pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable; 18878c2ecf20Sopenharmony_ci else 18888c2ecf20Sopenharmony_ci pi->sys_info.nb_dpm_enable = 0; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) { 18918c2ecf20Sopenharmony_ci pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]); 18928c2ecf20Sopenharmony_ci pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]); 18938c2ecf20Sopenharmony_ci } 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage); 18968c2ecf20Sopenharmony_ci pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage); 18978c2ecf20Sopenharmony_ci pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage); 18988c2ecf20Sopenharmony_ci pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage); 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci if (!pi->sys_info.nb_dpm_enable) { 19018c2ecf20Sopenharmony_ci for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) { 19028c2ecf20Sopenharmony_ci pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0]; 19038c2ecf20Sopenharmony_ci pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0]; 19048c2ecf20Sopenharmony_ci pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0]; 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci } 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber; 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci sumo_construct_sclk_voltage_mapping_table(rdev, 19118c2ecf20Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table, 19128c2ecf20Sopenharmony_ci igp_info->info_7.sAvail_SCLK); 19138c2ecf20Sopenharmony_ci sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table, 19148c2ecf20Sopenharmony_ci igp_info->info_7.sAvail_SCLK); 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[0].vclk_did = 19178c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState0VclkFid; 19188c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[1].vclk_did = 19198c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState1VclkFid; 19208c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[2].vclk_did = 19218c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState2VclkFid; 19228c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[3].vclk_did = 19238c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState3VclkFid; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[0].dclk_did = 19268c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState0DclkFid; 19278c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[1].dclk_did = 19288c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState1DclkFid; 19298c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[2].dclk_did = 19308c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState2DclkFid; 19318c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[3].dclk_did = 19328c2ecf20Sopenharmony_ci igp_info->info_7.ucDPMState3DclkFid; 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 19358c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].vclk = 19368c2ecf20Sopenharmony_ci trinity_convert_did_to_freq(rdev, 19378c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].vclk_did); 19388c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].dclk = 19398c2ecf20Sopenharmony_ci trinity_convert_did_to_freq(rdev, 19408c2ecf20Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].dclk_did); 19418c2ecf20Sopenharmony_ci } 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci } 19468c2ecf20Sopenharmony_ci return 0; 19478c2ecf20Sopenharmony_ci} 19488c2ecf20Sopenharmony_ci 19498c2ecf20Sopenharmony_ciint trinity_dpm_init(struct radeon_device *rdev) 19508c2ecf20Sopenharmony_ci{ 19518c2ecf20Sopenharmony_ci struct trinity_power_info *pi; 19528c2ecf20Sopenharmony_ci int ret, i; 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL); 19558c2ecf20Sopenharmony_ci if (pi == NULL) 19568c2ecf20Sopenharmony_ci return -ENOMEM; 19578c2ecf20Sopenharmony_ci rdev->pm.dpm.priv = pi; 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) 19608c2ecf20Sopenharmony_ci pi->at[i] = TRINITY_AT_DFLT; 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci if (radeon_bapm == -1) { 19638c2ecf20Sopenharmony_ci /* There are stability issues reported on with 19648c2ecf20Sopenharmony_ci * bapm enabled when switching between AC and battery 19658c2ecf20Sopenharmony_ci * power. At the same time, some MSI boards hang 19668c2ecf20Sopenharmony_ci * if it's not enabled and dpm is enabled. Just enable 19678c2ecf20Sopenharmony_ci * it for MSI boards right now. 19688c2ecf20Sopenharmony_ci */ 19698c2ecf20Sopenharmony_ci if (rdev->pdev->subsystem_vendor == 0x1462) 19708c2ecf20Sopenharmony_ci pi->enable_bapm = true; 19718c2ecf20Sopenharmony_ci else 19728c2ecf20Sopenharmony_ci pi->enable_bapm = false; 19738c2ecf20Sopenharmony_ci } else if (radeon_bapm == 0) { 19748c2ecf20Sopenharmony_ci pi->enable_bapm = false; 19758c2ecf20Sopenharmony_ci } else { 19768c2ecf20Sopenharmony_ci pi->enable_bapm = true; 19778c2ecf20Sopenharmony_ci } 19788c2ecf20Sopenharmony_ci pi->enable_nbps_policy = true; 19798c2ecf20Sopenharmony_ci pi->enable_sclk_ds = true; 19808c2ecf20Sopenharmony_ci pi->enable_gfx_power_gating = true; 19818c2ecf20Sopenharmony_ci pi->enable_gfx_clock_gating = true; 19828c2ecf20Sopenharmony_ci pi->enable_mg_clock_gating = false; 19838c2ecf20Sopenharmony_ci pi->enable_gfx_dynamic_mgpg = false; 19848c2ecf20Sopenharmony_ci pi->override_dynamic_mgpg = false; 19858c2ecf20Sopenharmony_ci pi->enable_auto_thermal_throttling = true; 19868c2ecf20Sopenharmony_ci pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */ 19878c2ecf20Sopenharmony_ci pi->uvd_dpm = true; /* ??? */ 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_ci ret = trinity_parse_sys_info_table(rdev); 19908c2ecf20Sopenharmony_ci if (ret) 19918c2ecf20Sopenharmony_ci return ret; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci trinity_construct_boot_state(rdev); 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci ret = r600_get_platform_caps(rdev); 19968c2ecf20Sopenharmony_ci if (ret) 19978c2ecf20Sopenharmony_ci return ret; 19988c2ecf20Sopenharmony_ci 19998c2ecf20Sopenharmony_ci ret = r600_parse_extended_power_table(rdev); 20008c2ecf20Sopenharmony_ci if (ret) 20018c2ecf20Sopenharmony_ci return ret; 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci ret = trinity_parse_power_table(rdev); 20048c2ecf20Sopenharmony_ci if (ret) 20058c2ecf20Sopenharmony_ci return ret; 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ci pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt; 20088c2ecf20Sopenharmony_ci pi->enable_dpm = true; 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci return 0; 20118c2ecf20Sopenharmony_ci} 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_civoid trinity_dpm_print_power_state(struct radeon_device *rdev, 20148c2ecf20Sopenharmony_ci struct radeon_ps *rps) 20158c2ecf20Sopenharmony_ci{ 20168c2ecf20Sopenharmony_ci int i; 20178c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci r600_dpm_print_class_info(rps->class, rps->class2); 20208c2ecf20Sopenharmony_ci r600_dpm_print_cap_info(rps->caps); 20218c2ecf20Sopenharmony_ci printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 20228c2ecf20Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 20238c2ecf20Sopenharmony_ci struct trinity_pl *pl = &ps->levels[i]; 20248c2ecf20Sopenharmony_ci printk("\t\tpower level %d sclk: %u vddc: %u\n", 20258c2ecf20Sopenharmony_ci i, pl->sclk, 20268c2ecf20Sopenharmony_ci trinity_convert_voltage_index_to_value(rdev, pl->vddc_index)); 20278c2ecf20Sopenharmony_ci } 20288c2ecf20Sopenharmony_ci r600_dpm_print_ps_status(rdev, rps); 20298c2ecf20Sopenharmony_ci} 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_civoid trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 20328c2ecf20Sopenharmony_ci struct seq_file *m) 20338c2ecf20Sopenharmony_ci{ 20348c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 20358c2ecf20Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 20368c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 20378c2ecf20Sopenharmony_ci struct trinity_pl *pl; 20388c2ecf20Sopenharmony_ci u32 current_index = 20398c2ecf20Sopenharmony_ci (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >> 20408c2ecf20Sopenharmony_ci CURRENT_STATE_SHIFT; 20418c2ecf20Sopenharmony_ci 20428c2ecf20Sopenharmony_ci if (current_index >= ps->num_levels) { 20438c2ecf20Sopenharmony_ci seq_printf(m, "invalid dpm profile %d\n", current_index); 20448c2ecf20Sopenharmony_ci } else { 20458c2ecf20Sopenharmony_ci pl = &ps->levels[current_index]; 20468c2ecf20Sopenharmony_ci seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 20478c2ecf20Sopenharmony_ci seq_printf(m, "power level %d sclk: %u vddc: %u\n", 20488c2ecf20Sopenharmony_ci current_index, pl->sclk, 20498c2ecf20Sopenharmony_ci trinity_convert_voltage_index_to_value(rdev, pl->vddc_index)); 20508c2ecf20Sopenharmony_ci } 20518c2ecf20Sopenharmony_ci} 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ciu32 trinity_dpm_get_current_sclk(struct radeon_device *rdev) 20548c2ecf20Sopenharmony_ci{ 20558c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 20568c2ecf20Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 20578c2ecf20Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 20588c2ecf20Sopenharmony_ci struct trinity_pl *pl; 20598c2ecf20Sopenharmony_ci u32 current_index = 20608c2ecf20Sopenharmony_ci (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >> 20618c2ecf20Sopenharmony_ci CURRENT_STATE_SHIFT; 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci if (current_index >= ps->num_levels) { 20648c2ecf20Sopenharmony_ci return 0; 20658c2ecf20Sopenharmony_ci } else { 20668c2ecf20Sopenharmony_ci pl = &ps->levels[current_index]; 20678c2ecf20Sopenharmony_ci return pl->sclk; 20688c2ecf20Sopenharmony_ci } 20698c2ecf20Sopenharmony_ci} 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_ciu32 trinity_dpm_get_current_mclk(struct radeon_device *rdev) 20728c2ecf20Sopenharmony_ci{ 20738c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 20768c2ecf20Sopenharmony_ci} 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_civoid trinity_dpm_fini(struct radeon_device *rdev) 20798c2ecf20Sopenharmony_ci{ 20808c2ecf20Sopenharmony_ci int i; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci trinity_cleanup_asic(rdev); /* ??? */ 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci for (i = 0; i < rdev->pm.dpm.num_ps; i++) { 20858c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps[i].ps_priv); 20868c2ecf20Sopenharmony_ci } 20878c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.ps); 20888c2ecf20Sopenharmony_ci kfree(rdev->pm.dpm.priv); 20898c2ecf20Sopenharmony_ci r600_free_extended_power_table(rdev); 20908c2ecf20Sopenharmony_ci} 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ciu32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low) 20938c2ecf20Sopenharmony_ci{ 20948c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 20958c2ecf20Sopenharmony_ci struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps); 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci if (low) 20988c2ecf20Sopenharmony_ci return requested_state->levels[0].sclk; 20998c2ecf20Sopenharmony_ci else 21008c2ecf20Sopenharmony_ci return requested_state->levels[requested_state->num_levels - 1].sclk; 21018c2ecf20Sopenharmony_ci} 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_ciu32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low) 21048c2ecf20Sopenharmony_ci{ 21058c2ecf20Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 21088c2ecf20Sopenharmony_ci} 2109