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/math64.h>
258c2ecf20Sopenharmony_ci#include <linux/pci.h>
268c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include "atom.h"
298c2ecf20Sopenharmony_ci#include "ni_dpm.h"
308c2ecf20Sopenharmony_ci#include "nid.h"
318c2ecf20Sopenharmony_ci#include "r600_dpm.h"
328c2ecf20Sopenharmony_ci#include "radeon.h"
338c2ecf20Sopenharmony_ci#include "radeon_asic.h"
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F0           0x0a
368c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F1           0x0b
378c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F2           0x0c
388c2ecf20Sopenharmony_ci#define MC_CG_ARB_FREQ_F3           0x0d
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define SMC_RAM_END 0xC000
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic const struct ni_cac_weights cac_weights_cayman_xt =
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	0x15,
458c2ecf20Sopenharmony_ci	0x2,
468c2ecf20Sopenharmony_ci	0x19,
478c2ecf20Sopenharmony_ci	0x2,
488c2ecf20Sopenharmony_ci	0x8,
498c2ecf20Sopenharmony_ci	0x14,
508c2ecf20Sopenharmony_ci	0x2,
518c2ecf20Sopenharmony_ci	0x16,
528c2ecf20Sopenharmony_ci	0xE,
538c2ecf20Sopenharmony_ci	0x17,
548c2ecf20Sopenharmony_ci	0x13,
558c2ecf20Sopenharmony_ci	0x2B,
568c2ecf20Sopenharmony_ci	0x10,
578c2ecf20Sopenharmony_ci	0x7,
588c2ecf20Sopenharmony_ci	0x5,
598c2ecf20Sopenharmony_ci	0x5,
608c2ecf20Sopenharmony_ci	0x5,
618c2ecf20Sopenharmony_ci	0x2,
628c2ecf20Sopenharmony_ci	0x3,
638c2ecf20Sopenharmony_ci	0x9,
648c2ecf20Sopenharmony_ci	0x10,
658c2ecf20Sopenharmony_ci	0x10,
668c2ecf20Sopenharmony_ci	0x2B,
678c2ecf20Sopenharmony_ci	0xA,
688c2ecf20Sopenharmony_ci	0x9,
698c2ecf20Sopenharmony_ci	0x4,
708c2ecf20Sopenharmony_ci	0xD,
718c2ecf20Sopenharmony_ci	0xD,
728c2ecf20Sopenharmony_ci	0x3E,
738c2ecf20Sopenharmony_ci	0x18,
748c2ecf20Sopenharmony_ci	0x14,
758c2ecf20Sopenharmony_ci	0,
768c2ecf20Sopenharmony_ci	0x3,
778c2ecf20Sopenharmony_ci	0x3,
788c2ecf20Sopenharmony_ci	0x5,
798c2ecf20Sopenharmony_ci	0,
808c2ecf20Sopenharmony_ci	0x2,
818c2ecf20Sopenharmony_ci	0,
828c2ecf20Sopenharmony_ci	0,
838c2ecf20Sopenharmony_ci	0,
848c2ecf20Sopenharmony_ci	0,
858c2ecf20Sopenharmony_ci	0,
868c2ecf20Sopenharmony_ci	0,
878c2ecf20Sopenharmony_ci	0,
888c2ecf20Sopenharmony_ci	0,
898c2ecf20Sopenharmony_ci	0,
908c2ecf20Sopenharmony_ci	0x1CC,
918c2ecf20Sopenharmony_ci	0,
928c2ecf20Sopenharmony_ci	0x164,
938c2ecf20Sopenharmony_ci	1,
948c2ecf20Sopenharmony_ci	1,
958c2ecf20Sopenharmony_ci	1,
968c2ecf20Sopenharmony_ci	1,
978c2ecf20Sopenharmony_ci	12,
988c2ecf20Sopenharmony_ci	12,
998c2ecf20Sopenharmony_ci	12,
1008c2ecf20Sopenharmony_ci	0x12,
1018c2ecf20Sopenharmony_ci	0x1F,
1028c2ecf20Sopenharmony_ci	132,
1038c2ecf20Sopenharmony_ci	5,
1048c2ecf20Sopenharmony_ci	7,
1058c2ecf20Sopenharmony_ci	0,
1068c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
1078c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0 },
1088c2ecf20Sopenharmony_ci	true
1098c2ecf20Sopenharmony_ci};
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic const struct ni_cac_weights cac_weights_cayman_pro =
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	0x16,
1148c2ecf20Sopenharmony_ci	0x4,
1158c2ecf20Sopenharmony_ci	0x10,
1168c2ecf20Sopenharmony_ci	0x2,
1178c2ecf20Sopenharmony_ci	0xA,
1188c2ecf20Sopenharmony_ci	0x16,
1198c2ecf20Sopenharmony_ci	0x2,
1208c2ecf20Sopenharmony_ci	0x18,
1218c2ecf20Sopenharmony_ci	0x10,
1228c2ecf20Sopenharmony_ci	0x1A,
1238c2ecf20Sopenharmony_ci	0x16,
1248c2ecf20Sopenharmony_ci	0x2D,
1258c2ecf20Sopenharmony_ci	0x12,
1268c2ecf20Sopenharmony_ci	0xA,
1278c2ecf20Sopenharmony_ci	0x6,
1288c2ecf20Sopenharmony_ci	0x6,
1298c2ecf20Sopenharmony_ci	0x6,
1308c2ecf20Sopenharmony_ci	0x2,
1318c2ecf20Sopenharmony_ci	0x4,
1328c2ecf20Sopenharmony_ci	0xB,
1338c2ecf20Sopenharmony_ci	0x11,
1348c2ecf20Sopenharmony_ci	0x11,
1358c2ecf20Sopenharmony_ci	0x2D,
1368c2ecf20Sopenharmony_ci	0xC,
1378c2ecf20Sopenharmony_ci	0xC,
1388c2ecf20Sopenharmony_ci	0x7,
1398c2ecf20Sopenharmony_ci	0x10,
1408c2ecf20Sopenharmony_ci	0x10,
1418c2ecf20Sopenharmony_ci	0x3F,
1428c2ecf20Sopenharmony_ci	0x1A,
1438c2ecf20Sopenharmony_ci	0x16,
1448c2ecf20Sopenharmony_ci	0,
1458c2ecf20Sopenharmony_ci	0x7,
1468c2ecf20Sopenharmony_ci	0x4,
1478c2ecf20Sopenharmony_ci	0x6,
1488c2ecf20Sopenharmony_ci	1,
1498c2ecf20Sopenharmony_ci	0x2,
1508c2ecf20Sopenharmony_ci	0x1,
1518c2ecf20Sopenharmony_ci	0,
1528c2ecf20Sopenharmony_ci	0,
1538c2ecf20Sopenharmony_ci	0,
1548c2ecf20Sopenharmony_ci	0,
1558c2ecf20Sopenharmony_ci	0,
1568c2ecf20Sopenharmony_ci	0,
1578c2ecf20Sopenharmony_ci	0x30,
1588c2ecf20Sopenharmony_ci	0,
1598c2ecf20Sopenharmony_ci	0x1CF,
1608c2ecf20Sopenharmony_ci	0,
1618c2ecf20Sopenharmony_ci	0x166,
1628c2ecf20Sopenharmony_ci	1,
1638c2ecf20Sopenharmony_ci	1,
1648c2ecf20Sopenharmony_ci	1,
1658c2ecf20Sopenharmony_ci	1,
1668c2ecf20Sopenharmony_ci	12,
1678c2ecf20Sopenharmony_ci	12,
1688c2ecf20Sopenharmony_ci	12,
1698c2ecf20Sopenharmony_ci	0x15,
1708c2ecf20Sopenharmony_ci	0x1F,
1718c2ecf20Sopenharmony_ci	132,
1728c2ecf20Sopenharmony_ci	6,
1738c2ecf20Sopenharmony_ci	6,
1748c2ecf20Sopenharmony_ci	0,
1758c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
1768c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0 },
1778c2ecf20Sopenharmony_ci	true
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic const struct ni_cac_weights cac_weights_cayman_le =
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	0x7,
1838c2ecf20Sopenharmony_ci	0xE,
1848c2ecf20Sopenharmony_ci	0x1,
1858c2ecf20Sopenharmony_ci	0xA,
1868c2ecf20Sopenharmony_ci	0x1,
1878c2ecf20Sopenharmony_ci	0x3F,
1888c2ecf20Sopenharmony_ci	0x2,
1898c2ecf20Sopenharmony_ci	0x18,
1908c2ecf20Sopenharmony_ci	0x10,
1918c2ecf20Sopenharmony_ci	0x1A,
1928c2ecf20Sopenharmony_ci	0x1,
1938c2ecf20Sopenharmony_ci	0x3F,
1948c2ecf20Sopenharmony_ci	0x1,
1958c2ecf20Sopenharmony_ci	0xE,
1968c2ecf20Sopenharmony_ci	0x6,
1978c2ecf20Sopenharmony_ci	0x6,
1988c2ecf20Sopenharmony_ci	0x6,
1998c2ecf20Sopenharmony_ci	0x2,
2008c2ecf20Sopenharmony_ci	0x4,
2018c2ecf20Sopenharmony_ci	0x9,
2028c2ecf20Sopenharmony_ci	0x1A,
2038c2ecf20Sopenharmony_ci	0x1A,
2048c2ecf20Sopenharmony_ci	0x2C,
2058c2ecf20Sopenharmony_ci	0xA,
2068c2ecf20Sopenharmony_ci	0x11,
2078c2ecf20Sopenharmony_ci	0x8,
2088c2ecf20Sopenharmony_ci	0x19,
2098c2ecf20Sopenharmony_ci	0x19,
2108c2ecf20Sopenharmony_ci	0x1,
2118c2ecf20Sopenharmony_ci	0x1,
2128c2ecf20Sopenharmony_ci	0x1A,
2138c2ecf20Sopenharmony_ci	0,
2148c2ecf20Sopenharmony_ci	0x8,
2158c2ecf20Sopenharmony_ci	0x5,
2168c2ecf20Sopenharmony_ci	0x8,
2178c2ecf20Sopenharmony_ci	0x1,
2188c2ecf20Sopenharmony_ci	0x3,
2198c2ecf20Sopenharmony_ci	0x1,
2208c2ecf20Sopenharmony_ci	0,
2218c2ecf20Sopenharmony_ci	0,
2228c2ecf20Sopenharmony_ci	0,
2238c2ecf20Sopenharmony_ci	0,
2248c2ecf20Sopenharmony_ci	0,
2258c2ecf20Sopenharmony_ci	0,
2268c2ecf20Sopenharmony_ci	0x38,
2278c2ecf20Sopenharmony_ci	0x38,
2288c2ecf20Sopenharmony_ci	0x239,
2298c2ecf20Sopenharmony_ci	0x3,
2308c2ecf20Sopenharmony_ci	0x18A,
2318c2ecf20Sopenharmony_ci	1,
2328c2ecf20Sopenharmony_ci	1,
2338c2ecf20Sopenharmony_ci	1,
2348c2ecf20Sopenharmony_ci	1,
2358c2ecf20Sopenharmony_ci	12,
2368c2ecf20Sopenharmony_ci	12,
2378c2ecf20Sopenharmony_ci	12,
2388c2ecf20Sopenharmony_ci	0x15,
2398c2ecf20Sopenharmony_ci	0x22,
2408c2ecf20Sopenharmony_ci	132,
2418c2ecf20Sopenharmony_ci	6,
2428c2ecf20Sopenharmony_ci	6,
2438c2ecf20Sopenharmony_ci	0,
2448c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
2458c2ecf20Sopenharmony_ci	{ 0, 0, 0, 0 },
2468c2ecf20Sopenharmony_ci	true
2478c2ecf20Sopenharmony_ci};
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci#define NISLANDS_MGCG_SEQUENCE  300
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic const u32 cayman_cgcg_cgls_default[] =
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
2548c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2558c2ecf20Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
2568c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2578c2ecf20Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
2588c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2598c2ecf20Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
2608c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2618c2ecf20Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
2628c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2638c2ecf20Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
2648c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2658c2ecf20Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
2668c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2678c2ecf20Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
2688c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2698c2ecf20Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
2708c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2718c2ecf20Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
2728c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2738c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
2748c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2758c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
2768c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2778c2ecf20Sopenharmony_ci	0x000008f8, 0x00000020, 0xffffffff,
2788c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2798c2ecf20Sopenharmony_ci	0x000008f8, 0x00000021, 0xffffffff,
2808c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2818c2ecf20Sopenharmony_ci	0x000008f8, 0x00000022, 0xffffffff,
2828c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2838c2ecf20Sopenharmony_ci	0x000008f8, 0x00000023, 0xffffffff,
2848c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2858c2ecf20Sopenharmony_ci	0x000008f8, 0x00000024, 0xffffffff,
2868c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2878c2ecf20Sopenharmony_ci	0x000008f8, 0x00000025, 0xffffffff,
2888c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2898c2ecf20Sopenharmony_ci	0x000008f8, 0x00000026, 0xffffffff,
2908c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2918c2ecf20Sopenharmony_ci	0x000008f8, 0x00000027, 0xffffffff,
2928c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2938c2ecf20Sopenharmony_ci	0x000008f8, 0x00000028, 0xffffffff,
2948c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2958c2ecf20Sopenharmony_ci	0x000008f8, 0x00000029, 0xffffffff,
2968c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2978c2ecf20Sopenharmony_ci	0x000008f8, 0x0000002a, 0xffffffff,
2988c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
2998c2ecf20Sopenharmony_ci	0x000008f8, 0x0000002b, 0xffffffff,
3008c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff
3018c2ecf20Sopenharmony_ci};
3028c2ecf20Sopenharmony_ci#define CAYMAN_CGCG_CGLS_DEFAULT_LENGTH sizeof(cayman_cgcg_cgls_default) / (3 * sizeof(u32))
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic const u32 cayman_cgcg_cgls_disable[] =
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
3078c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3088c2ecf20Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
3098c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3108c2ecf20Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
3118c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3128c2ecf20Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
3138c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3148c2ecf20Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
3158c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3168c2ecf20Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
3178c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3188c2ecf20Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
3198c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3208c2ecf20Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
3218c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3228c2ecf20Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
3238c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3248c2ecf20Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
3258c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3268c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
3278c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3288c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
3298c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3308c2ecf20Sopenharmony_ci	0x000008f8, 0x00000020, 0xffffffff,
3318c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3328c2ecf20Sopenharmony_ci	0x000008f8, 0x00000021, 0xffffffff,
3338c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3348c2ecf20Sopenharmony_ci	0x000008f8, 0x00000022, 0xffffffff,
3358c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3368c2ecf20Sopenharmony_ci	0x000008f8, 0x00000023, 0xffffffff,
3378c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3388c2ecf20Sopenharmony_ci	0x000008f8, 0x00000024, 0xffffffff,
3398c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3408c2ecf20Sopenharmony_ci	0x000008f8, 0x00000025, 0xffffffff,
3418c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3428c2ecf20Sopenharmony_ci	0x000008f8, 0x00000026, 0xffffffff,
3438c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3448c2ecf20Sopenharmony_ci	0x000008f8, 0x00000027, 0xffffffff,
3458c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3468c2ecf20Sopenharmony_ci	0x000008f8, 0x00000028, 0xffffffff,
3478c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3488c2ecf20Sopenharmony_ci	0x000008f8, 0x00000029, 0xffffffff,
3498c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3508c2ecf20Sopenharmony_ci	0x000008f8, 0x0000002a, 0xffffffff,
3518c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3528c2ecf20Sopenharmony_ci	0x000008f8, 0x0000002b, 0xffffffff,
3538c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3548c2ecf20Sopenharmony_ci	0x00000644, 0x000f7902, 0x001f4180,
3558c2ecf20Sopenharmony_ci	0x00000644, 0x000f3802, 0x001f4180
3568c2ecf20Sopenharmony_ci};
3578c2ecf20Sopenharmony_ci#define CAYMAN_CGCG_CGLS_DISABLE_LENGTH sizeof(cayman_cgcg_cgls_disable) / (3 * sizeof(u32))
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_cistatic const u32 cayman_cgcg_cgls_enable[] =
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	0x00000644, 0x000f7882, 0x001f4080,
3628c2ecf20Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
3638c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3648c2ecf20Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
3658c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3668c2ecf20Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
3678c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3688c2ecf20Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
3698c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3708c2ecf20Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
3718c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3728c2ecf20Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
3738c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3748c2ecf20Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
3758c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3768c2ecf20Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
3778c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3788c2ecf20Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
3798c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3808c2ecf20Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
3818c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3828c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
3838c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3848c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
3858c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
3868c2ecf20Sopenharmony_ci	0x000008f8, 0x00000020, 0xffffffff,
3878c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3888c2ecf20Sopenharmony_ci	0x000008f8, 0x00000021, 0xffffffff,
3898c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3908c2ecf20Sopenharmony_ci	0x000008f8, 0x00000022, 0xffffffff,
3918c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3928c2ecf20Sopenharmony_ci	0x000008f8, 0x00000023, 0xffffffff,
3938c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3948c2ecf20Sopenharmony_ci	0x000008f8, 0x00000024, 0xffffffff,
3958c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3968c2ecf20Sopenharmony_ci	0x000008f8, 0x00000025, 0xffffffff,
3978c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
3988c2ecf20Sopenharmony_ci	0x000008f8, 0x00000026, 0xffffffff,
3998c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
4008c2ecf20Sopenharmony_ci	0x000008f8, 0x00000027, 0xffffffff,
4018c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
4028c2ecf20Sopenharmony_ci	0x000008f8, 0x00000028, 0xffffffff,
4038c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
4048c2ecf20Sopenharmony_ci	0x000008f8, 0x00000029, 0xffffffff,
4058c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
4068c2ecf20Sopenharmony_ci	0x000008f8, 0x0000002a, 0xffffffff,
4078c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
4088c2ecf20Sopenharmony_ci	0x000008f8, 0x0000002b, 0xffffffff,
4098c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff
4108c2ecf20Sopenharmony_ci};
4118c2ecf20Sopenharmony_ci#define CAYMAN_CGCG_CGLS_ENABLE_LENGTH  sizeof(cayman_cgcg_cgls_enable) / (3 * sizeof(u32))
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic const u32 cayman_mgcg_default[] =
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
4168c2ecf20Sopenharmony_ci	0x00003fc4, 0xc0000000, 0xffffffff,
4178c2ecf20Sopenharmony_ci	0x00005448, 0x00000100, 0xffffffff,
4188c2ecf20Sopenharmony_ci	0x000055e4, 0x00000100, 0xffffffff,
4198c2ecf20Sopenharmony_ci	0x0000160c, 0x00000100, 0xffffffff,
4208c2ecf20Sopenharmony_ci	0x00008984, 0x06000100, 0xffffffff,
4218c2ecf20Sopenharmony_ci	0x0000c164, 0x00000100, 0xffffffff,
4228c2ecf20Sopenharmony_ci	0x00008a18, 0x00000100, 0xffffffff,
4238c2ecf20Sopenharmony_ci	0x0000897c, 0x06000100, 0xffffffff,
4248c2ecf20Sopenharmony_ci	0x00008b28, 0x00000100, 0xffffffff,
4258c2ecf20Sopenharmony_ci	0x00009144, 0x00800200, 0xffffffff,
4268c2ecf20Sopenharmony_ci	0x00009a60, 0x00000100, 0xffffffff,
4278c2ecf20Sopenharmony_ci	0x00009868, 0x00000100, 0xffffffff,
4288c2ecf20Sopenharmony_ci	0x00008d58, 0x00000100, 0xffffffff,
4298c2ecf20Sopenharmony_ci	0x00009510, 0x00000100, 0xffffffff,
4308c2ecf20Sopenharmony_ci	0x0000949c, 0x00000100, 0xffffffff,
4318c2ecf20Sopenharmony_ci	0x00009654, 0x00000100, 0xffffffff,
4328c2ecf20Sopenharmony_ci	0x00009030, 0x00000100, 0xffffffff,
4338c2ecf20Sopenharmony_ci	0x00009034, 0x00000100, 0xffffffff,
4348c2ecf20Sopenharmony_ci	0x00009038, 0x00000100, 0xffffffff,
4358c2ecf20Sopenharmony_ci	0x0000903c, 0x00000100, 0xffffffff,
4368c2ecf20Sopenharmony_ci	0x00009040, 0x00000100, 0xffffffff,
4378c2ecf20Sopenharmony_ci	0x0000a200, 0x00000100, 0xffffffff,
4388c2ecf20Sopenharmony_ci	0x0000a204, 0x00000100, 0xffffffff,
4398c2ecf20Sopenharmony_ci	0x0000a208, 0x00000100, 0xffffffff,
4408c2ecf20Sopenharmony_ci	0x0000a20c, 0x00000100, 0xffffffff,
4418c2ecf20Sopenharmony_ci	0x00009744, 0x00000100, 0xffffffff,
4428c2ecf20Sopenharmony_ci	0x00003f80, 0x00000100, 0xffffffff,
4438c2ecf20Sopenharmony_ci	0x0000a210, 0x00000100, 0xffffffff,
4448c2ecf20Sopenharmony_ci	0x0000a214, 0x00000100, 0xffffffff,
4458c2ecf20Sopenharmony_ci	0x000004d8, 0x00000100, 0xffffffff,
4468c2ecf20Sopenharmony_ci	0x00009664, 0x00000100, 0xffffffff,
4478c2ecf20Sopenharmony_ci	0x00009698, 0x00000100, 0xffffffff,
4488c2ecf20Sopenharmony_ci	0x000004d4, 0x00000200, 0xffffffff,
4498c2ecf20Sopenharmony_ci	0x000004d0, 0x00000000, 0xffffffff,
4508c2ecf20Sopenharmony_ci	0x000030cc, 0x00000104, 0xffffffff,
4518c2ecf20Sopenharmony_ci	0x0000d0c0, 0x00000100, 0xffffffff,
4528c2ecf20Sopenharmony_ci	0x0000d8c0, 0x00000100, 0xffffffff,
4538c2ecf20Sopenharmony_ci	0x0000802c, 0x40000000, 0xffffffff,
4548c2ecf20Sopenharmony_ci	0x00003fc4, 0x40000000, 0xffffffff,
4558c2ecf20Sopenharmony_ci	0x0000915c, 0x00010000, 0xffffffff,
4568c2ecf20Sopenharmony_ci	0x00009160, 0x00030002, 0xffffffff,
4578c2ecf20Sopenharmony_ci	0x00009164, 0x00050004, 0xffffffff,
4588c2ecf20Sopenharmony_ci	0x00009168, 0x00070006, 0xffffffff,
4598c2ecf20Sopenharmony_ci	0x00009178, 0x00070000, 0xffffffff,
4608c2ecf20Sopenharmony_ci	0x0000917c, 0x00030002, 0xffffffff,
4618c2ecf20Sopenharmony_ci	0x00009180, 0x00050004, 0xffffffff,
4628c2ecf20Sopenharmony_ci	0x0000918c, 0x00010006, 0xffffffff,
4638c2ecf20Sopenharmony_ci	0x00009190, 0x00090008, 0xffffffff,
4648c2ecf20Sopenharmony_ci	0x00009194, 0x00070000, 0xffffffff,
4658c2ecf20Sopenharmony_ci	0x00009198, 0x00030002, 0xffffffff,
4668c2ecf20Sopenharmony_ci	0x0000919c, 0x00050004, 0xffffffff,
4678c2ecf20Sopenharmony_ci	0x000091a8, 0x00010006, 0xffffffff,
4688c2ecf20Sopenharmony_ci	0x000091ac, 0x00090008, 0xffffffff,
4698c2ecf20Sopenharmony_ci	0x000091b0, 0x00070000, 0xffffffff,
4708c2ecf20Sopenharmony_ci	0x000091b4, 0x00030002, 0xffffffff,
4718c2ecf20Sopenharmony_ci	0x000091b8, 0x00050004, 0xffffffff,
4728c2ecf20Sopenharmony_ci	0x000091c4, 0x00010006, 0xffffffff,
4738c2ecf20Sopenharmony_ci	0x000091c8, 0x00090008, 0xffffffff,
4748c2ecf20Sopenharmony_ci	0x000091cc, 0x00070000, 0xffffffff,
4758c2ecf20Sopenharmony_ci	0x000091d0, 0x00030002, 0xffffffff,
4768c2ecf20Sopenharmony_ci	0x000091d4, 0x00050004, 0xffffffff,
4778c2ecf20Sopenharmony_ci	0x000091e0, 0x00010006, 0xffffffff,
4788c2ecf20Sopenharmony_ci	0x000091e4, 0x00090008, 0xffffffff,
4798c2ecf20Sopenharmony_ci	0x000091e8, 0x00000000, 0xffffffff,
4808c2ecf20Sopenharmony_ci	0x000091ec, 0x00070000, 0xffffffff,
4818c2ecf20Sopenharmony_ci	0x000091f0, 0x00030002, 0xffffffff,
4828c2ecf20Sopenharmony_ci	0x000091f4, 0x00050004, 0xffffffff,
4838c2ecf20Sopenharmony_ci	0x00009200, 0x00010006, 0xffffffff,
4848c2ecf20Sopenharmony_ci	0x00009204, 0x00090008, 0xffffffff,
4858c2ecf20Sopenharmony_ci	0x00009208, 0x00070000, 0xffffffff,
4868c2ecf20Sopenharmony_ci	0x0000920c, 0x00030002, 0xffffffff,
4878c2ecf20Sopenharmony_ci	0x00009210, 0x00050004, 0xffffffff,
4888c2ecf20Sopenharmony_ci	0x0000921c, 0x00010006, 0xffffffff,
4898c2ecf20Sopenharmony_ci	0x00009220, 0x00090008, 0xffffffff,
4908c2ecf20Sopenharmony_ci	0x00009224, 0x00070000, 0xffffffff,
4918c2ecf20Sopenharmony_ci	0x00009228, 0x00030002, 0xffffffff,
4928c2ecf20Sopenharmony_ci	0x0000922c, 0x00050004, 0xffffffff,
4938c2ecf20Sopenharmony_ci	0x00009238, 0x00010006, 0xffffffff,
4948c2ecf20Sopenharmony_ci	0x0000923c, 0x00090008, 0xffffffff,
4958c2ecf20Sopenharmony_ci	0x00009240, 0x00070000, 0xffffffff,
4968c2ecf20Sopenharmony_ci	0x00009244, 0x00030002, 0xffffffff,
4978c2ecf20Sopenharmony_ci	0x00009248, 0x00050004, 0xffffffff,
4988c2ecf20Sopenharmony_ci	0x00009254, 0x00010006, 0xffffffff,
4998c2ecf20Sopenharmony_ci	0x00009258, 0x00090008, 0xffffffff,
5008c2ecf20Sopenharmony_ci	0x0000925c, 0x00070000, 0xffffffff,
5018c2ecf20Sopenharmony_ci	0x00009260, 0x00030002, 0xffffffff,
5028c2ecf20Sopenharmony_ci	0x00009264, 0x00050004, 0xffffffff,
5038c2ecf20Sopenharmony_ci	0x00009270, 0x00010006, 0xffffffff,
5048c2ecf20Sopenharmony_ci	0x00009274, 0x00090008, 0xffffffff,
5058c2ecf20Sopenharmony_ci	0x00009278, 0x00070000, 0xffffffff,
5068c2ecf20Sopenharmony_ci	0x0000927c, 0x00030002, 0xffffffff,
5078c2ecf20Sopenharmony_ci	0x00009280, 0x00050004, 0xffffffff,
5088c2ecf20Sopenharmony_ci	0x0000928c, 0x00010006, 0xffffffff,
5098c2ecf20Sopenharmony_ci	0x00009290, 0x00090008, 0xffffffff,
5108c2ecf20Sopenharmony_ci	0x000092a8, 0x00070000, 0xffffffff,
5118c2ecf20Sopenharmony_ci	0x000092ac, 0x00030002, 0xffffffff,
5128c2ecf20Sopenharmony_ci	0x000092b0, 0x00050004, 0xffffffff,
5138c2ecf20Sopenharmony_ci	0x000092bc, 0x00010006, 0xffffffff,
5148c2ecf20Sopenharmony_ci	0x000092c0, 0x00090008, 0xffffffff,
5158c2ecf20Sopenharmony_ci	0x000092c4, 0x00070000, 0xffffffff,
5168c2ecf20Sopenharmony_ci	0x000092c8, 0x00030002, 0xffffffff,
5178c2ecf20Sopenharmony_ci	0x000092cc, 0x00050004, 0xffffffff,
5188c2ecf20Sopenharmony_ci	0x000092d8, 0x00010006, 0xffffffff,
5198c2ecf20Sopenharmony_ci	0x000092dc, 0x00090008, 0xffffffff,
5208c2ecf20Sopenharmony_ci	0x00009294, 0x00000000, 0xffffffff,
5218c2ecf20Sopenharmony_ci	0x0000802c, 0x40010000, 0xffffffff,
5228c2ecf20Sopenharmony_ci	0x00003fc4, 0x40010000, 0xffffffff,
5238c2ecf20Sopenharmony_ci	0x0000915c, 0x00010000, 0xffffffff,
5248c2ecf20Sopenharmony_ci	0x00009160, 0x00030002, 0xffffffff,
5258c2ecf20Sopenharmony_ci	0x00009164, 0x00050004, 0xffffffff,
5268c2ecf20Sopenharmony_ci	0x00009168, 0x00070006, 0xffffffff,
5278c2ecf20Sopenharmony_ci	0x00009178, 0x00070000, 0xffffffff,
5288c2ecf20Sopenharmony_ci	0x0000917c, 0x00030002, 0xffffffff,
5298c2ecf20Sopenharmony_ci	0x00009180, 0x00050004, 0xffffffff,
5308c2ecf20Sopenharmony_ci	0x0000918c, 0x00010006, 0xffffffff,
5318c2ecf20Sopenharmony_ci	0x00009190, 0x00090008, 0xffffffff,
5328c2ecf20Sopenharmony_ci	0x00009194, 0x00070000, 0xffffffff,
5338c2ecf20Sopenharmony_ci	0x00009198, 0x00030002, 0xffffffff,
5348c2ecf20Sopenharmony_ci	0x0000919c, 0x00050004, 0xffffffff,
5358c2ecf20Sopenharmony_ci	0x000091a8, 0x00010006, 0xffffffff,
5368c2ecf20Sopenharmony_ci	0x000091ac, 0x00090008, 0xffffffff,
5378c2ecf20Sopenharmony_ci	0x000091b0, 0x00070000, 0xffffffff,
5388c2ecf20Sopenharmony_ci	0x000091b4, 0x00030002, 0xffffffff,
5398c2ecf20Sopenharmony_ci	0x000091b8, 0x00050004, 0xffffffff,
5408c2ecf20Sopenharmony_ci	0x000091c4, 0x00010006, 0xffffffff,
5418c2ecf20Sopenharmony_ci	0x000091c8, 0x00090008, 0xffffffff,
5428c2ecf20Sopenharmony_ci	0x000091cc, 0x00070000, 0xffffffff,
5438c2ecf20Sopenharmony_ci	0x000091d0, 0x00030002, 0xffffffff,
5448c2ecf20Sopenharmony_ci	0x000091d4, 0x00050004, 0xffffffff,
5458c2ecf20Sopenharmony_ci	0x000091e0, 0x00010006, 0xffffffff,
5468c2ecf20Sopenharmony_ci	0x000091e4, 0x00090008, 0xffffffff,
5478c2ecf20Sopenharmony_ci	0x000091e8, 0x00000000, 0xffffffff,
5488c2ecf20Sopenharmony_ci	0x000091ec, 0x00070000, 0xffffffff,
5498c2ecf20Sopenharmony_ci	0x000091f0, 0x00030002, 0xffffffff,
5508c2ecf20Sopenharmony_ci	0x000091f4, 0x00050004, 0xffffffff,
5518c2ecf20Sopenharmony_ci	0x00009200, 0x00010006, 0xffffffff,
5528c2ecf20Sopenharmony_ci	0x00009204, 0x00090008, 0xffffffff,
5538c2ecf20Sopenharmony_ci	0x00009208, 0x00070000, 0xffffffff,
5548c2ecf20Sopenharmony_ci	0x0000920c, 0x00030002, 0xffffffff,
5558c2ecf20Sopenharmony_ci	0x00009210, 0x00050004, 0xffffffff,
5568c2ecf20Sopenharmony_ci	0x0000921c, 0x00010006, 0xffffffff,
5578c2ecf20Sopenharmony_ci	0x00009220, 0x00090008, 0xffffffff,
5588c2ecf20Sopenharmony_ci	0x00009224, 0x00070000, 0xffffffff,
5598c2ecf20Sopenharmony_ci	0x00009228, 0x00030002, 0xffffffff,
5608c2ecf20Sopenharmony_ci	0x0000922c, 0x00050004, 0xffffffff,
5618c2ecf20Sopenharmony_ci	0x00009238, 0x00010006, 0xffffffff,
5628c2ecf20Sopenharmony_ci	0x0000923c, 0x00090008, 0xffffffff,
5638c2ecf20Sopenharmony_ci	0x00009240, 0x00070000, 0xffffffff,
5648c2ecf20Sopenharmony_ci	0x00009244, 0x00030002, 0xffffffff,
5658c2ecf20Sopenharmony_ci	0x00009248, 0x00050004, 0xffffffff,
5668c2ecf20Sopenharmony_ci	0x00009254, 0x00010006, 0xffffffff,
5678c2ecf20Sopenharmony_ci	0x00009258, 0x00090008, 0xffffffff,
5688c2ecf20Sopenharmony_ci	0x0000925c, 0x00070000, 0xffffffff,
5698c2ecf20Sopenharmony_ci	0x00009260, 0x00030002, 0xffffffff,
5708c2ecf20Sopenharmony_ci	0x00009264, 0x00050004, 0xffffffff,
5718c2ecf20Sopenharmony_ci	0x00009270, 0x00010006, 0xffffffff,
5728c2ecf20Sopenharmony_ci	0x00009274, 0x00090008, 0xffffffff,
5738c2ecf20Sopenharmony_ci	0x00009278, 0x00070000, 0xffffffff,
5748c2ecf20Sopenharmony_ci	0x0000927c, 0x00030002, 0xffffffff,
5758c2ecf20Sopenharmony_ci	0x00009280, 0x00050004, 0xffffffff,
5768c2ecf20Sopenharmony_ci	0x0000928c, 0x00010006, 0xffffffff,
5778c2ecf20Sopenharmony_ci	0x00009290, 0x00090008, 0xffffffff,
5788c2ecf20Sopenharmony_ci	0x000092a8, 0x00070000, 0xffffffff,
5798c2ecf20Sopenharmony_ci	0x000092ac, 0x00030002, 0xffffffff,
5808c2ecf20Sopenharmony_ci	0x000092b0, 0x00050004, 0xffffffff,
5818c2ecf20Sopenharmony_ci	0x000092bc, 0x00010006, 0xffffffff,
5828c2ecf20Sopenharmony_ci	0x000092c0, 0x00090008, 0xffffffff,
5838c2ecf20Sopenharmony_ci	0x000092c4, 0x00070000, 0xffffffff,
5848c2ecf20Sopenharmony_ci	0x000092c8, 0x00030002, 0xffffffff,
5858c2ecf20Sopenharmony_ci	0x000092cc, 0x00050004, 0xffffffff,
5868c2ecf20Sopenharmony_ci	0x000092d8, 0x00010006, 0xffffffff,
5878c2ecf20Sopenharmony_ci	0x000092dc, 0x00090008, 0xffffffff,
5888c2ecf20Sopenharmony_ci	0x00009294, 0x00000000, 0xffffffff,
5898c2ecf20Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
5908c2ecf20Sopenharmony_ci	0x00003fc4, 0xc0000000, 0xffffffff,
5918c2ecf20Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
5928c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
5938c2ecf20Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
5948c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
5958c2ecf20Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
5968c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
5978c2ecf20Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
5988c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
5998c2ecf20Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
6008c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6018c2ecf20Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
6028c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6038c2ecf20Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
6048c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6058c2ecf20Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
6068c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6078c2ecf20Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
6088c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6098c2ecf20Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
6108c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6118c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
6128c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6138c2ecf20Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
6148c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff
6158c2ecf20Sopenharmony_ci};
6168c2ecf20Sopenharmony_ci#define CAYMAN_MGCG_DEFAULT_LENGTH sizeof(cayman_mgcg_default) / (3 * sizeof(u32))
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_cistatic const u32 cayman_mgcg_disable[] =
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
6218c2ecf20Sopenharmony_ci	0x000008f8, 0x00000000, 0xffffffff,
6228c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
6238c2ecf20Sopenharmony_ci	0x000008f8, 0x00000001, 0xffffffff,
6248c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
6258c2ecf20Sopenharmony_ci	0x000008f8, 0x00000002, 0xffffffff,
6268c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
6278c2ecf20Sopenharmony_ci	0x000008f8, 0x00000003, 0xffffffff,
6288c2ecf20Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
6298c2ecf20Sopenharmony_ci	0x00009150, 0x00600000, 0xffffffff
6308c2ecf20Sopenharmony_ci};
6318c2ecf20Sopenharmony_ci#define CAYMAN_MGCG_DISABLE_LENGTH   sizeof(cayman_mgcg_disable) / (3 * sizeof(u32))
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cistatic const u32 cayman_mgcg_enable[] =
6348c2ecf20Sopenharmony_ci{
6358c2ecf20Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
6368c2ecf20Sopenharmony_ci	0x000008f8, 0x00000000, 0xffffffff,
6378c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6388c2ecf20Sopenharmony_ci	0x000008f8, 0x00000001, 0xffffffff,
6398c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6408c2ecf20Sopenharmony_ci	0x000008f8, 0x00000002, 0xffffffff,
6418c2ecf20Sopenharmony_ci	0x000008fc, 0x00600000, 0xffffffff,
6428c2ecf20Sopenharmony_ci	0x000008f8, 0x00000003, 0xffffffff,
6438c2ecf20Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
6448c2ecf20Sopenharmony_ci	0x00009150, 0x96944200, 0xffffffff
6458c2ecf20Sopenharmony_ci};
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci#define CAYMAN_MGCG_ENABLE_LENGTH   sizeof(cayman_mgcg_enable) / (3 * sizeof(u32))
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci#define NISLANDS_SYSLS_SEQUENCE  100
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_cistatic const u32 cayman_sysls_default[] =
6528c2ecf20Sopenharmony_ci{
6538c2ecf20Sopenharmony_ci	/* Register,   Value,     Mask bits */
6548c2ecf20Sopenharmony_ci	0x000055e8, 0x00000000, 0xffffffff,
6558c2ecf20Sopenharmony_ci	0x0000d0bc, 0x00000000, 0xffffffff,
6568c2ecf20Sopenharmony_ci	0x0000d8bc, 0x00000000, 0xffffffff,
6578c2ecf20Sopenharmony_ci	0x000015c0, 0x000c1401, 0xffffffff,
6588c2ecf20Sopenharmony_ci	0x0000264c, 0x000c0400, 0xffffffff,
6598c2ecf20Sopenharmony_ci	0x00002648, 0x000c0400, 0xffffffff,
6608c2ecf20Sopenharmony_ci	0x00002650, 0x000c0400, 0xffffffff,
6618c2ecf20Sopenharmony_ci	0x000020b8, 0x000c0400, 0xffffffff,
6628c2ecf20Sopenharmony_ci	0x000020bc, 0x000c0400, 0xffffffff,
6638c2ecf20Sopenharmony_ci	0x000020c0, 0x000c0c80, 0xffffffff,
6648c2ecf20Sopenharmony_ci	0x0000f4a0, 0x000000c0, 0xffffffff,
6658c2ecf20Sopenharmony_ci	0x0000f4a4, 0x00680fff, 0xffffffff,
6668c2ecf20Sopenharmony_ci	0x00002f50, 0x00000404, 0xffffffff,
6678c2ecf20Sopenharmony_ci	0x000004c8, 0x00000001, 0xffffffff,
6688c2ecf20Sopenharmony_ci	0x000064ec, 0x00000000, 0xffffffff,
6698c2ecf20Sopenharmony_ci	0x00000c7c, 0x00000000, 0xffffffff,
6708c2ecf20Sopenharmony_ci	0x00008dfc, 0x00000000, 0xffffffff
6718c2ecf20Sopenharmony_ci};
6728c2ecf20Sopenharmony_ci#define CAYMAN_SYSLS_DEFAULT_LENGTH sizeof(cayman_sysls_default) / (3 * sizeof(u32))
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_cistatic const u32 cayman_sysls_disable[] =
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci	/* Register,   Value,     Mask bits */
6778c2ecf20Sopenharmony_ci	0x0000d0c0, 0x00000000, 0xffffffff,
6788c2ecf20Sopenharmony_ci	0x0000d8c0, 0x00000000, 0xffffffff,
6798c2ecf20Sopenharmony_ci	0x000055e8, 0x00000000, 0xffffffff,
6808c2ecf20Sopenharmony_ci	0x0000d0bc, 0x00000000, 0xffffffff,
6818c2ecf20Sopenharmony_ci	0x0000d8bc, 0x00000000, 0xffffffff,
6828c2ecf20Sopenharmony_ci	0x000015c0, 0x00041401, 0xffffffff,
6838c2ecf20Sopenharmony_ci	0x0000264c, 0x00040400, 0xffffffff,
6848c2ecf20Sopenharmony_ci	0x00002648, 0x00040400, 0xffffffff,
6858c2ecf20Sopenharmony_ci	0x00002650, 0x00040400, 0xffffffff,
6868c2ecf20Sopenharmony_ci	0x000020b8, 0x00040400, 0xffffffff,
6878c2ecf20Sopenharmony_ci	0x000020bc, 0x00040400, 0xffffffff,
6888c2ecf20Sopenharmony_ci	0x000020c0, 0x00040c80, 0xffffffff,
6898c2ecf20Sopenharmony_ci	0x0000f4a0, 0x000000c0, 0xffffffff,
6908c2ecf20Sopenharmony_ci	0x0000f4a4, 0x00680000, 0xffffffff,
6918c2ecf20Sopenharmony_ci	0x00002f50, 0x00000404, 0xffffffff,
6928c2ecf20Sopenharmony_ci	0x000004c8, 0x00000001, 0xffffffff,
6938c2ecf20Sopenharmony_ci	0x000064ec, 0x00007ffd, 0xffffffff,
6948c2ecf20Sopenharmony_ci	0x00000c7c, 0x0000ff00, 0xffffffff,
6958c2ecf20Sopenharmony_ci	0x00008dfc, 0x0000007f, 0xffffffff
6968c2ecf20Sopenharmony_ci};
6978c2ecf20Sopenharmony_ci#define CAYMAN_SYSLS_DISABLE_LENGTH sizeof(cayman_sysls_disable) / (3 * sizeof(u32))
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_cistatic const u32 cayman_sysls_enable[] =
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	/* Register,   Value,     Mask bits */
7028c2ecf20Sopenharmony_ci	0x000055e8, 0x00000001, 0xffffffff,
7038c2ecf20Sopenharmony_ci	0x0000d0bc, 0x00000100, 0xffffffff,
7048c2ecf20Sopenharmony_ci	0x0000d8bc, 0x00000100, 0xffffffff,
7058c2ecf20Sopenharmony_ci	0x000015c0, 0x000c1401, 0xffffffff,
7068c2ecf20Sopenharmony_ci	0x0000264c, 0x000c0400, 0xffffffff,
7078c2ecf20Sopenharmony_ci	0x00002648, 0x000c0400, 0xffffffff,
7088c2ecf20Sopenharmony_ci	0x00002650, 0x000c0400, 0xffffffff,
7098c2ecf20Sopenharmony_ci	0x000020b8, 0x000c0400, 0xffffffff,
7108c2ecf20Sopenharmony_ci	0x000020bc, 0x000c0400, 0xffffffff,
7118c2ecf20Sopenharmony_ci	0x000020c0, 0x000c0c80, 0xffffffff,
7128c2ecf20Sopenharmony_ci	0x0000f4a0, 0x000000c0, 0xffffffff,
7138c2ecf20Sopenharmony_ci	0x0000f4a4, 0x00680fff, 0xffffffff,
7148c2ecf20Sopenharmony_ci	0x00002f50, 0x00000903, 0xffffffff,
7158c2ecf20Sopenharmony_ci	0x000004c8, 0x00000000, 0xffffffff,
7168c2ecf20Sopenharmony_ci	0x000064ec, 0x00000000, 0xffffffff,
7178c2ecf20Sopenharmony_ci	0x00000c7c, 0x00000000, 0xffffffff,
7188c2ecf20Sopenharmony_ci	0x00008dfc, 0x00000000, 0xffffffff
7198c2ecf20Sopenharmony_ci};
7208c2ecf20Sopenharmony_ci#define CAYMAN_SYSLS_ENABLE_LENGTH sizeof(cayman_sysls_enable) / (3 * sizeof(u32))
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_cistruct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev);
7238c2ecf20Sopenharmony_cistruct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ciextern int ni_mc_load_microcode(struct radeon_device *rdev);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_cistruct ni_power_info *ni_get_pi(struct radeon_device *rdev)
7288c2ecf20Sopenharmony_ci{
7298c2ecf20Sopenharmony_ci	struct ni_power_info *pi = rdev->pm.dpm.priv;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	return pi;
7328c2ecf20Sopenharmony_ci}
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_cistruct ni_ps *ni_get_ps(struct radeon_ps *rps)
7358c2ecf20Sopenharmony_ci{
7368c2ecf20Sopenharmony_ci	struct ni_ps *ps = rps->ps_priv;
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	return ps;
7398c2ecf20Sopenharmony_ci}
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_cistatic void ni_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff,
7428c2ecf20Sopenharmony_ci						     u16 v, s32 t,
7438c2ecf20Sopenharmony_ci						     u32 ileakage,
7448c2ecf20Sopenharmony_ci						     u32 *leakage)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	s64 kt, kv, leakage_w, i_leakage, vddc, temperature;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	i_leakage = div64_s64(drm_int2fixp(ileakage), 1000);
7498c2ecf20Sopenharmony_ci	vddc = div64_s64(drm_int2fixp(v), 1000);
7508c2ecf20Sopenharmony_ci	temperature = div64_s64(drm_int2fixp(t), 1000);
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	kt = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->at), 1000),
7538c2ecf20Sopenharmony_ci			  drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bt), 1000), temperature)));
7548c2ecf20Sopenharmony_ci	kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 1000),
7558c2ecf20Sopenharmony_ci			  drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 1000), vddc)));
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci	*leakage = drm_fixp2int(leakage_w * 1000);
7608c2ecf20Sopenharmony_ci}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_cistatic void ni_calculate_leakage_for_v_and_t(struct radeon_device *rdev,
7638c2ecf20Sopenharmony_ci					     const struct ni_leakage_coeffients *coeff,
7648c2ecf20Sopenharmony_ci					     u16 v,
7658c2ecf20Sopenharmony_ci					     s32 t,
7668c2ecf20Sopenharmony_ci					     u32 i_leakage,
7678c2ecf20Sopenharmony_ci					     u32 *leakage)
7688c2ecf20Sopenharmony_ci{
7698c2ecf20Sopenharmony_ci	ni_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_cibool ni_dpm_vblank_too_short(struct radeon_device *rdev)
7738c2ecf20Sopenharmony_ci{
7748c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
7758c2ecf20Sopenharmony_ci	u32 vblank_time = r600_dpm_get_vblank_time(rdev);
7768c2ecf20Sopenharmony_ci	/* we never hit the non-gddr5 limit so disable it */
7778c2ecf20Sopenharmony_ci	u32 switch_limit = pi->mem_gddr5 ? 450 : 0;
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	if (vblank_time < switch_limit)
7808c2ecf20Sopenharmony_ci		return true;
7818c2ecf20Sopenharmony_ci	else
7828c2ecf20Sopenharmony_ci		return false;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_cistatic void ni_apply_state_adjust_rules(struct radeon_device *rdev,
7878c2ecf20Sopenharmony_ci					struct radeon_ps *rps)
7888c2ecf20Sopenharmony_ci{
7898c2ecf20Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
7908c2ecf20Sopenharmony_ci	struct radeon_clock_and_voltage_limits *max_limits;
7918c2ecf20Sopenharmony_ci	bool disable_mclk_switching;
7928c2ecf20Sopenharmony_ci	u32 mclk;
7938c2ecf20Sopenharmony_ci	u16 vddci;
7948c2ecf20Sopenharmony_ci	int i;
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
7978c2ecf20Sopenharmony_ci	    ni_dpm_vblank_too_short(rdev))
7988c2ecf20Sopenharmony_ci		disable_mclk_switching = true;
7998c2ecf20Sopenharmony_ci	else
8008c2ecf20Sopenharmony_ci		disable_mclk_switching = false;
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.ac_power)
8038c2ecf20Sopenharmony_ci		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
8048c2ecf20Sopenharmony_ci	else
8058c2ecf20Sopenharmony_ci		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.ac_power == false) {
8088c2ecf20Sopenharmony_ci		for (i = 0; i < ps->performance_level_count; i++) {
8098c2ecf20Sopenharmony_ci			if (ps->performance_levels[i].mclk > max_limits->mclk)
8108c2ecf20Sopenharmony_ci				ps->performance_levels[i].mclk = max_limits->mclk;
8118c2ecf20Sopenharmony_ci			if (ps->performance_levels[i].sclk > max_limits->sclk)
8128c2ecf20Sopenharmony_ci				ps->performance_levels[i].sclk = max_limits->sclk;
8138c2ecf20Sopenharmony_ci			if (ps->performance_levels[i].vddc > max_limits->vddc)
8148c2ecf20Sopenharmony_ci				ps->performance_levels[i].vddc = max_limits->vddc;
8158c2ecf20Sopenharmony_ci			if (ps->performance_levels[i].vddci > max_limits->vddci)
8168c2ecf20Sopenharmony_ci				ps->performance_levels[i].vddci = max_limits->vddci;
8178c2ecf20Sopenharmony_ci		}
8188c2ecf20Sopenharmony_ci	}
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	/* XXX validate the min clocks required for display */
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	/* adjust low state */
8238c2ecf20Sopenharmony_ci	if (disable_mclk_switching) {
8248c2ecf20Sopenharmony_ci		ps->performance_levels[0].mclk =
8258c2ecf20Sopenharmony_ci			ps->performance_levels[ps->performance_level_count - 1].mclk;
8268c2ecf20Sopenharmony_ci		ps->performance_levels[0].vddci =
8278c2ecf20Sopenharmony_ci			ps->performance_levels[ps->performance_level_count - 1].vddci;
8288c2ecf20Sopenharmony_ci	}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
8318c2ecf20Sopenharmony_ci				  &ps->performance_levels[0].sclk,
8328c2ecf20Sopenharmony_ci				  &ps->performance_levels[0].mclk);
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	for (i = 1; i < ps->performance_level_count; i++) {
8358c2ecf20Sopenharmony_ci		if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
8368c2ecf20Sopenharmony_ci			ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
8378c2ecf20Sopenharmony_ci		if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
8388c2ecf20Sopenharmony_ci			ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
8398c2ecf20Sopenharmony_ci	}
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	/* adjust remaining states */
8428c2ecf20Sopenharmony_ci	if (disable_mclk_switching) {
8438c2ecf20Sopenharmony_ci		mclk = ps->performance_levels[0].mclk;
8448c2ecf20Sopenharmony_ci		vddci = ps->performance_levels[0].vddci;
8458c2ecf20Sopenharmony_ci		for (i = 1; i < ps->performance_level_count; i++) {
8468c2ecf20Sopenharmony_ci			if (mclk < ps->performance_levels[i].mclk)
8478c2ecf20Sopenharmony_ci				mclk = ps->performance_levels[i].mclk;
8488c2ecf20Sopenharmony_ci			if (vddci < ps->performance_levels[i].vddci)
8498c2ecf20Sopenharmony_ci				vddci = ps->performance_levels[i].vddci;
8508c2ecf20Sopenharmony_ci		}
8518c2ecf20Sopenharmony_ci		for (i = 0; i < ps->performance_level_count; i++) {
8528c2ecf20Sopenharmony_ci			ps->performance_levels[i].mclk = mclk;
8538c2ecf20Sopenharmony_ci			ps->performance_levels[i].vddci = vddci;
8548c2ecf20Sopenharmony_ci		}
8558c2ecf20Sopenharmony_ci	} else {
8568c2ecf20Sopenharmony_ci		for (i = 1; i < ps->performance_level_count; i++) {
8578c2ecf20Sopenharmony_ci			if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk)
8588c2ecf20Sopenharmony_ci				ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk;
8598c2ecf20Sopenharmony_ci			if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci)
8608c2ecf20Sopenharmony_ci				ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci;
8618c2ecf20Sopenharmony_ci		}
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	for (i = 1; i < ps->performance_level_count; i++)
8658c2ecf20Sopenharmony_ci		btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
8668c2ecf20Sopenharmony_ci					  &ps->performance_levels[i].sclk,
8678c2ecf20Sopenharmony_ci					  &ps->performance_levels[i].mclk);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++)
8708c2ecf20Sopenharmony_ci		btc_adjust_clock_combinations(rdev, max_limits,
8718c2ecf20Sopenharmony_ci					      &ps->performance_levels[i]);
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
8748c2ecf20Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
8758c2ecf20Sopenharmony_ci						   ps->performance_levels[i].sclk,
8768c2ecf20Sopenharmony_ci						   max_limits->vddc,  &ps->performance_levels[i].vddc);
8778c2ecf20Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
8788c2ecf20Sopenharmony_ci						   ps->performance_levels[i].mclk,
8798c2ecf20Sopenharmony_ci						   max_limits->vddci, &ps->performance_levels[i].vddci);
8808c2ecf20Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
8818c2ecf20Sopenharmony_ci						   ps->performance_levels[i].mclk,
8828c2ecf20Sopenharmony_ci						   max_limits->vddc,  &ps->performance_levels[i].vddc);
8838c2ecf20Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
8848c2ecf20Sopenharmony_ci						   rdev->clock.current_dispclk,
8858c2ecf20Sopenharmony_ci						   max_limits->vddc,  &ps->performance_levels[i].vddc);
8868c2ecf20Sopenharmony_ci	}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
8898c2ecf20Sopenharmony_ci		btc_apply_voltage_delta_rules(rdev,
8908c2ecf20Sopenharmony_ci					      max_limits->vddc, max_limits->vddci,
8918c2ecf20Sopenharmony_ci					      &ps->performance_levels[i].vddc,
8928c2ecf20Sopenharmony_ci					      &ps->performance_levels[i].vddci);
8938c2ecf20Sopenharmony_ci	}
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	ps->dc_compatible = true;
8968c2ecf20Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
8978c2ecf20Sopenharmony_ci		if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
8988c2ecf20Sopenharmony_ci			ps->dc_compatible = false;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci		if (ps->performance_levels[i].vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
9018c2ecf20Sopenharmony_ci			ps->performance_levels[i].flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
9028c2ecf20Sopenharmony_ci	}
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_cistatic void ni_cg_clockgating_default(struct radeon_device *rdev)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	u32 count;
9088c2ecf20Sopenharmony_ci	const u32 *ps = NULL;
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	ps = (const u32 *)&cayman_cgcg_cgls_default;
9118c2ecf20Sopenharmony_ci	count = CAYMAN_CGCG_CGLS_DEFAULT_LENGTH;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
9148c2ecf20Sopenharmony_ci}
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_cistatic void ni_gfx_clockgating_enable(struct radeon_device *rdev,
9178c2ecf20Sopenharmony_ci				      bool enable)
9188c2ecf20Sopenharmony_ci{
9198c2ecf20Sopenharmony_ci	u32 count;
9208c2ecf20Sopenharmony_ci	const u32 *ps = NULL;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	if (enable) {
9238c2ecf20Sopenharmony_ci		ps = (const u32 *)&cayman_cgcg_cgls_enable;
9248c2ecf20Sopenharmony_ci		count = CAYMAN_CGCG_CGLS_ENABLE_LENGTH;
9258c2ecf20Sopenharmony_ci	} else {
9268c2ecf20Sopenharmony_ci		ps = (const u32 *)&cayman_cgcg_cgls_disable;
9278c2ecf20Sopenharmony_ci		count = CAYMAN_CGCG_CGLS_DISABLE_LENGTH;
9288c2ecf20Sopenharmony_ci	}
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
9318c2ecf20Sopenharmony_ci}
9328c2ecf20Sopenharmony_ci
9338c2ecf20Sopenharmony_cistatic void ni_mg_clockgating_default(struct radeon_device *rdev)
9348c2ecf20Sopenharmony_ci{
9358c2ecf20Sopenharmony_ci	u32 count;
9368c2ecf20Sopenharmony_ci	const u32 *ps = NULL;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	ps = (const u32 *)&cayman_mgcg_default;
9398c2ecf20Sopenharmony_ci	count = CAYMAN_MGCG_DEFAULT_LENGTH;
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
9428c2ecf20Sopenharmony_ci}
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_cistatic void ni_mg_clockgating_enable(struct radeon_device *rdev,
9458c2ecf20Sopenharmony_ci				     bool enable)
9468c2ecf20Sopenharmony_ci{
9478c2ecf20Sopenharmony_ci	u32 count;
9488c2ecf20Sopenharmony_ci	const u32 *ps = NULL;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	if (enable) {
9518c2ecf20Sopenharmony_ci		ps = (const u32 *)&cayman_mgcg_enable;
9528c2ecf20Sopenharmony_ci		count = CAYMAN_MGCG_ENABLE_LENGTH;
9538c2ecf20Sopenharmony_ci	} else {
9548c2ecf20Sopenharmony_ci		ps = (const u32 *)&cayman_mgcg_disable;
9558c2ecf20Sopenharmony_ci		count = CAYMAN_MGCG_DISABLE_LENGTH;
9568c2ecf20Sopenharmony_ci	}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
9598c2ecf20Sopenharmony_ci}
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_cistatic void ni_ls_clockgating_default(struct radeon_device *rdev)
9628c2ecf20Sopenharmony_ci{
9638c2ecf20Sopenharmony_ci	u32 count;
9648c2ecf20Sopenharmony_ci	const u32 *ps = NULL;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	ps = (const u32 *)&cayman_sysls_default;
9678c2ecf20Sopenharmony_ci	count = CAYMAN_SYSLS_DEFAULT_LENGTH;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
9708c2ecf20Sopenharmony_ci}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_cistatic void ni_ls_clockgating_enable(struct radeon_device *rdev,
9738c2ecf20Sopenharmony_ci				     bool enable)
9748c2ecf20Sopenharmony_ci{
9758c2ecf20Sopenharmony_ci	u32 count;
9768c2ecf20Sopenharmony_ci	const u32 *ps = NULL;
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	if (enable) {
9798c2ecf20Sopenharmony_ci		ps = (const u32 *)&cayman_sysls_enable;
9808c2ecf20Sopenharmony_ci		count = CAYMAN_SYSLS_ENABLE_LENGTH;
9818c2ecf20Sopenharmony_ci	} else {
9828c2ecf20Sopenharmony_ci		ps = (const u32 *)&cayman_sysls_disable;
9838c2ecf20Sopenharmony_ci		count = CAYMAN_SYSLS_DISABLE_LENGTH;
9848c2ecf20Sopenharmony_ci	}
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci}
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_cistatic int ni_patch_single_dependency_table_based_on_leakage(struct radeon_device *rdev,
9918c2ecf20Sopenharmony_ci							     struct radeon_clock_voltage_dependency_table *table)
9928c2ecf20Sopenharmony_ci{
9938c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
9948c2ecf20Sopenharmony_ci	u32 i;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	if (table) {
9978c2ecf20Sopenharmony_ci		for (i = 0; i < table->count; i++) {
9988c2ecf20Sopenharmony_ci			if (0xff01 == table->entries[i].v) {
9998c2ecf20Sopenharmony_ci				if (pi->max_vddc == 0)
10008c2ecf20Sopenharmony_ci					return -EINVAL;
10018c2ecf20Sopenharmony_ci				table->entries[i].v = pi->max_vddc;
10028c2ecf20Sopenharmony_ci			}
10038c2ecf20Sopenharmony_ci		}
10048c2ecf20Sopenharmony_ci	}
10058c2ecf20Sopenharmony_ci	return 0;
10068c2ecf20Sopenharmony_ci}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_cistatic int ni_patch_dependency_tables_based_on_leakage(struct radeon_device *rdev)
10098c2ecf20Sopenharmony_ci{
10108c2ecf20Sopenharmony_ci	int ret = 0;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	ret = ni_patch_single_dependency_table_based_on_leakage(rdev,
10138c2ecf20Sopenharmony_ci								&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk);
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	ret = ni_patch_single_dependency_table_based_on_leakage(rdev,
10168c2ecf20Sopenharmony_ci								&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk);
10178c2ecf20Sopenharmony_ci	return ret;
10188c2ecf20Sopenharmony_ci}
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_cistatic void ni_stop_dpm(struct radeon_device *rdev)
10218c2ecf20Sopenharmony_ci{
10228c2ecf20Sopenharmony_ci	WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
10238c2ecf20Sopenharmony_ci}
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci#if 0
10268c2ecf20Sopenharmony_cistatic int ni_notify_hw_of_power_source(struct radeon_device *rdev,
10278c2ecf20Sopenharmony_ci					bool ac_power)
10288c2ecf20Sopenharmony_ci{
10298c2ecf20Sopenharmony_ci	if (ac_power)
10308c2ecf20Sopenharmony_ci		return (rv770_send_msg_to_smc(rdev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ?
10318c2ecf20Sopenharmony_ci			0 : -EINVAL;
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	return 0;
10348c2ecf20Sopenharmony_ci}
10358c2ecf20Sopenharmony_ci#endif
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic PPSMC_Result ni_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
10388c2ecf20Sopenharmony_ci						      PPSMC_Msg msg, u32 parameter)
10398c2ecf20Sopenharmony_ci{
10408c2ecf20Sopenharmony_ci	WREG32(SMC_SCRATCH0, parameter);
10418c2ecf20Sopenharmony_ci	return rv770_send_msg_to_smc(rdev, msg);
10428c2ecf20Sopenharmony_ci}
10438c2ecf20Sopenharmony_ci
10448c2ecf20Sopenharmony_cistatic int ni_restrict_performance_levels_before_switch(struct radeon_device *rdev)
10458c2ecf20Sopenharmony_ci{
10468c2ecf20Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
10478c2ecf20Sopenharmony_ci		return -EINVAL;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	return (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ?
10508c2ecf20Sopenharmony_ci		0 : -EINVAL;
10518c2ecf20Sopenharmony_ci}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ciint ni_dpm_force_performance_level(struct radeon_device *rdev,
10548c2ecf20Sopenharmony_ci				   enum radeon_dpm_forced_level level)
10558c2ecf20Sopenharmony_ci{
10568c2ecf20Sopenharmony_ci	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
10578c2ecf20Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
10588c2ecf20Sopenharmony_ci			return -EINVAL;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)
10618c2ecf20Sopenharmony_ci			return -EINVAL;
10628c2ecf20Sopenharmony_ci	} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
10638c2ecf20Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
10648c2ecf20Sopenharmony_ci			return -EINVAL;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK)
10678c2ecf20Sopenharmony_ci			return -EINVAL;
10688c2ecf20Sopenharmony_ci	} else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
10698c2ecf20Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
10708c2ecf20Sopenharmony_ci			return -EINVAL;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
10738c2ecf20Sopenharmony_ci			return -EINVAL;
10748c2ecf20Sopenharmony_ci	}
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	rdev->pm.dpm.forced_level = level;
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	return 0;
10798c2ecf20Sopenharmony_ci}
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_cistatic void ni_stop_smc(struct radeon_device *rdev)
10828c2ecf20Sopenharmony_ci{
10838c2ecf20Sopenharmony_ci	u32 tmp;
10848c2ecf20Sopenharmony_ci	int i;
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
10878c2ecf20Sopenharmony_ci		tmp = RREG32(LB_SYNC_RESET_SEL) & LB_SYNC_RESET_SEL_MASK;
10888c2ecf20Sopenharmony_ci		if (tmp != 1)
10898c2ecf20Sopenharmony_ci			break;
10908c2ecf20Sopenharmony_ci		udelay(1);
10918c2ecf20Sopenharmony_ci	}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	udelay(100);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	r7xx_stop_smc(rdev);
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic int ni_process_firmware_header(struct radeon_device *rdev)
10998c2ecf20Sopenharmony_ci{
11008c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
11018c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
11028c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
11038c2ecf20Sopenharmony_ci	u32 tmp;
11048c2ecf20Sopenharmony_ci	int ret;
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
11078c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
11088c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_stateTable,
11098c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	if (ret)
11128c2ecf20Sopenharmony_ci		return ret;
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	pi->state_table_start = (u16)tmp;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
11178c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
11188c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_softRegisters,
11198c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	if (ret)
11228c2ecf20Sopenharmony_ci		return ret;
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	pi->soft_regs_start = (u16)tmp;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
11278c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
11288c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable,
11298c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	if (ret)
11328c2ecf20Sopenharmony_ci		return ret;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	eg_pi->mc_reg_table_start = (u16)tmp;
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
11378c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
11388c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_fanTable,
11398c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	if (ret)
11428c2ecf20Sopenharmony_ci		return ret;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	ni_pi->fan_table_start = (u16)tmp;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
11478c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
11488c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable,
11498c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci	if (ret)
11528c2ecf20Sopenharmony_ci		return ret;
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	ni_pi->arb_table_start = (u16)tmp;
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
11578c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
11588c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_cacTable,
11598c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ci	if (ret)
11628c2ecf20Sopenharmony_ci		return ret;
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	ni_pi->cac_table_start = (u16)tmp;
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
11678c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
11688c2ecf20Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_spllTable,
11698c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	if (ret)
11728c2ecf20Sopenharmony_ci		return ret;
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ci	ni_pi->spll_table_start = (u16)tmp;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci
11778c2ecf20Sopenharmony_ci	return ret;
11788c2ecf20Sopenharmony_ci}
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_cistatic void ni_read_clock_registers(struct radeon_device *rdev)
11818c2ecf20Sopenharmony_ci{
11828c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL);
11858c2ecf20Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2);
11868c2ecf20Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3);
11878c2ecf20Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4);
11888c2ecf20Sopenharmony_ci	ni_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM);
11898c2ecf20Sopenharmony_ci	ni_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
11908c2ecf20Sopenharmony_ci	ni_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL);
11918c2ecf20Sopenharmony_ci	ni_pi->clock_registers.mpll_ad_func_cntl_2 = RREG32(MPLL_AD_FUNC_CNTL_2);
11928c2ecf20Sopenharmony_ci	ni_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL);
11938c2ecf20Sopenharmony_ci	ni_pi->clock_registers.mpll_dq_func_cntl_2 = RREG32(MPLL_DQ_FUNC_CNTL_2);
11948c2ecf20Sopenharmony_ci	ni_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL);
11958c2ecf20Sopenharmony_ci	ni_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL);
11968c2ecf20Sopenharmony_ci	ni_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1);
11978c2ecf20Sopenharmony_ci	ni_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2);
11988c2ecf20Sopenharmony_ci}
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci#if 0
12018c2ecf20Sopenharmony_cistatic int ni_enter_ulp_state(struct radeon_device *rdev)
12028c2ecf20Sopenharmony_ci{
12038c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	if (pi->gfx_clock_gating) {
12068c2ecf20Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
12078c2ecf20Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
12088c2ecf20Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
12098c2ecf20Sopenharmony_ci		RREG32(GB_ADDR_CONFIG);
12108c2ecf20Sopenharmony_ci	}
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_SwitchToMinimumPower),
12138c2ecf20Sopenharmony_ci		 ~HOST_SMC_MSG_MASK);
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	udelay(25000);
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	return 0;
12188c2ecf20Sopenharmony_ci}
12198c2ecf20Sopenharmony_ci#endif
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_cistatic void ni_program_response_times(struct radeon_device *rdev)
12228c2ecf20Sopenharmony_ci{
12238c2ecf20Sopenharmony_ci	u32 voltage_response_time, backbias_response_time, acpi_delay_time, vbi_time_out;
12248c2ecf20Sopenharmony_ci	u32 vddc_dly, bb_dly, acpi_dly, vbi_dly, mclk_switch_limit;
12258c2ecf20Sopenharmony_ci	u32 reference_clock;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mvdd_chg_time, 1);
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	voltage_response_time = (u32)rdev->pm.dpm.voltage_response_time;
12308c2ecf20Sopenharmony_ci	backbias_response_time = (u32)rdev->pm.dpm.backbias_response_time;
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	if (voltage_response_time == 0)
12338c2ecf20Sopenharmony_ci		voltage_response_time = 1000;
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci	if (backbias_response_time == 0)
12368c2ecf20Sopenharmony_ci		backbias_response_time = 1000;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	acpi_delay_time = 15000;
12398c2ecf20Sopenharmony_ci	vbi_time_out = 100000;
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	reference_clock = radeon_get_xclk(rdev);
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	vddc_dly = (voltage_response_time  * reference_clock) / 1600;
12448c2ecf20Sopenharmony_ci	bb_dly   = (backbias_response_time * reference_clock) / 1600;
12458c2ecf20Sopenharmony_ci	acpi_dly = (acpi_delay_time * reference_clock) / 1600;
12468c2ecf20Sopenharmony_ci	vbi_dly  = (vbi_time_out * reference_clock) / 1600;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	mclk_switch_limit = (460 * reference_clock) / 100;
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_vreg,  vddc_dly);
12518c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_bbias, bb_dly);
12528c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_acpi,  acpi_dly);
12538c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);
12548c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA);
12558c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mclk_switch_lim, mclk_switch_limit);
12568c2ecf20Sopenharmony_ci}
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_cistatic void ni_populate_smc_voltage_table(struct radeon_device *rdev,
12598c2ecf20Sopenharmony_ci					  struct atom_voltage_table *voltage_table,
12608c2ecf20Sopenharmony_ci					  NISLANDS_SMC_STATETABLE *table)
12618c2ecf20Sopenharmony_ci{
12628c2ecf20Sopenharmony_ci	unsigned int i;
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_ci	for (i = 0; i < voltage_table->count; i++) {
12658c2ecf20Sopenharmony_ci		table->highSMIO[i] = 0;
12668c2ecf20Sopenharmony_ci		table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low);
12678c2ecf20Sopenharmony_ci	}
12688c2ecf20Sopenharmony_ci}
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_cistatic void ni_populate_smc_voltage_tables(struct radeon_device *rdev,
12718c2ecf20Sopenharmony_ci					   NISLANDS_SMC_STATETABLE *table)
12728c2ecf20Sopenharmony_ci{
12738c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
12748c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
12758c2ecf20Sopenharmony_ci	unsigned char i;
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	if (eg_pi->vddc_voltage_table.count) {
12788c2ecf20Sopenharmony_ci		ni_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
12798c2ecf20Sopenharmony_ci		table->voltageMaskTable.highMask[NISLANDS_SMC_VOLTAGEMASK_VDDC] = 0;
12808c2ecf20Sopenharmony_ci		table->voltageMaskTable.lowMask[NISLANDS_SMC_VOLTAGEMASK_VDDC] =
12818c2ecf20Sopenharmony_ci			cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci		for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
12848c2ecf20Sopenharmony_ci			if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
12858c2ecf20Sopenharmony_ci				table->maxVDDCIndexInPPTable = i;
12868c2ecf20Sopenharmony_ci				break;
12878c2ecf20Sopenharmony_ci			}
12888c2ecf20Sopenharmony_ci		}
12898c2ecf20Sopenharmony_ci	}
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	if (eg_pi->vddci_voltage_table.count) {
12928c2ecf20Sopenharmony_ci		ni_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci		table->voltageMaskTable.highMask[NISLANDS_SMC_VOLTAGEMASK_VDDCI] = 0;
12958c2ecf20Sopenharmony_ci		table->voltageMaskTable.lowMask[NISLANDS_SMC_VOLTAGEMASK_VDDCI] =
12968c2ecf20Sopenharmony_ci			cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
12978c2ecf20Sopenharmony_ci	}
12988c2ecf20Sopenharmony_ci}
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_cistatic int ni_populate_voltage_value(struct radeon_device *rdev,
13018c2ecf20Sopenharmony_ci				     struct atom_voltage_table *table,
13028c2ecf20Sopenharmony_ci				     u16 value,
13038c2ecf20Sopenharmony_ci				     NISLANDS_SMC_VOLTAGE_VALUE *voltage)
13048c2ecf20Sopenharmony_ci{
13058c2ecf20Sopenharmony_ci	unsigned int i;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	for (i = 0; i < table->count; i++) {
13088c2ecf20Sopenharmony_ci		if (value <= table->entries[i].value) {
13098c2ecf20Sopenharmony_ci			voltage->index = (u8)i;
13108c2ecf20Sopenharmony_ci			voltage->value = cpu_to_be16(table->entries[i].value);
13118c2ecf20Sopenharmony_ci			break;
13128c2ecf20Sopenharmony_ci		}
13138c2ecf20Sopenharmony_ci	}
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	if (i >= table->count)
13168c2ecf20Sopenharmony_ci		return -EINVAL;
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci	return 0;
13198c2ecf20Sopenharmony_ci}
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_cistatic void ni_populate_mvdd_value(struct radeon_device *rdev,
13228c2ecf20Sopenharmony_ci				   u32 mclk,
13238c2ecf20Sopenharmony_ci				   NISLANDS_SMC_VOLTAGE_VALUE *voltage)
13248c2ecf20Sopenharmony_ci{
13258c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
13268c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	if (!pi->mvdd_control) {
13298c2ecf20Sopenharmony_ci		voltage->index = eg_pi->mvdd_high_index;
13308c2ecf20Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
13318c2ecf20Sopenharmony_ci		return;
13328c2ecf20Sopenharmony_ci	}
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	if (mclk <= pi->mvdd_split_frequency) {
13358c2ecf20Sopenharmony_ci		voltage->index = eg_pi->mvdd_low_index;
13368c2ecf20Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_LOW_VALUE);
13378c2ecf20Sopenharmony_ci	} else {
13388c2ecf20Sopenharmony_ci		voltage->index = eg_pi->mvdd_high_index;
13398c2ecf20Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
13408c2ecf20Sopenharmony_ci	}
13418c2ecf20Sopenharmony_ci}
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_cistatic int ni_get_std_voltage_value(struct radeon_device *rdev,
13448c2ecf20Sopenharmony_ci				    NISLANDS_SMC_VOLTAGE_VALUE *voltage,
13458c2ecf20Sopenharmony_ci				    u16 *std_voltage)
13468c2ecf20Sopenharmony_ci{
13478c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries &&
13488c2ecf20Sopenharmony_ci	    ((u32)voltage->index < rdev->pm.dpm.dyn_state.cac_leakage_table.count))
13498c2ecf20Sopenharmony_ci		*std_voltage = rdev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc;
13508c2ecf20Sopenharmony_ci	else
13518c2ecf20Sopenharmony_ci		*std_voltage = be16_to_cpu(voltage->value);
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_ci	return 0;
13548c2ecf20Sopenharmony_ci}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_cistatic void ni_populate_std_voltage_value(struct radeon_device *rdev,
13578c2ecf20Sopenharmony_ci					  u16 value, u8 index,
13588c2ecf20Sopenharmony_ci					  NISLANDS_SMC_VOLTAGE_VALUE *voltage)
13598c2ecf20Sopenharmony_ci{
13608c2ecf20Sopenharmony_ci	voltage->index = index;
13618c2ecf20Sopenharmony_ci	voltage->value = cpu_to_be16(value);
13628c2ecf20Sopenharmony_ci}
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_cistatic u32 ni_get_smc_power_scaling_factor(struct radeon_device *rdev)
13658c2ecf20Sopenharmony_ci{
13668c2ecf20Sopenharmony_ci	u32 xclk_period;
13678c2ecf20Sopenharmony_ci	u32 xclk = radeon_get_xclk(rdev);
13688c2ecf20Sopenharmony_ci	u32 tmp = RREG32(CG_CAC_CTRL) & TID_CNT_MASK;
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_ci	xclk_period = (1000000000UL / xclk);
13718c2ecf20Sopenharmony_ci	xclk_period /= 10000UL;
13728c2ecf20Sopenharmony_ci
13738c2ecf20Sopenharmony_ci	return tmp * xclk_period;
13748c2ecf20Sopenharmony_ci}
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_cistatic u32 ni_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor)
13778c2ecf20Sopenharmony_ci{
13788c2ecf20Sopenharmony_ci	return (power_in_watts * scaling_factor) << 2;
13798c2ecf20Sopenharmony_ci}
13808c2ecf20Sopenharmony_ci
13818c2ecf20Sopenharmony_cistatic u32 ni_calculate_power_boost_limit(struct radeon_device *rdev,
13828c2ecf20Sopenharmony_ci					  struct radeon_ps *radeon_state,
13838c2ecf20Sopenharmony_ci					  u32 near_tdp_limit)
13848c2ecf20Sopenharmony_ci{
13858c2ecf20Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
13868c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
13878c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
13888c2ecf20Sopenharmony_ci	u32 power_boost_limit = 0;
13898c2ecf20Sopenharmony_ci	int ret;
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	if (ni_pi->enable_power_containment &&
13928c2ecf20Sopenharmony_ci	    ni_pi->use_power_boost_limit) {
13938c2ecf20Sopenharmony_ci		NISLANDS_SMC_VOLTAGE_VALUE vddc;
13948c2ecf20Sopenharmony_ci		u16 std_vddc_med;
13958c2ecf20Sopenharmony_ci		u16 std_vddc_high;
13968c2ecf20Sopenharmony_ci		u64 tmp, n, d;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci		if (state->performance_level_count < 3)
13998c2ecf20Sopenharmony_ci			return 0;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci		ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
14028c2ecf20Sopenharmony_ci						state->performance_levels[state->performance_level_count - 2].vddc,
14038c2ecf20Sopenharmony_ci						&vddc);
14048c2ecf20Sopenharmony_ci		if (ret)
14058c2ecf20Sopenharmony_ci			return 0;
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci		ret = ni_get_std_voltage_value(rdev, &vddc, &std_vddc_med);
14088c2ecf20Sopenharmony_ci		if (ret)
14098c2ecf20Sopenharmony_ci			return 0;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci		ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
14128c2ecf20Sopenharmony_ci						state->performance_levels[state->performance_level_count - 1].vddc,
14138c2ecf20Sopenharmony_ci						&vddc);
14148c2ecf20Sopenharmony_ci		if (ret)
14158c2ecf20Sopenharmony_ci			return 0;
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci		ret = ni_get_std_voltage_value(rdev, &vddc, &std_vddc_high);
14188c2ecf20Sopenharmony_ci		if (ret)
14198c2ecf20Sopenharmony_ci			return 0;
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci		n = ((u64)near_tdp_limit * ((u64)std_vddc_med * (u64)std_vddc_med) * 90);
14228c2ecf20Sopenharmony_ci		d = ((u64)std_vddc_high * (u64)std_vddc_high * 100);
14238c2ecf20Sopenharmony_ci		tmp = div64_u64(n, d);
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci		if (tmp >> 32)
14268c2ecf20Sopenharmony_ci			return 0;
14278c2ecf20Sopenharmony_ci		power_boost_limit = (u32)tmp;
14288c2ecf20Sopenharmony_ci	}
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	return power_boost_limit;
14318c2ecf20Sopenharmony_ci}
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_cistatic int ni_calculate_adjusted_tdp_limits(struct radeon_device *rdev,
14348c2ecf20Sopenharmony_ci					    bool adjust_polarity,
14358c2ecf20Sopenharmony_ci					    u32 tdp_adjustment,
14368c2ecf20Sopenharmony_ci					    u32 *tdp_limit,
14378c2ecf20Sopenharmony_ci					    u32 *near_tdp_limit)
14388c2ecf20Sopenharmony_ci{
14398c2ecf20Sopenharmony_ci	if (tdp_adjustment > (u32)rdev->pm.dpm.tdp_od_limit)
14408c2ecf20Sopenharmony_ci		return -EINVAL;
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	if (adjust_polarity) {
14438c2ecf20Sopenharmony_ci		*tdp_limit = ((100 + tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
14448c2ecf20Sopenharmony_ci		*near_tdp_limit = rdev->pm.dpm.near_tdp_limit + (*tdp_limit - rdev->pm.dpm.tdp_limit);
14458c2ecf20Sopenharmony_ci	} else {
14468c2ecf20Sopenharmony_ci		*tdp_limit = ((100 - tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
14478c2ecf20Sopenharmony_ci		*near_tdp_limit = rdev->pm.dpm.near_tdp_limit - (rdev->pm.dpm.tdp_limit - *tdp_limit);
14488c2ecf20Sopenharmony_ci	}
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	return 0;
14518c2ecf20Sopenharmony_ci}
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_cistatic int ni_populate_smc_tdp_limits(struct radeon_device *rdev,
14548c2ecf20Sopenharmony_ci				      struct radeon_ps *radeon_state)
14558c2ecf20Sopenharmony_ci{
14568c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
14578c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci	if (ni_pi->enable_power_containment) {
14608c2ecf20Sopenharmony_ci		NISLANDS_SMC_STATETABLE *smc_table = &ni_pi->smc_statetable;
14618c2ecf20Sopenharmony_ci		u32 scaling_factor = ni_get_smc_power_scaling_factor(rdev);
14628c2ecf20Sopenharmony_ci		u32 tdp_limit;
14638c2ecf20Sopenharmony_ci		u32 near_tdp_limit;
14648c2ecf20Sopenharmony_ci		u32 power_boost_limit;
14658c2ecf20Sopenharmony_ci		int ret;
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci		if (scaling_factor == 0)
14688c2ecf20Sopenharmony_ci			return -EINVAL;
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci		memset(smc_table, 0, sizeof(NISLANDS_SMC_STATETABLE));
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci		ret = ni_calculate_adjusted_tdp_limits(rdev,
14738c2ecf20Sopenharmony_ci						       false, /* ??? */
14748c2ecf20Sopenharmony_ci						       rdev->pm.dpm.tdp_adjustment,
14758c2ecf20Sopenharmony_ci						       &tdp_limit,
14768c2ecf20Sopenharmony_ci						       &near_tdp_limit);
14778c2ecf20Sopenharmony_ci		if (ret)
14788c2ecf20Sopenharmony_ci			return ret;
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_ci		power_boost_limit = ni_calculate_power_boost_limit(rdev, radeon_state,
14818c2ecf20Sopenharmony_ci								   near_tdp_limit);
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci		smc_table->dpm2Params.TDPLimit =
14848c2ecf20Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc(tdp_limit, scaling_factor));
14858c2ecf20Sopenharmony_ci		smc_table->dpm2Params.NearTDPLimit =
14868c2ecf20Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc(near_tdp_limit, scaling_factor));
14878c2ecf20Sopenharmony_ci		smc_table->dpm2Params.SafePowerLimit =
14888c2ecf20Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc((near_tdp_limit * NISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100,
14898c2ecf20Sopenharmony_ci							   scaling_factor));
14908c2ecf20Sopenharmony_ci		smc_table->dpm2Params.PowerBoostLimit =
14918c2ecf20Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc(power_boost_limit, scaling_factor));
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci		ret = rv770_copy_bytes_to_smc(rdev,
14948c2ecf20Sopenharmony_ci					      (u16)(pi->state_table_start + offsetof(NISLANDS_SMC_STATETABLE, dpm2Params) +
14958c2ecf20Sopenharmony_ci						    offsetof(PP_NIslands_DPM2Parameters, TDPLimit)),
14968c2ecf20Sopenharmony_ci					      (u8 *)(&smc_table->dpm2Params.TDPLimit),
14978c2ecf20Sopenharmony_ci					      sizeof(u32) * 4, pi->sram_end);
14988c2ecf20Sopenharmony_ci		if (ret)
14998c2ecf20Sopenharmony_ci			return ret;
15008c2ecf20Sopenharmony_ci	}
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci	return 0;
15038c2ecf20Sopenharmony_ci}
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ciint ni_copy_and_switch_arb_sets(struct radeon_device *rdev,
15068c2ecf20Sopenharmony_ci				u32 arb_freq_src, u32 arb_freq_dest)
15078c2ecf20Sopenharmony_ci{
15088c2ecf20Sopenharmony_ci	u32 mc_arb_dram_timing;
15098c2ecf20Sopenharmony_ci	u32 mc_arb_dram_timing2;
15108c2ecf20Sopenharmony_ci	u32 burst_time;
15118c2ecf20Sopenharmony_ci	u32 mc_cg_config;
15128c2ecf20Sopenharmony_ci
15138c2ecf20Sopenharmony_ci	switch (arb_freq_src) {
15148c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F0:
15158c2ecf20Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING);
15168c2ecf20Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
15178c2ecf20Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT;
15188c2ecf20Sopenharmony_ci		break;
15198c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F1:
15208c2ecf20Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_1);
15218c2ecf20Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1);
15228c2ecf20Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT;
15238c2ecf20Sopenharmony_ci		break;
15248c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F2:
15258c2ecf20Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_2);
15268c2ecf20Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2);
15278c2ecf20Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT;
15288c2ecf20Sopenharmony_ci		break;
15298c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F3:
15308c2ecf20Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_3);
15318c2ecf20Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3);
15328c2ecf20Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT;
15338c2ecf20Sopenharmony_ci		break;
15348c2ecf20Sopenharmony_ci	default:
15358c2ecf20Sopenharmony_ci		return -EINVAL;
15368c2ecf20Sopenharmony_ci	}
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	switch (arb_freq_dest) {
15398c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F0:
15408c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing);
15418c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
15428c2ecf20Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK);
15438c2ecf20Sopenharmony_ci		break;
15448c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F1:
15458c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
15468c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
15478c2ecf20Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK);
15488c2ecf20Sopenharmony_ci		break;
15498c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F2:
15508c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing);
15518c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2);
15528c2ecf20Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK);
15538c2ecf20Sopenharmony_ci		break;
15548c2ecf20Sopenharmony_ci	case MC_CG_ARB_FREQ_F3:
15558c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing);
15568c2ecf20Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2);
15578c2ecf20Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK);
15588c2ecf20Sopenharmony_ci		break;
15598c2ecf20Sopenharmony_ci	default:
15608c2ecf20Sopenharmony_ci		return -EINVAL;
15618c2ecf20Sopenharmony_ci	}
15628c2ecf20Sopenharmony_ci
15638c2ecf20Sopenharmony_ci	mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F;
15648c2ecf20Sopenharmony_ci	WREG32(MC_CG_CONFIG, mc_cg_config);
15658c2ecf20Sopenharmony_ci	WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK);
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci	return 0;
15688c2ecf20Sopenharmony_ci}
15698c2ecf20Sopenharmony_ci
15708c2ecf20Sopenharmony_cistatic int ni_init_arb_table_index(struct radeon_device *rdev)
15718c2ecf20Sopenharmony_ci{
15728c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
15738c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
15748c2ecf20Sopenharmony_ci	u32 tmp;
15758c2ecf20Sopenharmony_ci	int ret;
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev, ni_pi->arb_table_start,
15788c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
15798c2ecf20Sopenharmony_ci	if (ret)
15808c2ecf20Sopenharmony_ci		return ret;
15818c2ecf20Sopenharmony_ci
15828c2ecf20Sopenharmony_ci	tmp &= 0x00FFFFFF;
15838c2ecf20Sopenharmony_ci	tmp |= ((u32)MC_CG_ARB_FREQ_F1) << 24;
15848c2ecf20Sopenharmony_ci
15858c2ecf20Sopenharmony_ci	return rv770_write_smc_sram_dword(rdev, ni_pi->arb_table_start,
15868c2ecf20Sopenharmony_ci					  tmp, pi->sram_end);
15878c2ecf20Sopenharmony_ci}
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_cistatic int ni_initial_switch_from_arb_f0_to_f1(struct radeon_device *rdev)
15908c2ecf20Sopenharmony_ci{
15918c2ecf20Sopenharmony_ci	return ni_copy_and_switch_arb_sets(rdev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
15928c2ecf20Sopenharmony_ci}
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_cistatic int ni_force_switch_to_arb_f0(struct radeon_device *rdev)
15958c2ecf20Sopenharmony_ci{
15968c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
15978c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
15988c2ecf20Sopenharmony_ci	u32 tmp;
15998c2ecf20Sopenharmony_ci	int ret;
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev, ni_pi->arb_table_start,
16028c2ecf20Sopenharmony_ci					&tmp, pi->sram_end);
16038c2ecf20Sopenharmony_ci	if (ret)
16048c2ecf20Sopenharmony_ci		return ret;
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci	tmp = (tmp >> 24) & 0xff;
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	if (tmp == MC_CG_ARB_FREQ_F0)
16098c2ecf20Sopenharmony_ci		return 0;
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	return ni_copy_and_switch_arb_sets(rdev, tmp, MC_CG_ARB_FREQ_F0);
16128c2ecf20Sopenharmony_ci}
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_cistatic int ni_populate_memory_timing_parameters(struct radeon_device *rdev,
16158c2ecf20Sopenharmony_ci						struct rv7xx_pl *pl,
16168c2ecf20Sopenharmony_ci						SMC_NIslands_MCArbDramTimingRegisterSet *arb_regs)
16178c2ecf20Sopenharmony_ci{
16188c2ecf20Sopenharmony_ci	u32 dram_timing;
16198c2ecf20Sopenharmony_ci	u32 dram_timing2;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	arb_regs->mc_arb_rfsh_rate =
16228c2ecf20Sopenharmony_ci		(u8)rv770_calculate_memory_refresh_rate(rdev, pl->sclk);
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	radeon_atom_set_engine_dram_timings(rdev, pl->sclk, pl->mclk);
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	dram_timing = RREG32(MC_ARB_DRAM_TIMING);
16288c2ecf20Sopenharmony_ci	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci	arb_regs->mc_arb_dram_timing  = cpu_to_be32(dram_timing);
16318c2ecf20Sopenharmony_ci	arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2);
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci	return 0;
16348c2ecf20Sopenharmony_ci}
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_cistatic int ni_do_program_memory_timing_parameters(struct radeon_device *rdev,
16378c2ecf20Sopenharmony_ci						  struct radeon_ps *radeon_state,
16388c2ecf20Sopenharmony_ci						  unsigned int first_arb_set)
16398c2ecf20Sopenharmony_ci{
16408c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
16418c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
16428c2ecf20Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
16438c2ecf20Sopenharmony_ci	SMC_NIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };
16448c2ecf20Sopenharmony_ci	int i, ret = 0;
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
16478c2ecf20Sopenharmony_ci		ret = ni_populate_memory_timing_parameters(rdev, &state->performance_levels[i], &arb_regs);
16488c2ecf20Sopenharmony_ci		if (ret)
16498c2ecf20Sopenharmony_ci			break;
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci		ret = rv770_copy_bytes_to_smc(rdev,
16528c2ecf20Sopenharmony_ci					      (u16)(ni_pi->arb_table_start +
16538c2ecf20Sopenharmony_ci						    offsetof(SMC_NIslands_MCArbDramTimingRegisters, data) +
16548c2ecf20Sopenharmony_ci						    sizeof(SMC_NIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i)),
16558c2ecf20Sopenharmony_ci					      (u8 *)&arb_regs,
16568c2ecf20Sopenharmony_ci					      (u16)sizeof(SMC_NIslands_MCArbDramTimingRegisterSet),
16578c2ecf20Sopenharmony_ci					      pi->sram_end);
16588c2ecf20Sopenharmony_ci		if (ret)
16598c2ecf20Sopenharmony_ci			break;
16608c2ecf20Sopenharmony_ci	}
16618c2ecf20Sopenharmony_ci	return ret;
16628c2ecf20Sopenharmony_ci}
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_cistatic int ni_program_memory_timing_parameters(struct radeon_device *rdev,
16658c2ecf20Sopenharmony_ci					       struct radeon_ps *radeon_new_state)
16668c2ecf20Sopenharmony_ci{
16678c2ecf20Sopenharmony_ci	return ni_do_program_memory_timing_parameters(rdev, radeon_new_state,
16688c2ecf20Sopenharmony_ci						      NISLANDS_DRIVER_STATE_ARB_INDEX);
16698c2ecf20Sopenharmony_ci}
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_cistatic void ni_populate_initial_mvdd_value(struct radeon_device *rdev,
16728c2ecf20Sopenharmony_ci					   struct NISLANDS_SMC_VOLTAGE_VALUE *voltage)
16738c2ecf20Sopenharmony_ci{
16748c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci	voltage->index = eg_pi->mvdd_high_index;
16778c2ecf20Sopenharmony_ci	voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
16788c2ecf20Sopenharmony_ci}
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_cistatic int ni_populate_smc_initial_state(struct radeon_device *rdev,
16818c2ecf20Sopenharmony_ci					 struct radeon_ps *radeon_initial_state,
16828c2ecf20Sopenharmony_ci					 NISLANDS_SMC_STATETABLE *table)
16838c2ecf20Sopenharmony_ci{
16848c2ecf20Sopenharmony_ci	struct ni_ps *initial_state = ni_get_ps(radeon_initial_state);
16858c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
16868c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
16878c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
16888c2ecf20Sopenharmony_ci	u32 reg;
16898c2ecf20Sopenharmony_ci	int ret;
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vMPLL_AD_FUNC_CNTL =
16928c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ad_func_cntl);
16938c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vMPLL_AD_FUNC_CNTL_2 =
16948c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ad_func_cntl_2);
16958c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL =
16968c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_dq_func_cntl);
16978c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL_2 =
16988c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_dq_func_cntl_2);
16998c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vMCLK_PWRMGT_CNTL =
17008c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mclk_pwrmgt_cntl);
17018c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vDLL_CNTL =
17028c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.dll_cntl);
17038c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vMPLL_SS =
17048c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ss1);
17058c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.vMPLL_SS2 =
17068c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ss2);
17078c2ecf20Sopenharmony_ci	table->initialState.levels[0].mclk.mclk_value =
17088c2ecf20Sopenharmony_ci		cpu_to_be32(initial_state->performance_levels[0].mclk);
17098c2ecf20Sopenharmony_ci
17108c2ecf20Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
17118c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl);
17128c2ecf20Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
17138c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_2);
17148c2ecf20Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
17158c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_3);
17168c2ecf20Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 =
17178c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_4);
17188c2ecf20Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM =
17198c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_spread_spectrum);
17208c2ecf20Sopenharmony_ci	table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
17218c2ecf20Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_spread_spectrum_2);
17228c2ecf20Sopenharmony_ci	table->initialState.levels[0].sclk.sclk_value =
17238c2ecf20Sopenharmony_ci		cpu_to_be32(initial_state->performance_levels[0].sclk);
17248c2ecf20Sopenharmony_ci	table->initialState.levels[0].arbRefreshState =
17258c2ecf20Sopenharmony_ci		NISLANDS_INITIAL_STATE_ARB_INDEX;
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	table->initialState.levels[0].ACIndex = 0;
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
17308c2ecf20Sopenharmony_ci					initial_state->performance_levels[0].vddc,
17318c2ecf20Sopenharmony_ci					&table->initialState.levels[0].vddc);
17328c2ecf20Sopenharmony_ci	if (!ret) {
17338c2ecf20Sopenharmony_ci		u16 std_vddc;
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci		ret = ni_get_std_voltage_value(rdev,
17368c2ecf20Sopenharmony_ci					       &table->initialState.levels[0].vddc,
17378c2ecf20Sopenharmony_ci					       &std_vddc);
17388c2ecf20Sopenharmony_ci		if (!ret)
17398c2ecf20Sopenharmony_ci			ni_populate_std_voltage_value(rdev, std_vddc,
17408c2ecf20Sopenharmony_ci						      table->initialState.levels[0].vddc.index,
17418c2ecf20Sopenharmony_ci						      &table->initialState.levels[0].std_vddc);
17428c2ecf20Sopenharmony_ci	}
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	if (eg_pi->vddci_control)
17458c2ecf20Sopenharmony_ci		ni_populate_voltage_value(rdev,
17468c2ecf20Sopenharmony_ci					  &eg_pi->vddci_voltage_table,
17478c2ecf20Sopenharmony_ci					  initial_state->performance_levels[0].vddci,
17488c2ecf20Sopenharmony_ci					  &table->initialState.levels[0].vddci);
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci	ni_populate_initial_mvdd_value(rdev, &table->initialState.levels[0].mvdd);
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci	reg = CG_R(0xffff) | CG_L(0);
17538c2ecf20Sopenharmony_ci	table->initialState.levels[0].aT = cpu_to_be32(reg);
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci	table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp);
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	if (pi->boot_in_gen2)
17588c2ecf20Sopenharmony_ci		table->initialState.levels[0].gen2PCIE = 1;
17598c2ecf20Sopenharmony_ci	else
17608c2ecf20Sopenharmony_ci		table->initialState.levels[0].gen2PCIE = 0;
17618c2ecf20Sopenharmony_ci
17628c2ecf20Sopenharmony_ci	if (pi->mem_gddr5) {
17638c2ecf20Sopenharmony_ci		table->initialState.levels[0].strobeMode =
17648c2ecf20Sopenharmony_ci			cypress_get_strobe_mode_settings(rdev,
17658c2ecf20Sopenharmony_ci							 initial_state->performance_levels[0].mclk);
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_ci		if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold)
17688c2ecf20Sopenharmony_ci			table->initialState.levels[0].mcFlags = NISLANDS_SMC_MC_EDC_RD_FLAG | NISLANDS_SMC_MC_EDC_WR_FLAG;
17698c2ecf20Sopenharmony_ci		else
17708c2ecf20Sopenharmony_ci			table->initialState.levels[0].mcFlags =  0;
17718c2ecf20Sopenharmony_ci	}
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	table->initialState.levelCount = 1;
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	table->initialState.levels[0].dpm2.MaxPS = 0;
17788c2ecf20Sopenharmony_ci	table->initialState.levels[0].dpm2.NearTDPDec = 0;
17798c2ecf20Sopenharmony_ci	table->initialState.levels[0].dpm2.AboveSafeInc = 0;
17808c2ecf20Sopenharmony_ci	table->initialState.levels[0].dpm2.BelowSafeInc = 0;
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	reg = MIN_POWER_MASK | MAX_POWER_MASK;
17838c2ecf20Sopenharmony_ci	table->initialState.levels[0].SQPowerThrottle = cpu_to_be32(reg);
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
17868c2ecf20Sopenharmony_ci	table->initialState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg);
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	return 0;
17898c2ecf20Sopenharmony_ci}
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_cistatic int ni_populate_smc_acpi_state(struct radeon_device *rdev,
17928c2ecf20Sopenharmony_ci				      NISLANDS_SMC_STATETABLE *table)
17938c2ecf20Sopenharmony_ci{
17948c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
17958c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
17968c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
17978c2ecf20Sopenharmony_ci	u32 mpll_ad_func_cntl   = ni_pi->clock_registers.mpll_ad_func_cntl;
17988c2ecf20Sopenharmony_ci	u32 mpll_ad_func_cntl_2 = ni_pi->clock_registers.mpll_ad_func_cntl_2;
17998c2ecf20Sopenharmony_ci	u32 mpll_dq_func_cntl   = ni_pi->clock_registers.mpll_dq_func_cntl;
18008c2ecf20Sopenharmony_ci	u32 mpll_dq_func_cntl_2 = ni_pi->clock_registers.mpll_dq_func_cntl_2;
18018c2ecf20Sopenharmony_ci	u32 spll_func_cntl      = ni_pi->clock_registers.cg_spll_func_cntl;
18028c2ecf20Sopenharmony_ci	u32 spll_func_cntl_2    = ni_pi->clock_registers.cg_spll_func_cntl_2;
18038c2ecf20Sopenharmony_ci	u32 spll_func_cntl_3    = ni_pi->clock_registers.cg_spll_func_cntl_3;
18048c2ecf20Sopenharmony_ci	u32 spll_func_cntl_4    = ni_pi->clock_registers.cg_spll_func_cntl_4;
18058c2ecf20Sopenharmony_ci	u32 mclk_pwrmgt_cntl    = ni_pi->clock_registers.mclk_pwrmgt_cntl;
18068c2ecf20Sopenharmony_ci	u32 dll_cntl            = ni_pi->clock_registers.dll_cntl;
18078c2ecf20Sopenharmony_ci	u32 reg;
18088c2ecf20Sopenharmony_ci	int ret;
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci	table->ACPIState = table->initialState;
18118c2ecf20Sopenharmony_ci
18128c2ecf20Sopenharmony_ci	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	if (pi->acpi_vddc) {
18158c2ecf20Sopenharmony_ci		ret = ni_populate_voltage_value(rdev,
18168c2ecf20Sopenharmony_ci						&eg_pi->vddc_voltage_table,
18178c2ecf20Sopenharmony_ci						pi->acpi_vddc, &table->ACPIState.levels[0].vddc);
18188c2ecf20Sopenharmony_ci		if (!ret) {
18198c2ecf20Sopenharmony_ci			u16 std_vddc;
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci			ret = ni_get_std_voltage_value(rdev,
18228c2ecf20Sopenharmony_ci						       &table->ACPIState.levels[0].vddc, &std_vddc);
18238c2ecf20Sopenharmony_ci			if (!ret)
18248c2ecf20Sopenharmony_ci				ni_populate_std_voltage_value(rdev, std_vddc,
18258c2ecf20Sopenharmony_ci							      table->ACPIState.levels[0].vddc.index,
18268c2ecf20Sopenharmony_ci							      &table->ACPIState.levels[0].std_vddc);
18278c2ecf20Sopenharmony_ci		}
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci		if (pi->pcie_gen2) {
18308c2ecf20Sopenharmony_ci			if (pi->acpi_pcie_gen2)
18318c2ecf20Sopenharmony_ci				table->ACPIState.levels[0].gen2PCIE = 1;
18328c2ecf20Sopenharmony_ci			else
18338c2ecf20Sopenharmony_ci				table->ACPIState.levels[0].gen2PCIE = 0;
18348c2ecf20Sopenharmony_ci		} else {
18358c2ecf20Sopenharmony_ci			table->ACPIState.levels[0].gen2PCIE = 0;
18368c2ecf20Sopenharmony_ci		}
18378c2ecf20Sopenharmony_ci	} else {
18388c2ecf20Sopenharmony_ci		ret = ni_populate_voltage_value(rdev,
18398c2ecf20Sopenharmony_ci						&eg_pi->vddc_voltage_table,
18408c2ecf20Sopenharmony_ci						pi->min_vddc_in_table,
18418c2ecf20Sopenharmony_ci						&table->ACPIState.levels[0].vddc);
18428c2ecf20Sopenharmony_ci		if (!ret) {
18438c2ecf20Sopenharmony_ci			u16 std_vddc;
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci			ret = ni_get_std_voltage_value(rdev,
18468c2ecf20Sopenharmony_ci						       &table->ACPIState.levels[0].vddc,
18478c2ecf20Sopenharmony_ci						       &std_vddc);
18488c2ecf20Sopenharmony_ci			if (!ret)
18498c2ecf20Sopenharmony_ci				ni_populate_std_voltage_value(rdev, std_vddc,
18508c2ecf20Sopenharmony_ci							      table->ACPIState.levels[0].vddc.index,
18518c2ecf20Sopenharmony_ci							      &table->ACPIState.levels[0].std_vddc);
18528c2ecf20Sopenharmony_ci		}
18538c2ecf20Sopenharmony_ci		table->ACPIState.levels[0].gen2PCIE = 0;
18548c2ecf20Sopenharmony_ci	}
18558c2ecf20Sopenharmony_ci
18568c2ecf20Sopenharmony_ci	if (eg_pi->acpi_vddci) {
18578c2ecf20Sopenharmony_ci		if (eg_pi->vddci_control)
18588c2ecf20Sopenharmony_ci			ni_populate_voltage_value(rdev,
18598c2ecf20Sopenharmony_ci						  &eg_pi->vddci_voltage_table,
18608c2ecf20Sopenharmony_ci						  eg_pi->acpi_vddci,
18618c2ecf20Sopenharmony_ci						  &table->ACPIState.levels[0].vddci);
18628c2ecf20Sopenharmony_ci	}
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	mpll_ad_func_cntl &= ~PDNB;
18668c2ecf20Sopenharmony_ci
18678c2ecf20Sopenharmony_ci	mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	if (pi->mem_gddr5)
18708c2ecf20Sopenharmony_ci		mpll_dq_func_cntl &= ~PDNB;
18718c2ecf20Sopenharmony_ci	mpll_dq_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN | BYPASS;
18728c2ecf20Sopenharmony_ci
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	mclk_pwrmgt_cntl |= (MRDCKA0_RESET |
18758c2ecf20Sopenharmony_ci			     MRDCKA1_RESET |
18768c2ecf20Sopenharmony_ci			     MRDCKB0_RESET |
18778c2ecf20Sopenharmony_ci			     MRDCKB1_RESET |
18788c2ecf20Sopenharmony_ci			     MRDCKC0_RESET |
18798c2ecf20Sopenharmony_ci			     MRDCKC1_RESET |
18808c2ecf20Sopenharmony_ci			     MRDCKD0_RESET |
18818c2ecf20Sopenharmony_ci			     MRDCKD1_RESET);
18828c2ecf20Sopenharmony_ci
18838c2ecf20Sopenharmony_ci	mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
18848c2ecf20Sopenharmony_ci			      MRDCKA1_PDNB |
18858c2ecf20Sopenharmony_ci			      MRDCKB0_PDNB |
18868c2ecf20Sopenharmony_ci			      MRDCKB1_PDNB |
18878c2ecf20Sopenharmony_ci			      MRDCKC0_PDNB |
18888c2ecf20Sopenharmony_ci			      MRDCKC1_PDNB |
18898c2ecf20Sopenharmony_ci			      MRDCKD0_PDNB |
18908c2ecf20Sopenharmony_ci			      MRDCKD1_PDNB);
18918c2ecf20Sopenharmony_ci
18928c2ecf20Sopenharmony_ci	dll_cntl |= (MRDCKA0_BYPASS |
18938c2ecf20Sopenharmony_ci		     MRDCKA1_BYPASS |
18948c2ecf20Sopenharmony_ci		     MRDCKB0_BYPASS |
18958c2ecf20Sopenharmony_ci		     MRDCKB1_BYPASS |
18968c2ecf20Sopenharmony_ci		     MRDCKC0_BYPASS |
18978c2ecf20Sopenharmony_ci		     MRDCKC1_BYPASS |
18988c2ecf20Sopenharmony_ci		     MRDCKD0_BYPASS |
18998c2ecf20Sopenharmony_ci		     MRDCKD1_BYPASS);
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
19028c2ecf20Sopenharmony_ci	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
19058c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].mclk.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
19068c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
19078c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
19088c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].mclk.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
19098c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].mclk.vDLL_CNTL = cpu_to_be32(dll_cntl);
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].mclk.mclk_value = 0;
19128c2ecf20Sopenharmony_ci
19138c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
19148c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
19158c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
19168c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(spll_func_cntl_4);
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].sclk.sclk_value = 0;
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	ni_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
19218c2ecf20Sopenharmony_ci
19228c2ecf20Sopenharmony_ci	if (eg_pi->dynamic_ac_timing)
19238c2ecf20Sopenharmony_ci		table->ACPIState.levels[0].ACIndex = 1;
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].dpm2.MaxPS = 0;
19268c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].dpm2.NearTDPDec = 0;
19278c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].dpm2.AboveSafeInc = 0;
19288c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].dpm2.BelowSafeInc = 0;
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	reg = MIN_POWER_MASK | MAX_POWER_MASK;
19318c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].SQPowerThrottle = cpu_to_be32(reg);
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_ci	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
19348c2ecf20Sopenharmony_ci	table->ACPIState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg);
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	return 0;
19378c2ecf20Sopenharmony_ci}
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_cistatic int ni_init_smc_table(struct radeon_device *rdev)
19408c2ecf20Sopenharmony_ci{
19418c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
19428c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
19438c2ecf20Sopenharmony_ci	int ret;
19448c2ecf20Sopenharmony_ci	struct radeon_ps *radeon_boot_state = rdev->pm.dpm.boot_ps;
19458c2ecf20Sopenharmony_ci	NISLANDS_SMC_STATETABLE *table = &ni_pi->smc_statetable;
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	memset(table, 0, sizeof(NISLANDS_SMC_STATETABLE));
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_ci	ni_populate_smc_voltage_tables(rdev, table);
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci	switch (rdev->pm.int_thermal_type) {
19528c2ecf20Sopenharmony_ci	case THERMAL_TYPE_NI:
19538c2ecf20Sopenharmony_ci	case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
19548c2ecf20Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
19558c2ecf20Sopenharmony_ci		break;
19568c2ecf20Sopenharmony_ci	case THERMAL_TYPE_NONE:
19578c2ecf20Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;
19588c2ecf20Sopenharmony_ci		break;
19598c2ecf20Sopenharmony_ci	default:
19608c2ecf20Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
19618c2ecf20Sopenharmony_ci		break;
19628c2ecf20Sopenharmony_ci	}
19638c2ecf20Sopenharmony_ci
19648c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)
19658c2ecf20Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT)
19688c2ecf20Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT;
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
19718c2ecf20Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
19728c2ecf20Sopenharmony_ci
19738c2ecf20Sopenharmony_ci	if (pi->mem_gddr5)
19748c2ecf20Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	ret = ni_populate_smc_initial_state(rdev, radeon_boot_state, table);
19778c2ecf20Sopenharmony_ci	if (ret)
19788c2ecf20Sopenharmony_ci		return ret;
19798c2ecf20Sopenharmony_ci
19808c2ecf20Sopenharmony_ci	ret = ni_populate_smc_acpi_state(rdev, table);
19818c2ecf20Sopenharmony_ci	if (ret)
19828c2ecf20Sopenharmony_ci		return ret;
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	table->driverState = table->initialState;
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci	table->ULVState = table->initialState;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	ret = ni_do_program_memory_timing_parameters(rdev, radeon_boot_state,
19898c2ecf20Sopenharmony_ci						     NISLANDS_INITIAL_STATE_ARB_INDEX);
19908c2ecf20Sopenharmony_ci	if (ret)
19918c2ecf20Sopenharmony_ci		return ret;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, pi->state_table_start, (u8 *)table,
19948c2ecf20Sopenharmony_ci				       sizeof(NISLANDS_SMC_STATETABLE), pi->sram_end);
19958c2ecf20Sopenharmony_ci}
19968c2ecf20Sopenharmony_ci
19978c2ecf20Sopenharmony_cistatic int ni_calculate_sclk_params(struct radeon_device *rdev,
19988c2ecf20Sopenharmony_ci				    u32 engine_clock,
19998c2ecf20Sopenharmony_ci				    NISLANDS_SMC_SCLK_VALUE *sclk)
20008c2ecf20Sopenharmony_ci{
20018c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
20028c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
20038c2ecf20Sopenharmony_ci	struct atom_clock_dividers dividers;
20048c2ecf20Sopenharmony_ci	u32 spll_func_cntl = ni_pi->clock_registers.cg_spll_func_cntl;
20058c2ecf20Sopenharmony_ci	u32 spll_func_cntl_2 = ni_pi->clock_registers.cg_spll_func_cntl_2;
20068c2ecf20Sopenharmony_ci	u32 spll_func_cntl_3 = ni_pi->clock_registers.cg_spll_func_cntl_3;
20078c2ecf20Sopenharmony_ci	u32 spll_func_cntl_4 = ni_pi->clock_registers.cg_spll_func_cntl_4;
20088c2ecf20Sopenharmony_ci	u32 cg_spll_spread_spectrum = ni_pi->clock_registers.cg_spll_spread_spectrum;
20098c2ecf20Sopenharmony_ci	u32 cg_spll_spread_spectrum_2 = ni_pi->clock_registers.cg_spll_spread_spectrum_2;
20108c2ecf20Sopenharmony_ci	u64 tmp;
20118c2ecf20Sopenharmony_ci	u32 reference_clock = rdev->clock.spll.reference_freq;
20128c2ecf20Sopenharmony_ci	u32 reference_divider;
20138c2ecf20Sopenharmony_ci	u32 fbdiv;
20148c2ecf20Sopenharmony_ci	int ret;
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
20178c2ecf20Sopenharmony_ci					     engine_clock, false, &dividers);
20188c2ecf20Sopenharmony_ci	if (ret)
20198c2ecf20Sopenharmony_ci		return ret;
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_ci	reference_divider = 1 + dividers.ref_div;
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ci	tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16834;
20258c2ecf20Sopenharmony_ci	do_div(tmp, reference_clock);
20268c2ecf20Sopenharmony_ci	fbdiv = (u32) tmp;
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK);
20298c2ecf20Sopenharmony_ci	spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
20308c2ecf20Sopenharmony_ci	spll_func_cntl |= SPLL_PDIV_A(dividers.post_div);
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
20338c2ecf20Sopenharmony_ci	spll_func_cntl_2 |= SCLK_MUX_SEL(2);
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
20368c2ecf20Sopenharmony_ci	spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
20378c2ecf20Sopenharmony_ci	spll_func_cntl_3 |= SPLL_DITHEN;
20388c2ecf20Sopenharmony_ci
20398c2ecf20Sopenharmony_ci	if (pi->sclk_ss) {
20408c2ecf20Sopenharmony_ci		struct radeon_atom_ss ss;
20418c2ecf20Sopenharmony_ci		u32 vco_freq = engine_clock * dividers.post_div;
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
20448c2ecf20Sopenharmony_ci						     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
20458c2ecf20Sopenharmony_ci			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
20468c2ecf20Sopenharmony_ci			u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
20478c2ecf20Sopenharmony_ci
20488c2ecf20Sopenharmony_ci			cg_spll_spread_spectrum &= ~CLK_S_MASK;
20498c2ecf20Sopenharmony_ci			cg_spll_spread_spectrum |= CLK_S(clk_s);
20508c2ecf20Sopenharmony_ci			cg_spll_spread_spectrum |= SSEN;
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci			cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
20538c2ecf20Sopenharmony_ci			cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
20548c2ecf20Sopenharmony_ci		}
20558c2ecf20Sopenharmony_ci	}
20568c2ecf20Sopenharmony_ci
20578c2ecf20Sopenharmony_ci	sclk->sclk_value = engine_clock;
20588c2ecf20Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl;
20598c2ecf20Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2;
20608c2ecf20Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3;
20618c2ecf20Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4;
20628c2ecf20Sopenharmony_ci	sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum;
20638c2ecf20Sopenharmony_ci	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2;
20648c2ecf20Sopenharmony_ci
20658c2ecf20Sopenharmony_ci	return 0;
20668c2ecf20Sopenharmony_ci}
20678c2ecf20Sopenharmony_ci
20688c2ecf20Sopenharmony_cistatic int ni_populate_sclk_value(struct radeon_device *rdev,
20698c2ecf20Sopenharmony_ci				  u32 engine_clock,
20708c2ecf20Sopenharmony_ci				  NISLANDS_SMC_SCLK_VALUE *sclk)
20718c2ecf20Sopenharmony_ci{
20728c2ecf20Sopenharmony_ci	NISLANDS_SMC_SCLK_VALUE sclk_tmp;
20738c2ecf20Sopenharmony_ci	int ret;
20748c2ecf20Sopenharmony_ci
20758c2ecf20Sopenharmony_ci	ret = ni_calculate_sclk_params(rdev, engine_clock, &sclk_tmp);
20768c2ecf20Sopenharmony_ci	if (!ret) {
20778c2ecf20Sopenharmony_ci		sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value);
20788c2ecf20Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL);
20798c2ecf20Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2);
20808c2ecf20Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3);
20818c2ecf20Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4);
20828c2ecf20Sopenharmony_ci		sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM);
20838c2ecf20Sopenharmony_ci		sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2);
20848c2ecf20Sopenharmony_ci	}
20858c2ecf20Sopenharmony_ci
20868c2ecf20Sopenharmony_ci	return ret;
20878c2ecf20Sopenharmony_ci}
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_cistatic int ni_init_smc_spll_table(struct radeon_device *rdev)
20908c2ecf20Sopenharmony_ci{
20918c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
20928c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
20938c2ecf20Sopenharmony_ci	SMC_NISLANDS_SPLL_DIV_TABLE *spll_table;
20948c2ecf20Sopenharmony_ci	NISLANDS_SMC_SCLK_VALUE sclk_params;
20958c2ecf20Sopenharmony_ci	u32 fb_div;
20968c2ecf20Sopenharmony_ci	u32 p_div;
20978c2ecf20Sopenharmony_ci	u32 clk_s;
20988c2ecf20Sopenharmony_ci	u32 clk_v;
20998c2ecf20Sopenharmony_ci	u32 sclk = 0;
21008c2ecf20Sopenharmony_ci	int i, ret;
21018c2ecf20Sopenharmony_ci	u32 tmp;
21028c2ecf20Sopenharmony_ci
21038c2ecf20Sopenharmony_ci	if (ni_pi->spll_table_start == 0)
21048c2ecf20Sopenharmony_ci		return -EINVAL;
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci	spll_table = kzalloc(sizeof(SMC_NISLANDS_SPLL_DIV_TABLE), GFP_KERNEL);
21078c2ecf20Sopenharmony_ci	if (spll_table == NULL)
21088c2ecf20Sopenharmony_ci		return -ENOMEM;
21098c2ecf20Sopenharmony_ci
21108c2ecf20Sopenharmony_ci	for (i = 0; i < 256; i++) {
21118c2ecf20Sopenharmony_ci		ret = ni_calculate_sclk_params(rdev, sclk, &sclk_params);
21128c2ecf20Sopenharmony_ci		if (ret)
21138c2ecf20Sopenharmony_ci			break;
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci		p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT;
21168c2ecf20Sopenharmony_ci		fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT;
21178c2ecf20Sopenharmony_ci		clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT;
21188c2ecf20Sopenharmony_ci		clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT;
21198c2ecf20Sopenharmony_ci
21208c2ecf20Sopenharmony_ci		fb_div &= ~0x00001FFF;
21218c2ecf20Sopenharmony_ci		fb_div >>= 1;
21228c2ecf20Sopenharmony_ci		clk_v >>= 6;
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_ci		if (p_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT))
21258c2ecf20Sopenharmony_ci			ret = -EINVAL;
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci		if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
21288c2ecf20Sopenharmony_ci			ret = -EINVAL;
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci		if (fb_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT))
21318c2ecf20Sopenharmony_ci			ret = -EINVAL;
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci		if (clk_v & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))
21348c2ecf20Sopenharmony_ci			ret = -EINVAL;
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_ci		if (ret)
21378c2ecf20Sopenharmony_ci			break;
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci		tmp = ((fb_div << SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) |
21408c2ecf20Sopenharmony_ci			((p_div << SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK);
21418c2ecf20Sopenharmony_ci		spll_table->freq[i] = cpu_to_be32(tmp);
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci		tmp = ((clk_v << SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK) |
21448c2ecf20Sopenharmony_ci			((clk_s << SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK);
21458c2ecf20Sopenharmony_ci		spll_table->ss[i] = cpu_to_be32(tmp);
21468c2ecf20Sopenharmony_ci
21478c2ecf20Sopenharmony_ci		sclk += 512;
21488c2ecf20Sopenharmony_ci	}
21498c2ecf20Sopenharmony_ci
21508c2ecf20Sopenharmony_ci	if (!ret)
21518c2ecf20Sopenharmony_ci		ret = rv770_copy_bytes_to_smc(rdev, ni_pi->spll_table_start, (u8 *)spll_table,
21528c2ecf20Sopenharmony_ci					      sizeof(SMC_NISLANDS_SPLL_DIV_TABLE), pi->sram_end);
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci	kfree(spll_table);
21558c2ecf20Sopenharmony_ci
21568c2ecf20Sopenharmony_ci	return ret;
21578c2ecf20Sopenharmony_ci}
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_cistatic int ni_populate_mclk_value(struct radeon_device *rdev,
21608c2ecf20Sopenharmony_ci				  u32 engine_clock,
21618c2ecf20Sopenharmony_ci				  u32 memory_clock,
21628c2ecf20Sopenharmony_ci				  NISLANDS_SMC_MCLK_VALUE *mclk,
21638c2ecf20Sopenharmony_ci				  bool strobe_mode,
21648c2ecf20Sopenharmony_ci				  bool dll_state_on)
21658c2ecf20Sopenharmony_ci{
21668c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
21678c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
21688c2ecf20Sopenharmony_ci	u32 mpll_ad_func_cntl = ni_pi->clock_registers.mpll_ad_func_cntl;
21698c2ecf20Sopenharmony_ci	u32 mpll_ad_func_cntl_2 = ni_pi->clock_registers.mpll_ad_func_cntl_2;
21708c2ecf20Sopenharmony_ci	u32 mpll_dq_func_cntl = ni_pi->clock_registers.mpll_dq_func_cntl;
21718c2ecf20Sopenharmony_ci	u32 mpll_dq_func_cntl_2 = ni_pi->clock_registers.mpll_dq_func_cntl_2;
21728c2ecf20Sopenharmony_ci	u32 mclk_pwrmgt_cntl = ni_pi->clock_registers.mclk_pwrmgt_cntl;
21738c2ecf20Sopenharmony_ci	u32 dll_cntl = ni_pi->clock_registers.dll_cntl;
21748c2ecf20Sopenharmony_ci	u32 mpll_ss1 = ni_pi->clock_registers.mpll_ss1;
21758c2ecf20Sopenharmony_ci	u32 mpll_ss2 = ni_pi->clock_registers.mpll_ss2;
21768c2ecf20Sopenharmony_ci	struct atom_clock_dividers dividers;
21778c2ecf20Sopenharmony_ci	u32 ibias;
21788c2ecf20Sopenharmony_ci	u32 dll_speed;
21798c2ecf20Sopenharmony_ci	int ret;
21808c2ecf20Sopenharmony_ci	u32 mc_seq_misc7;
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
21838c2ecf20Sopenharmony_ci					     memory_clock, strobe_mode, &dividers);
21848c2ecf20Sopenharmony_ci	if (ret)
21858c2ecf20Sopenharmony_ci		return ret;
21868c2ecf20Sopenharmony_ci
21878c2ecf20Sopenharmony_ci	if (!strobe_mode) {
21888c2ecf20Sopenharmony_ci		mc_seq_misc7 = RREG32(MC_SEQ_MISC7);
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci		if (mc_seq_misc7 & 0x8000000)
21918c2ecf20Sopenharmony_ci			dividers.post_div = 1;
21928c2ecf20Sopenharmony_ci	}
21938c2ecf20Sopenharmony_ci
21948c2ecf20Sopenharmony_ci	ibias = cypress_map_clkf_to_ibias(rdev, dividers.whole_fb_div);
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_ci	mpll_ad_func_cntl &= ~(CLKR_MASK |
21978c2ecf20Sopenharmony_ci			       YCLK_POST_DIV_MASK |
21988c2ecf20Sopenharmony_ci			       CLKF_MASK |
21998c2ecf20Sopenharmony_ci			       CLKFRAC_MASK |
22008c2ecf20Sopenharmony_ci			       IBIAS_MASK);
22018c2ecf20Sopenharmony_ci	mpll_ad_func_cntl |= CLKR(dividers.ref_div);
22028c2ecf20Sopenharmony_ci	mpll_ad_func_cntl |= YCLK_POST_DIV(dividers.post_div);
22038c2ecf20Sopenharmony_ci	mpll_ad_func_cntl |= CLKF(dividers.whole_fb_div);
22048c2ecf20Sopenharmony_ci	mpll_ad_func_cntl |= CLKFRAC(dividers.frac_fb_div);
22058c2ecf20Sopenharmony_ci	mpll_ad_func_cntl |= IBIAS(ibias);
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	if (dividers.vco_mode)
22088c2ecf20Sopenharmony_ci		mpll_ad_func_cntl_2 |= VCO_MODE;
22098c2ecf20Sopenharmony_ci	else
22108c2ecf20Sopenharmony_ci		mpll_ad_func_cntl_2 &= ~VCO_MODE;
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	if (pi->mem_gddr5) {
22138c2ecf20Sopenharmony_ci		mpll_dq_func_cntl &= ~(CLKR_MASK |
22148c2ecf20Sopenharmony_ci				       YCLK_POST_DIV_MASK |
22158c2ecf20Sopenharmony_ci				       CLKF_MASK |
22168c2ecf20Sopenharmony_ci				       CLKFRAC_MASK |
22178c2ecf20Sopenharmony_ci				       IBIAS_MASK);
22188c2ecf20Sopenharmony_ci		mpll_dq_func_cntl |= CLKR(dividers.ref_div);
22198c2ecf20Sopenharmony_ci		mpll_dq_func_cntl |= YCLK_POST_DIV(dividers.post_div);
22208c2ecf20Sopenharmony_ci		mpll_dq_func_cntl |= CLKF(dividers.whole_fb_div);
22218c2ecf20Sopenharmony_ci		mpll_dq_func_cntl |= CLKFRAC(dividers.frac_fb_div);
22228c2ecf20Sopenharmony_ci		mpll_dq_func_cntl |= IBIAS(ibias);
22238c2ecf20Sopenharmony_ci
22248c2ecf20Sopenharmony_ci		if (strobe_mode)
22258c2ecf20Sopenharmony_ci			mpll_dq_func_cntl &= ~PDNB;
22268c2ecf20Sopenharmony_ci		else
22278c2ecf20Sopenharmony_ci			mpll_dq_func_cntl |= PDNB;
22288c2ecf20Sopenharmony_ci
22298c2ecf20Sopenharmony_ci		if (dividers.vco_mode)
22308c2ecf20Sopenharmony_ci			mpll_dq_func_cntl_2 |= VCO_MODE;
22318c2ecf20Sopenharmony_ci		else
22328c2ecf20Sopenharmony_ci			mpll_dq_func_cntl_2 &= ~VCO_MODE;
22338c2ecf20Sopenharmony_ci	}
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_ci	if (pi->mclk_ss) {
22368c2ecf20Sopenharmony_ci		struct radeon_atom_ss ss;
22378c2ecf20Sopenharmony_ci		u32 vco_freq = memory_clock * dividers.post_div;
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
22408c2ecf20Sopenharmony_ci						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
22418c2ecf20Sopenharmony_ci			u32 reference_clock = rdev->clock.mpll.reference_freq;
22428c2ecf20Sopenharmony_ci			u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
22438c2ecf20Sopenharmony_ci			u32 clk_s, clk_v;
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci			if (!decoded_ref)
22468c2ecf20Sopenharmony_ci				return -EINVAL;
22478c2ecf20Sopenharmony_ci			clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
22488c2ecf20Sopenharmony_ci			clk_v = ss.percentage *
22498c2ecf20Sopenharmony_ci				(0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_ci			mpll_ss1 &= ~CLKV_MASK;
22528c2ecf20Sopenharmony_ci			mpll_ss1 |= CLKV(clk_v);
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_ci			mpll_ss2 &= ~CLKS_MASK;
22558c2ecf20Sopenharmony_ci			mpll_ss2 |= CLKS(clk_s);
22568c2ecf20Sopenharmony_ci		}
22578c2ecf20Sopenharmony_ci	}
22588c2ecf20Sopenharmony_ci
22598c2ecf20Sopenharmony_ci	dll_speed = rv740_get_dll_speed(pi->mem_gddr5,
22608c2ecf20Sopenharmony_ci					memory_clock);
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci	mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
22638c2ecf20Sopenharmony_ci	mclk_pwrmgt_cntl |= DLL_SPEED(dll_speed);
22648c2ecf20Sopenharmony_ci	if (dll_state_on)
22658c2ecf20Sopenharmony_ci		mclk_pwrmgt_cntl |= (MRDCKA0_PDNB |
22668c2ecf20Sopenharmony_ci				     MRDCKA1_PDNB |
22678c2ecf20Sopenharmony_ci				     MRDCKB0_PDNB |
22688c2ecf20Sopenharmony_ci				     MRDCKB1_PDNB |
22698c2ecf20Sopenharmony_ci				     MRDCKC0_PDNB |
22708c2ecf20Sopenharmony_ci				     MRDCKC1_PDNB |
22718c2ecf20Sopenharmony_ci				     MRDCKD0_PDNB |
22728c2ecf20Sopenharmony_ci				     MRDCKD1_PDNB);
22738c2ecf20Sopenharmony_ci	else
22748c2ecf20Sopenharmony_ci		mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
22758c2ecf20Sopenharmony_ci				      MRDCKA1_PDNB |
22768c2ecf20Sopenharmony_ci				      MRDCKB0_PDNB |
22778c2ecf20Sopenharmony_ci				      MRDCKB1_PDNB |
22788c2ecf20Sopenharmony_ci				      MRDCKC0_PDNB |
22798c2ecf20Sopenharmony_ci				      MRDCKC1_PDNB |
22808c2ecf20Sopenharmony_ci				      MRDCKD0_PDNB |
22818c2ecf20Sopenharmony_ci				      MRDCKD1_PDNB);
22828c2ecf20Sopenharmony_ci
22838c2ecf20Sopenharmony_ci
22848c2ecf20Sopenharmony_ci	mclk->mclk_value = cpu_to_be32(memory_clock);
22858c2ecf20Sopenharmony_ci	mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
22868c2ecf20Sopenharmony_ci	mclk->vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
22878c2ecf20Sopenharmony_ci	mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
22888c2ecf20Sopenharmony_ci	mclk->vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
22898c2ecf20Sopenharmony_ci	mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
22908c2ecf20Sopenharmony_ci	mclk->vDLL_CNTL = cpu_to_be32(dll_cntl);
22918c2ecf20Sopenharmony_ci	mclk->vMPLL_SS = cpu_to_be32(mpll_ss1);
22928c2ecf20Sopenharmony_ci	mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2);
22938c2ecf20Sopenharmony_ci
22948c2ecf20Sopenharmony_ci	return 0;
22958c2ecf20Sopenharmony_ci}
22968c2ecf20Sopenharmony_ci
22978c2ecf20Sopenharmony_cistatic void ni_populate_smc_sp(struct radeon_device *rdev,
22988c2ecf20Sopenharmony_ci			       struct radeon_ps *radeon_state,
22998c2ecf20Sopenharmony_ci			       NISLANDS_SMC_SWSTATE *smc_state)
23008c2ecf20Sopenharmony_ci{
23018c2ecf20Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(radeon_state);
23028c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
23038c2ecf20Sopenharmony_ci	int i;
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci	for (i = 0; i < ps->performance_level_count - 1; i++)
23068c2ecf20Sopenharmony_ci		smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	smc_state->levels[ps->performance_level_count - 1].bSP =
23098c2ecf20Sopenharmony_ci		cpu_to_be32(pi->psp);
23108c2ecf20Sopenharmony_ci}
23118c2ecf20Sopenharmony_ci
23128c2ecf20Sopenharmony_cistatic int ni_convert_power_level_to_smc(struct radeon_device *rdev,
23138c2ecf20Sopenharmony_ci					 struct rv7xx_pl *pl,
23148c2ecf20Sopenharmony_ci					 NISLANDS_SMC_HW_PERFORMANCE_LEVEL *level)
23158c2ecf20Sopenharmony_ci{
23168c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
23178c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
23188c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
23198c2ecf20Sopenharmony_ci	int ret;
23208c2ecf20Sopenharmony_ci	bool dll_state_on;
23218c2ecf20Sopenharmony_ci	u16 std_vddc;
23228c2ecf20Sopenharmony_ci	u32 tmp = RREG32(DC_STUTTER_CNTL);
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_ci	level->gen2PCIE = pi->pcie_gen2 ?
23258c2ecf20Sopenharmony_ci		((pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0) : 0;
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	ret = ni_populate_sclk_value(rdev, pl->sclk, &level->sclk);
23288c2ecf20Sopenharmony_ci	if (ret)
23298c2ecf20Sopenharmony_ci		return ret;
23308c2ecf20Sopenharmony_ci
23318c2ecf20Sopenharmony_ci	level->mcFlags =  0;
23328c2ecf20Sopenharmony_ci	if (pi->mclk_stutter_mode_threshold &&
23338c2ecf20Sopenharmony_ci	    (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
23348c2ecf20Sopenharmony_ci	    !eg_pi->uvd_enabled &&
23358c2ecf20Sopenharmony_ci	    (tmp & DC_STUTTER_ENABLE_A) &&
23368c2ecf20Sopenharmony_ci	    (tmp & DC_STUTTER_ENABLE_B))
23378c2ecf20Sopenharmony_ci		level->mcFlags |= NISLANDS_SMC_MC_STUTTER_EN;
23388c2ecf20Sopenharmony_ci
23398c2ecf20Sopenharmony_ci	if (pi->mem_gddr5) {
23408c2ecf20Sopenharmony_ci		if (pl->mclk > pi->mclk_edc_enable_threshold)
23418c2ecf20Sopenharmony_ci			level->mcFlags |= NISLANDS_SMC_MC_EDC_RD_FLAG;
23428c2ecf20Sopenharmony_ci		if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold)
23438c2ecf20Sopenharmony_ci			level->mcFlags |= NISLANDS_SMC_MC_EDC_WR_FLAG;
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_ci		level->strobeMode = cypress_get_strobe_mode_settings(rdev, pl->mclk);
23468c2ecf20Sopenharmony_ci
23478c2ecf20Sopenharmony_ci		if (level->strobeMode & NISLANDS_SMC_STROBE_ENABLE) {
23488c2ecf20Sopenharmony_ci			if (cypress_get_mclk_frequency_ratio(rdev, pl->mclk, true) >=
23498c2ecf20Sopenharmony_ci			    ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf))
23508c2ecf20Sopenharmony_ci				dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
23518c2ecf20Sopenharmony_ci			else
23528c2ecf20Sopenharmony_ci				dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false;
23538c2ecf20Sopenharmony_ci		} else {
23548c2ecf20Sopenharmony_ci			dll_state_on = false;
23558c2ecf20Sopenharmony_ci			if (pl->mclk > ni_pi->mclk_rtt_mode_threshold)
23568c2ecf20Sopenharmony_ci				level->mcFlags |= NISLANDS_SMC_MC_RTT_ENABLE;
23578c2ecf20Sopenharmony_ci		}
23588c2ecf20Sopenharmony_ci
23598c2ecf20Sopenharmony_ci		ret = ni_populate_mclk_value(rdev, pl->sclk, pl->mclk,
23608c2ecf20Sopenharmony_ci					     &level->mclk,
23618c2ecf20Sopenharmony_ci					     (level->strobeMode & NISLANDS_SMC_STROBE_ENABLE) != 0,
23628c2ecf20Sopenharmony_ci					     dll_state_on);
23638c2ecf20Sopenharmony_ci	} else
23648c2ecf20Sopenharmony_ci		ret = ni_populate_mclk_value(rdev, pl->sclk, pl->mclk, &level->mclk, 1, 1);
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_ci	if (ret)
23678c2ecf20Sopenharmony_ci		return ret;
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci	ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
23708c2ecf20Sopenharmony_ci					pl->vddc, &level->vddc);
23718c2ecf20Sopenharmony_ci	if (ret)
23728c2ecf20Sopenharmony_ci		return ret;
23738c2ecf20Sopenharmony_ci
23748c2ecf20Sopenharmony_ci	ret = ni_get_std_voltage_value(rdev, &level->vddc, &std_vddc);
23758c2ecf20Sopenharmony_ci	if (ret)
23768c2ecf20Sopenharmony_ci		return ret;
23778c2ecf20Sopenharmony_ci
23788c2ecf20Sopenharmony_ci	ni_populate_std_voltage_value(rdev, std_vddc,
23798c2ecf20Sopenharmony_ci				      level->vddc.index, &level->std_vddc);
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci	if (eg_pi->vddci_control) {
23828c2ecf20Sopenharmony_ci		ret = ni_populate_voltage_value(rdev, &eg_pi->vddci_voltage_table,
23838c2ecf20Sopenharmony_ci						pl->vddci, &level->vddci);
23848c2ecf20Sopenharmony_ci		if (ret)
23858c2ecf20Sopenharmony_ci			return ret;
23868c2ecf20Sopenharmony_ci	}
23878c2ecf20Sopenharmony_ci
23888c2ecf20Sopenharmony_ci	ni_populate_mvdd_value(rdev, pl->mclk, &level->mvdd);
23898c2ecf20Sopenharmony_ci
23908c2ecf20Sopenharmony_ci	return ret;
23918c2ecf20Sopenharmony_ci}
23928c2ecf20Sopenharmony_ci
23938c2ecf20Sopenharmony_cistatic int ni_populate_smc_t(struct radeon_device *rdev,
23948c2ecf20Sopenharmony_ci			     struct radeon_ps *radeon_state,
23958c2ecf20Sopenharmony_ci			     NISLANDS_SMC_SWSTATE *smc_state)
23968c2ecf20Sopenharmony_ci{
23978c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
23988c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
23998c2ecf20Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
24008c2ecf20Sopenharmony_ci	u32 a_t;
24018c2ecf20Sopenharmony_ci	u32 t_l, t_h;
24028c2ecf20Sopenharmony_ci	u32 high_bsp;
24038c2ecf20Sopenharmony_ci	int i, ret;
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	if (state->performance_level_count >= 9)
24068c2ecf20Sopenharmony_ci		return -EINVAL;
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	if (state->performance_level_count < 2) {
24098c2ecf20Sopenharmony_ci		a_t = CG_R(0xffff) | CG_L(0);
24108c2ecf20Sopenharmony_ci		smc_state->levels[0].aT = cpu_to_be32(a_t);
24118c2ecf20Sopenharmony_ci		return 0;
24128c2ecf20Sopenharmony_ci	}
24138c2ecf20Sopenharmony_ci
24148c2ecf20Sopenharmony_ci	smc_state->levels[0].aT = cpu_to_be32(0);
24158c2ecf20Sopenharmony_ci
24168c2ecf20Sopenharmony_ci	for (i = 0; i <= state->performance_level_count - 2; i++) {
24178c2ecf20Sopenharmony_ci		if (eg_pi->uvd_enabled)
24188c2ecf20Sopenharmony_ci			ret = r600_calculate_at(
24198c2ecf20Sopenharmony_ci				1000 * (i * (eg_pi->smu_uvd_hs ? 2 : 8) + 2),
24208c2ecf20Sopenharmony_ci				100 * R600_AH_DFLT,
24218c2ecf20Sopenharmony_ci				state->performance_levels[i + 1].sclk,
24228c2ecf20Sopenharmony_ci				state->performance_levels[i].sclk,
24238c2ecf20Sopenharmony_ci				&t_l,
24248c2ecf20Sopenharmony_ci				&t_h);
24258c2ecf20Sopenharmony_ci		else
24268c2ecf20Sopenharmony_ci			ret = r600_calculate_at(
24278c2ecf20Sopenharmony_ci				1000 * (i + 1),
24288c2ecf20Sopenharmony_ci				100 * R600_AH_DFLT,
24298c2ecf20Sopenharmony_ci				state->performance_levels[i + 1].sclk,
24308c2ecf20Sopenharmony_ci				state->performance_levels[i].sclk,
24318c2ecf20Sopenharmony_ci				&t_l,
24328c2ecf20Sopenharmony_ci				&t_h);
24338c2ecf20Sopenharmony_ci
24348c2ecf20Sopenharmony_ci		if (ret) {
24358c2ecf20Sopenharmony_ci			t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT;
24368c2ecf20Sopenharmony_ci			t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT;
24378c2ecf20Sopenharmony_ci		}
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci		a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK;
24408c2ecf20Sopenharmony_ci		a_t |= CG_R(t_l * pi->bsp / 20000);
24418c2ecf20Sopenharmony_ci		smc_state->levels[i].aT = cpu_to_be32(a_t);
24428c2ecf20Sopenharmony_ci
24438c2ecf20Sopenharmony_ci		high_bsp = (i == state->performance_level_count - 2) ?
24448c2ecf20Sopenharmony_ci			pi->pbsp : pi->bsp;
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_ci		a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000);
24478c2ecf20Sopenharmony_ci		smc_state->levels[i + 1].aT = cpu_to_be32(a_t);
24488c2ecf20Sopenharmony_ci	}
24498c2ecf20Sopenharmony_ci
24508c2ecf20Sopenharmony_ci	return 0;
24518c2ecf20Sopenharmony_ci}
24528c2ecf20Sopenharmony_ci
24538c2ecf20Sopenharmony_cistatic int ni_populate_power_containment_values(struct radeon_device *rdev,
24548c2ecf20Sopenharmony_ci						struct radeon_ps *radeon_state,
24558c2ecf20Sopenharmony_ci						NISLANDS_SMC_SWSTATE *smc_state)
24568c2ecf20Sopenharmony_ci{
24578c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
24588c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
24598c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
24608c2ecf20Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
24618c2ecf20Sopenharmony_ci	u32 prev_sclk;
24628c2ecf20Sopenharmony_ci	u32 max_sclk;
24638c2ecf20Sopenharmony_ci	u32 min_sclk;
24648c2ecf20Sopenharmony_ci	int i, ret;
24658c2ecf20Sopenharmony_ci	u32 tdp_limit;
24668c2ecf20Sopenharmony_ci	u32 near_tdp_limit;
24678c2ecf20Sopenharmony_ci	u32 power_boost_limit;
24688c2ecf20Sopenharmony_ci	u8 max_ps_percent;
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_ci	if (ni_pi->enable_power_containment == false)
24718c2ecf20Sopenharmony_ci		return 0;
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci	if (state->performance_level_count == 0)
24748c2ecf20Sopenharmony_ci		return -EINVAL;
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci	if (smc_state->levelCount != state->performance_level_count)
24778c2ecf20Sopenharmony_ci		return -EINVAL;
24788c2ecf20Sopenharmony_ci
24798c2ecf20Sopenharmony_ci	ret = ni_calculate_adjusted_tdp_limits(rdev,
24808c2ecf20Sopenharmony_ci					       false, /* ??? */
24818c2ecf20Sopenharmony_ci					       rdev->pm.dpm.tdp_adjustment,
24828c2ecf20Sopenharmony_ci					       &tdp_limit,
24838c2ecf20Sopenharmony_ci					       &near_tdp_limit);
24848c2ecf20Sopenharmony_ci	if (ret)
24858c2ecf20Sopenharmony_ci		return ret;
24868c2ecf20Sopenharmony_ci
24878c2ecf20Sopenharmony_ci	power_boost_limit = ni_calculate_power_boost_limit(rdev, radeon_state, near_tdp_limit);
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci	ret = rv770_write_smc_sram_dword(rdev,
24908c2ecf20Sopenharmony_ci					 pi->state_table_start +
24918c2ecf20Sopenharmony_ci					 offsetof(NISLANDS_SMC_STATETABLE, dpm2Params) +
24928c2ecf20Sopenharmony_ci					 offsetof(PP_NIslands_DPM2Parameters, PowerBoostLimit),
24938c2ecf20Sopenharmony_ci					 ni_scale_power_for_smc(power_boost_limit, ni_get_smc_power_scaling_factor(rdev)),
24948c2ecf20Sopenharmony_ci					 pi->sram_end);
24958c2ecf20Sopenharmony_ci	if (ret)
24968c2ecf20Sopenharmony_ci		power_boost_limit = 0;
24978c2ecf20Sopenharmony_ci
24988c2ecf20Sopenharmony_ci	smc_state->levels[0].dpm2.MaxPS = 0;
24998c2ecf20Sopenharmony_ci	smc_state->levels[0].dpm2.NearTDPDec = 0;
25008c2ecf20Sopenharmony_ci	smc_state->levels[0].dpm2.AboveSafeInc = 0;
25018c2ecf20Sopenharmony_ci	smc_state->levels[0].dpm2.BelowSafeInc = 0;
25028c2ecf20Sopenharmony_ci	smc_state->levels[0].stateFlags |= power_boost_limit ? PPSMC_STATEFLAG_POWERBOOST : 0;
25038c2ecf20Sopenharmony_ci
25048c2ecf20Sopenharmony_ci	for (i = 1; i < state->performance_level_count; i++) {
25058c2ecf20Sopenharmony_ci		prev_sclk = state->performance_levels[i-1].sclk;
25068c2ecf20Sopenharmony_ci		max_sclk  = state->performance_levels[i].sclk;
25078c2ecf20Sopenharmony_ci		max_ps_percent = (i != (state->performance_level_count - 1)) ?
25088c2ecf20Sopenharmony_ci			NISLANDS_DPM2_MAXPS_PERCENT_M : NISLANDS_DPM2_MAXPS_PERCENT_H;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci		if (max_sclk < prev_sclk)
25118c2ecf20Sopenharmony_ci			return -EINVAL;
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci		if ((max_ps_percent == 0) || (prev_sclk == max_sclk) || eg_pi->uvd_enabled)
25148c2ecf20Sopenharmony_ci			min_sclk = max_sclk;
25158c2ecf20Sopenharmony_ci		else if (1 == i)
25168c2ecf20Sopenharmony_ci			min_sclk = prev_sclk;
25178c2ecf20Sopenharmony_ci		else
25188c2ecf20Sopenharmony_ci			min_sclk = (prev_sclk * (u32)max_ps_percent) / 100;
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_ci		if (min_sclk < state->performance_levels[0].sclk)
25218c2ecf20Sopenharmony_ci			min_sclk = state->performance_levels[0].sclk;
25228c2ecf20Sopenharmony_ci
25238c2ecf20Sopenharmony_ci		if (min_sclk == 0)
25248c2ecf20Sopenharmony_ci			return -EINVAL;
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_ci		smc_state->levels[i].dpm2.MaxPS =
25278c2ecf20Sopenharmony_ci			(u8)((NISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk);
25288c2ecf20Sopenharmony_ci		smc_state->levels[i].dpm2.NearTDPDec = NISLANDS_DPM2_NEAR_TDP_DEC;
25298c2ecf20Sopenharmony_ci		smc_state->levels[i].dpm2.AboveSafeInc = NISLANDS_DPM2_ABOVE_SAFE_INC;
25308c2ecf20Sopenharmony_ci		smc_state->levels[i].dpm2.BelowSafeInc = NISLANDS_DPM2_BELOW_SAFE_INC;
25318c2ecf20Sopenharmony_ci		smc_state->levels[i].stateFlags |=
25328c2ecf20Sopenharmony_ci			((i != (state->performance_level_count - 1)) && power_boost_limit) ?
25338c2ecf20Sopenharmony_ci			PPSMC_STATEFLAG_POWERBOOST : 0;
25348c2ecf20Sopenharmony_ci	}
25358c2ecf20Sopenharmony_ci
25368c2ecf20Sopenharmony_ci	return 0;
25378c2ecf20Sopenharmony_ci}
25388c2ecf20Sopenharmony_ci
25398c2ecf20Sopenharmony_cistatic int ni_populate_sq_ramping_values(struct radeon_device *rdev,
25408c2ecf20Sopenharmony_ci					 struct radeon_ps *radeon_state,
25418c2ecf20Sopenharmony_ci					 NISLANDS_SMC_SWSTATE *smc_state)
25428c2ecf20Sopenharmony_ci{
25438c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
25448c2ecf20Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
25458c2ecf20Sopenharmony_ci	u32 sq_power_throttle;
25468c2ecf20Sopenharmony_ci	u32 sq_power_throttle2;
25478c2ecf20Sopenharmony_ci	bool enable_sq_ramping = ni_pi->enable_sq_ramping;
25488c2ecf20Sopenharmony_ci	int i;
25498c2ecf20Sopenharmony_ci
25508c2ecf20Sopenharmony_ci	if (state->performance_level_count == 0)
25518c2ecf20Sopenharmony_ci		return -EINVAL;
25528c2ecf20Sopenharmony_ci
25538c2ecf20Sopenharmony_ci	if (smc_state->levelCount != state->performance_level_count)
25548c2ecf20Sopenharmony_ci		return -EINVAL;
25558c2ecf20Sopenharmony_ci
25568c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.sq_ramping_threshold == 0)
25578c2ecf20Sopenharmony_ci		return -EINVAL;
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT))
25608c2ecf20Sopenharmony_ci		enable_sq_ramping = false;
25618c2ecf20Sopenharmony_ci
25628c2ecf20Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT))
25638c2ecf20Sopenharmony_ci		enable_sq_ramping = false;
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT))
25668c2ecf20Sopenharmony_ci		enable_sq_ramping = false;
25678c2ecf20Sopenharmony_ci
25688c2ecf20Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
25698c2ecf20Sopenharmony_ci		enable_sq_ramping = false;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
25728c2ecf20Sopenharmony_ci		enable_sq_ramping = false;
25738c2ecf20Sopenharmony_ci
25748c2ecf20Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
25758c2ecf20Sopenharmony_ci		sq_power_throttle  = 0;
25768c2ecf20Sopenharmony_ci		sq_power_throttle2 = 0;
25778c2ecf20Sopenharmony_ci
25788c2ecf20Sopenharmony_ci		if ((state->performance_levels[i].sclk >= rdev->pm.dpm.sq_ramping_threshold) &&
25798c2ecf20Sopenharmony_ci		    enable_sq_ramping) {
25808c2ecf20Sopenharmony_ci			sq_power_throttle |= MAX_POWER(NISLANDS_DPM2_SQ_RAMP_MAX_POWER);
25818c2ecf20Sopenharmony_ci			sq_power_throttle |= MIN_POWER(NISLANDS_DPM2_SQ_RAMP_MIN_POWER);
25828c2ecf20Sopenharmony_ci			sq_power_throttle2 |= MAX_POWER_DELTA(NISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA);
25838c2ecf20Sopenharmony_ci			sq_power_throttle2 |= STI_SIZE(NISLANDS_DPM2_SQ_RAMP_STI_SIZE);
25848c2ecf20Sopenharmony_ci			sq_power_throttle2 |= LTI_RATIO(NISLANDS_DPM2_SQ_RAMP_LTI_RATIO);
25858c2ecf20Sopenharmony_ci		} else {
25868c2ecf20Sopenharmony_ci			sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK;
25878c2ecf20Sopenharmony_ci			sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
25888c2ecf20Sopenharmony_ci		}
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci		smc_state->levels[i].SQPowerThrottle   = cpu_to_be32(sq_power_throttle);
25918c2ecf20Sopenharmony_ci		smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2);
25928c2ecf20Sopenharmony_ci	}
25938c2ecf20Sopenharmony_ci
25948c2ecf20Sopenharmony_ci	return 0;
25958c2ecf20Sopenharmony_ci}
25968c2ecf20Sopenharmony_ci
25978c2ecf20Sopenharmony_cistatic int ni_enable_power_containment(struct radeon_device *rdev,
25988c2ecf20Sopenharmony_ci				       struct radeon_ps *radeon_new_state,
25998c2ecf20Sopenharmony_ci				       bool enable)
26008c2ecf20Sopenharmony_ci{
26018c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
26028c2ecf20Sopenharmony_ci	PPSMC_Result smc_result;
26038c2ecf20Sopenharmony_ci	int ret = 0;
26048c2ecf20Sopenharmony_ci
26058c2ecf20Sopenharmony_ci	if (ni_pi->enable_power_containment) {
26068c2ecf20Sopenharmony_ci		if (enable) {
26078c2ecf20Sopenharmony_ci			if (!r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
26088c2ecf20Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_TDPClampingActive);
26098c2ecf20Sopenharmony_ci				if (smc_result != PPSMC_Result_OK) {
26108c2ecf20Sopenharmony_ci					ret = -EINVAL;
26118c2ecf20Sopenharmony_ci					ni_pi->pc_enabled = false;
26128c2ecf20Sopenharmony_ci				} else {
26138c2ecf20Sopenharmony_ci					ni_pi->pc_enabled = true;
26148c2ecf20Sopenharmony_ci				}
26158c2ecf20Sopenharmony_ci			}
26168c2ecf20Sopenharmony_ci		} else {
26178c2ecf20Sopenharmony_ci			smc_result = rv770_send_msg_to_smc(rdev, PPSMC_TDPClampingInactive);
26188c2ecf20Sopenharmony_ci			if (smc_result != PPSMC_Result_OK)
26198c2ecf20Sopenharmony_ci				ret = -EINVAL;
26208c2ecf20Sopenharmony_ci			ni_pi->pc_enabled = false;
26218c2ecf20Sopenharmony_ci		}
26228c2ecf20Sopenharmony_ci	}
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	return ret;
26258c2ecf20Sopenharmony_ci}
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_cistatic int ni_convert_power_state_to_smc(struct radeon_device *rdev,
26288c2ecf20Sopenharmony_ci					 struct radeon_ps *radeon_state,
26298c2ecf20Sopenharmony_ci					 NISLANDS_SMC_SWSTATE *smc_state)
26308c2ecf20Sopenharmony_ci{
26318c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
26328c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
26338c2ecf20Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
26348c2ecf20Sopenharmony_ci	int i, ret;
26358c2ecf20Sopenharmony_ci	u32 threshold = state->performance_levels[state->performance_level_count - 1].sclk * 100 / 100;
26368c2ecf20Sopenharmony_ci
26378c2ecf20Sopenharmony_ci	if (!(radeon_state->caps & ATOM_PPLIB_DISALLOW_ON_DC))
26388c2ecf20Sopenharmony_ci		smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci	smc_state->levelCount = 0;
26418c2ecf20Sopenharmony_ci
26428c2ecf20Sopenharmony_ci	if (state->performance_level_count > NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE)
26438c2ecf20Sopenharmony_ci		return -EINVAL;
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
26468c2ecf20Sopenharmony_ci		ret = ni_convert_power_level_to_smc(rdev, &state->performance_levels[i],
26478c2ecf20Sopenharmony_ci						    &smc_state->levels[i]);
26488c2ecf20Sopenharmony_ci		smc_state->levels[i].arbRefreshState =
26498c2ecf20Sopenharmony_ci			(u8)(NISLANDS_DRIVER_STATE_ARB_INDEX + i);
26508c2ecf20Sopenharmony_ci
26518c2ecf20Sopenharmony_ci		if (ret)
26528c2ecf20Sopenharmony_ci			return ret;
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci		if (ni_pi->enable_power_containment)
26558c2ecf20Sopenharmony_ci			smc_state->levels[i].displayWatermark =
26568c2ecf20Sopenharmony_ci				(state->performance_levels[i].sclk < threshold) ?
26578c2ecf20Sopenharmony_ci				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
26588c2ecf20Sopenharmony_ci		else
26598c2ecf20Sopenharmony_ci			smc_state->levels[i].displayWatermark = (i < 2) ?
26608c2ecf20Sopenharmony_ci				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
26618c2ecf20Sopenharmony_ci
26628c2ecf20Sopenharmony_ci		if (eg_pi->dynamic_ac_timing)
26638c2ecf20Sopenharmony_ci			smc_state->levels[i].ACIndex = NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i;
26648c2ecf20Sopenharmony_ci		else
26658c2ecf20Sopenharmony_ci			smc_state->levels[i].ACIndex = 0;
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci		smc_state->levelCount++;
26688c2ecf20Sopenharmony_ci	}
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_watermark_threshold,
26718c2ecf20Sopenharmony_ci				      cpu_to_be32(threshold / 512));
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci	ni_populate_smc_sp(rdev, radeon_state, smc_state);
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_ci	ret = ni_populate_power_containment_values(rdev, radeon_state, smc_state);
26768c2ecf20Sopenharmony_ci	if (ret)
26778c2ecf20Sopenharmony_ci		ni_pi->enable_power_containment = false;
26788c2ecf20Sopenharmony_ci
26798c2ecf20Sopenharmony_ci	ret = ni_populate_sq_ramping_values(rdev, radeon_state, smc_state);
26808c2ecf20Sopenharmony_ci	if (ret)
26818c2ecf20Sopenharmony_ci		ni_pi->enable_sq_ramping = false;
26828c2ecf20Sopenharmony_ci
26838c2ecf20Sopenharmony_ci	return ni_populate_smc_t(rdev, radeon_state, smc_state);
26848c2ecf20Sopenharmony_ci}
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_cistatic int ni_upload_sw_state(struct radeon_device *rdev,
26878c2ecf20Sopenharmony_ci			      struct radeon_ps *radeon_new_state)
26888c2ecf20Sopenharmony_ci{
26898c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
26908c2ecf20Sopenharmony_ci	u16 address = pi->state_table_start +
26918c2ecf20Sopenharmony_ci		offsetof(NISLANDS_SMC_STATETABLE, driverState);
26928c2ecf20Sopenharmony_ci	NISLANDS_SMC_SWSTATE *smc_state;
26938c2ecf20Sopenharmony_ci	size_t state_size = struct_size(smc_state, levels,
26948c2ecf20Sopenharmony_ci			NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE);
26958c2ecf20Sopenharmony_ci	int ret;
26968c2ecf20Sopenharmony_ci
26978c2ecf20Sopenharmony_ci	smc_state = kzalloc(state_size, GFP_KERNEL);
26988c2ecf20Sopenharmony_ci	if (smc_state == NULL)
26998c2ecf20Sopenharmony_ci		return -ENOMEM;
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_ci	ret = ni_convert_power_state_to_smc(rdev, radeon_new_state, smc_state);
27028c2ecf20Sopenharmony_ci	if (ret)
27038c2ecf20Sopenharmony_ci		goto done;
27048c2ecf20Sopenharmony_ci
27058c2ecf20Sopenharmony_ci	ret = rv770_copy_bytes_to_smc(rdev, address, (u8 *)smc_state, state_size, pi->sram_end);
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_cidone:
27088c2ecf20Sopenharmony_ci	kfree(smc_state);
27098c2ecf20Sopenharmony_ci
27108c2ecf20Sopenharmony_ci	return ret;
27118c2ecf20Sopenharmony_ci}
27128c2ecf20Sopenharmony_ci
27138c2ecf20Sopenharmony_cistatic int ni_set_mc_special_registers(struct radeon_device *rdev,
27148c2ecf20Sopenharmony_ci				       struct ni_mc_reg_table *table)
27158c2ecf20Sopenharmony_ci{
27168c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
27178c2ecf20Sopenharmony_ci	u8 i, j, k;
27188c2ecf20Sopenharmony_ci	u32 temp_reg;
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_ci	for (i = 0, j = table->last; i < table->last; i++) {
27218c2ecf20Sopenharmony_ci		switch (table->mc_reg_address[i].s1) {
27228c2ecf20Sopenharmony_ci		case MC_SEQ_MISC1 >> 2:
27238c2ecf20Sopenharmony_ci			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
27248c2ecf20Sopenharmony_ci				return -EINVAL;
27258c2ecf20Sopenharmony_ci			temp_reg = RREG32(MC_PMG_CMD_EMRS);
27268c2ecf20Sopenharmony_ci			table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS >> 2;
27278c2ecf20Sopenharmony_ci			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
27288c2ecf20Sopenharmony_ci			for (k = 0; k < table->num_entries; k++)
27298c2ecf20Sopenharmony_ci				table->mc_reg_table_entry[k].mc_data[j] =
27308c2ecf20Sopenharmony_ci					((temp_reg & 0xffff0000)) |
27318c2ecf20Sopenharmony_ci					((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
27328c2ecf20Sopenharmony_ci			j++;
27338c2ecf20Sopenharmony_ci			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
27348c2ecf20Sopenharmony_ci				return -EINVAL;
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci			temp_reg = RREG32(MC_PMG_CMD_MRS);
27378c2ecf20Sopenharmony_ci			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS >> 2;
27388c2ecf20Sopenharmony_ci			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP >> 2;
27398c2ecf20Sopenharmony_ci			for(k = 0; k < table->num_entries; k++) {
27408c2ecf20Sopenharmony_ci				table->mc_reg_table_entry[k].mc_data[j] =
27418c2ecf20Sopenharmony_ci					(temp_reg & 0xffff0000) |
27428c2ecf20Sopenharmony_ci					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
27438c2ecf20Sopenharmony_ci				if (!pi->mem_gddr5)
27448c2ecf20Sopenharmony_ci					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
27458c2ecf20Sopenharmony_ci			}
27468c2ecf20Sopenharmony_ci			j++;
27478c2ecf20Sopenharmony_ci			break;
27488c2ecf20Sopenharmony_ci		case MC_SEQ_RESERVE_M >> 2:
27498c2ecf20Sopenharmony_ci			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
27508c2ecf20Sopenharmony_ci				return -EINVAL;
27518c2ecf20Sopenharmony_ci			temp_reg = RREG32(MC_PMG_CMD_MRS1);
27528c2ecf20Sopenharmony_ci			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1 >> 2;
27538c2ecf20Sopenharmony_ci			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
27548c2ecf20Sopenharmony_ci			for (k = 0; k < table->num_entries; k++)
27558c2ecf20Sopenharmony_ci				table->mc_reg_table_entry[k].mc_data[j] =
27568c2ecf20Sopenharmony_ci					(temp_reg & 0xffff0000) |
27578c2ecf20Sopenharmony_ci					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
27588c2ecf20Sopenharmony_ci			j++;
27598c2ecf20Sopenharmony_ci			break;
27608c2ecf20Sopenharmony_ci		default:
27618c2ecf20Sopenharmony_ci			break;
27628c2ecf20Sopenharmony_ci		}
27638c2ecf20Sopenharmony_ci	}
27648c2ecf20Sopenharmony_ci
27658c2ecf20Sopenharmony_ci	table->last = j;
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci	return 0;
27688c2ecf20Sopenharmony_ci}
27698c2ecf20Sopenharmony_ci
27708c2ecf20Sopenharmony_cistatic bool ni_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)
27718c2ecf20Sopenharmony_ci{
27728c2ecf20Sopenharmony_ci	bool result = true;
27738c2ecf20Sopenharmony_ci
27748c2ecf20Sopenharmony_ci	switch (in_reg) {
27758c2ecf20Sopenharmony_ci	case  MC_SEQ_RAS_TIMING >> 2:
27768c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_RAS_TIMING_LP >> 2;
27778c2ecf20Sopenharmony_ci		break;
27788c2ecf20Sopenharmony_ci	case MC_SEQ_CAS_TIMING >> 2:
27798c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_CAS_TIMING_LP >> 2;
27808c2ecf20Sopenharmony_ci		break;
27818c2ecf20Sopenharmony_ci	case MC_SEQ_MISC_TIMING >> 2:
27828c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_MISC_TIMING_LP >> 2;
27838c2ecf20Sopenharmony_ci		break;
27848c2ecf20Sopenharmony_ci	case MC_SEQ_MISC_TIMING2 >> 2:
27858c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_MISC_TIMING2_LP >> 2;
27868c2ecf20Sopenharmony_ci		break;
27878c2ecf20Sopenharmony_ci	case MC_SEQ_RD_CTL_D0 >> 2:
27888c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_RD_CTL_D0_LP >> 2;
27898c2ecf20Sopenharmony_ci		break;
27908c2ecf20Sopenharmony_ci	case MC_SEQ_RD_CTL_D1 >> 2:
27918c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_RD_CTL_D1_LP >> 2;
27928c2ecf20Sopenharmony_ci		break;
27938c2ecf20Sopenharmony_ci	case MC_SEQ_WR_CTL_D0 >> 2:
27948c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_WR_CTL_D0_LP >> 2;
27958c2ecf20Sopenharmony_ci		break;
27968c2ecf20Sopenharmony_ci	case MC_SEQ_WR_CTL_D1 >> 2:
27978c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_WR_CTL_D1_LP >> 2;
27988c2ecf20Sopenharmony_ci		break;
27998c2ecf20Sopenharmony_ci	case MC_PMG_CMD_EMRS >> 2:
28008c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
28018c2ecf20Sopenharmony_ci		break;
28028c2ecf20Sopenharmony_ci	case MC_PMG_CMD_MRS >> 2:
28038c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_MRS_LP >> 2;
28048c2ecf20Sopenharmony_ci		break;
28058c2ecf20Sopenharmony_ci	case MC_PMG_CMD_MRS1 >> 2:
28068c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
28078c2ecf20Sopenharmony_ci		break;
28088c2ecf20Sopenharmony_ci	case MC_SEQ_PMG_TIMING >> 2:
28098c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_PMG_TIMING_LP >> 2;
28108c2ecf20Sopenharmony_ci		break;
28118c2ecf20Sopenharmony_ci	case MC_PMG_CMD_MRS2 >> 2:
28128c2ecf20Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_MRS2_LP >> 2;
28138c2ecf20Sopenharmony_ci		break;
28148c2ecf20Sopenharmony_ci	default:
28158c2ecf20Sopenharmony_ci		result = false;
28168c2ecf20Sopenharmony_ci		break;
28178c2ecf20Sopenharmony_ci	}
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_ci	return result;
28208c2ecf20Sopenharmony_ci}
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_cistatic void ni_set_valid_flag(struct ni_mc_reg_table *table)
28238c2ecf20Sopenharmony_ci{
28248c2ecf20Sopenharmony_ci	u8 i, j;
28258c2ecf20Sopenharmony_ci
28268c2ecf20Sopenharmony_ci	for (i = 0; i < table->last; i++) {
28278c2ecf20Sopenharmony_ci		for (j = 1; j < table->num_entries; j++) {
28288c2ecf20Sopenharmony_ci			if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) {
28298c2ecf20Sopenharmony_ci				table->valid_flag |= 1 << i;
28308c2ecf20Sopenharmony_ci				break;
28318c2ecf20Sopenharmony_ci			}
28328c2ecf20Sopenharmony_ci		}
28338c2ecf20Sopenharmony_ci	}
28348c2ecf20Sopenharmony_ci}
28358c2ecf20Sopenharmony_ci
28368c2ecf20Sopenharmony_cistatic void ni_set_s0_mc_reg_index(struct ni_mc_reg_table *table)
28378c2ecf20Sopenharmony_ci{
28388c2ecf20Sopenharmony_ci	u32 i;
28398c2ecf20Sopenharmony_ci	u16 address;
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci	for (i = 0; i < table->last; i++)
28428c2ecf20Sopenharmony_ci		table->mc_reg_address[i].s0 =
28438c2ecf20Sopenharmony_ci			ni_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ?
28448c2ecf20Sopenharmony_ci			address : table->mc_reg_address[i].s1;
28458c2ecf20Sopenharmony_ci}
28468c2ecf20Sopenharmony_ci
28478c2ecf20Sopenharmony_cistatic int ni_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table,
28488c2ecf20Sopenharmony_ci				      struct ni_mc_reg_table *ni_table)
28498c2ecf20Sopenharmony_ci{
28508c2ecf20Sopenharmony_ci	u8 i, j;
28518c2ecf20Sopenharmony_ci
28528c2ecf20Sopenharmony_ci	if (table->last > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
28538c2ecf20Sopenharmony_ci		return -EINVAL;
28548c2ecf20Sopenharmony_ci	if (table->num_entries > MAX_AC_TIMING_ENTRIES)
28558c2ecf20Sopenharmony_ci		return -EINVAL;
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci	for (i = 0; i < table->last; i++)
28588c2ecf20Sopenharmony_ci		ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
28598c2ecf20Sopenharmony_ci	ni_table->last = table->last;
28608c2ecf20Sopenharmony_ci
28618c2ecf20Sopenharmony_ci	for (i = 0; i < table->num_entries; i++) {
28628c2ecf20Sopenharmony_ci		ni_table->mc_reg_table_entry[i].mclk_max =
28638c2ecf20Sopenharmony_ci			table->mc_reg_table_entry[i].mclk_max;
28648c2ecf20Sopenharmony_ci		for (j = 0; j < table->last; j++)
28658c2ecf20Sopenharmony_ci			ni_table->mc_reg_table_entry[i].mc_data[j] =
28668c2ecf20Sopenharmony_ci				table->mc_reg_table_entry[i].mc_data[j];
28678c2ecf20Sopenharmony_ci	}
28688c2ecf20Sopenharmony_ci	ni_table->num_entries = table->num_entries;
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci	return 0;
28718c2ecf20Sopenharmony_ci}
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_cistatic int ni_initialize_mc_reg_table(struct radeon_device *rdev)
28748c2ecf20Sopenharmony_ci{
28758c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
28768c2ecf20Sopenharmony_ci	int ret;
28778c2ecf20Sopenharmony_ci	struct atom_mc_reg_table *table;
28788c2ecf20Sopenharmony_ci	struct ni_mc_reg_table *ni_table = &ni_pi->mc_reg_table;
28798c2ecf20Sopenharmony_ci	u8 module_index = rv770_get_memory_module_index(rdev);
28808c2ecf20Sopenharmony_ci
28818c2ecf20Sopenharmony_ci	table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL);
28828c2ecf20Sopenharmony_ci	if (!table)
28838c2ecf20Sopenharmony_ci		return -ENOMEM;
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING));
28868c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING));
28878c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING));
28888c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2));
28898c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS));
28908c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS));
28918c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1));
28928c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0));
28938c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1));
28948c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0));
28958c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1));
28968c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING));
28978c2ecf20Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2));
28988c2ecf20Sopenharmony_ci
28998c2ecf20Sopenharmony_ci	ret = radeon_atom_init_mc_reg_table(rdev, module_index, table);
29008c2ecf20Sopenharmony_ci
29018c2ecf20Sopenharmony_ci	if (ret)
29028c2ecf20Sopenharmony_ci		goto init_mc_done;
29038c2ecf20Sopenharmony_ci
29048c2ecf20Sopenharmony_ci	ret = ni_copy_vbios_mc_reg_table(table, ni_table);
29058c2ecf20Sopenharmony_ci
29068c2ecf20Sopenharmony_ci	if (ret)
29078c2ecf20Sopenharmony_ci		goto init_mc_done;
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	ni_set_s0_mc_reg_index(ni_table);
29108c2ecf20Sopenharmony_ci
29118c2ecf20Sopenharmony_ci	ret = ni_set_mc_special_registers(rdev, ni_table);
29128c2ecf20Sopenharmony_ci
29138c2ecf20Sopenharmony_ci	if (ret)
29148c2ecf20Sopenharmony_ci		goto init_mc_done;
29158c2ecf20Sopenharmony_ci
29168c2ecf20Sopenharmony_ci	ni_set_valid_flag(ni_table);
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ciinit_mc_done:
29198c2ecf20Sopenharmony_ci	kfree(table);
29208c2ecf20Sopenharmony_ci
29218c2ecf20Sopenharmony_ci	return ret;
29228c2ecf20Sopenharmony_ci}
29238c2ecf20Sopenharmony_ci
29248c2ecf20Sopenharmony_cistatic void ni_populate_mc_reg_addresses(struct radeon_device *rdev,
29258c2ecf20Sopenharmony_ci					 SMC_NIslands_MCRegisters *mc_reg_table)
29268c2ecf20Sopenharmony_ci{
29278c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
29288c2ecf20Sopenharmony_ci	u32 i, j;
29298c2ecf20Sopenharmony_ci
29308c2ecf20Sopenharmony_ci	for (i = 0, j = 0; j < ni_pi->mc_reg_table.last; j++) {
29318c2ecf20Sopenharmony_ci		if (ni_pi->mc_reg_table.valid_flag & (1 << j)) {
29328c2ecf20Sopenharmony_ci			if (i >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
29338c2ecf20Sopenharmony_ci				break;
29348c2ecf20Sopenharmony_ci			mc_reg_table->address[i].s0 =
29358c2ecf20Sopenharmony_ci				cpu_to_be16(ni_pi->mc_reg_table.mc_reg_address[j].s0);
29368c2ecf20Sopenharmony_ci			mc_reg_table->address[i].s1 =
29378c2ecf20Sopenharmony_ci				cpu_to_be16(ni_pi->mc_reg_table.mc_reg_address[j].s1);
29388c2ecf20Sopenharmony_ci			i++;
29398c2ecf20Sopenharmony_ci		}
29408c2ecf20Sopenharmony_ci	}
29418c2ecf20Sopenharmony_ci	mc_reg_table->last = (u8)i;
29428c2ecf20Sopenharmony_ci}
29438c2ecf20Sopenharmony_ci
29448c2ecf20Sopenharmony_ci
29458c2ecf20Sopenharmony_cistatic void ni_convert_mc_registers(struct ni_mc_reg_entry *entry,
29468c2ecf20Sopenharmony_ci				    SMC_NIslands_MCRegisterSet *data,
29478c2ecf20Sopenharmony_ci				    u32 num_entries, u32 valid_flag)
29488c2ecf20Sopenharmony_ci{
29498c2ecf20Sopenharmony_ci	u32 i, j;
29508c2ecf20Sopenharmony_ci
29518c2ecf20Sopenharmony_ci	for (i = 0, j = 0; j < num_entries; j++) {
29528c2ecf20Sopenharmony_ci		if (valid_flag & (1 << j)) {
29538c2ecf20Sopenharmony_ci			data->value[i] = cpu_to_be32(entry->mc_data[j]);
29548c2ecf20Sopenharmony_ci			i++;
29558c2ecf20Sopenharmony_ci		}
29568c2ecf20Sopenharmony_ci	}
29578c2ecf20Sopenharmony_ci}
29588c2ecf20Sopenharmony_ci
29598c2ecf20Sopenharmony_cistatic void ni_convert_mc_reg_table_entry_to_smc(struct radeon_device *rdev,
29608c2ecf20Sopenharmony_ci						 struct rv7xx_pl *pl,
29618c2ecf20Sopenharmony_ci						 SMC_NIslands_MCRegisterSet *mc_reg_table_data)
29628c2ecf20Sopenharmony_ci{
29638c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
29648c2ecf20Sopenharmony_ci	u32 i = 0;
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_ci	for (i = 0; i < ni_pi->mc_reg_table.num_entries; i++) {
29678c2ecf20Sopenharmony_ci		if (pl->mclk <= ni_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max)
29688c2ecf20Sopenharmony_ci			break;
29698c2ecf20Sopenharmony_ci	}
29708c2ecf20Sopenharmony_ci
29718c2ecf20Sopenharmony_ci	if ((i == ni_pi->mc_reg_table.num_entries) && (i > 0))
29728c2ecf20Sopenharmony_ci		--i;
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_ci	ni_convert_mc_registers(&ni_pi->mc_reg_table.mc_reg_table_entry[i],
29758c2ecf20Sopenharmony_ci				mc_reg_table_data,
29768c2ecf20Sopenharmony_ci				ni_pi->mc_reg_table.last,
29778c2ecf20Sopenharmony_ci				ni_pi->mc_reg_table.valid_flag);
29788c2ecf20Sopenharmony_ci}
29798c2ecf20Sopenharmony_ci
29808c2ecf20Sopenharmony_cistatic void ni_convert_mc_reg_table_to_smc(struct radeon_device *rdev,
29818c2ecf20Sopenharmony_ci					   struct radeon_ps *radeon_state,
29828c2ecf20Sopenharmony_ci					   SMC_NIslands_MCRegisters *mc_reg_table)
29838c2ecf20Sopenharmony_ci{
29848c2ecf20Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
29858c2ecf20Sopenharmony_ci	int i;
29868c2ecf20Sopenharmony_ci
29878c2ecf20Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
29888c2ecf20Sopenharmony_ci		ni_convert_mc_reg_table_entry_to_smc(rdev,
29898c2ecf20Sopenharmony_ci						     &state->performance_levels[i],
29908c2ecf20Sopenharmony_ci						     &mc_reg_table->data[NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]);
29918c2ecf20Sopenharmony_ci	}
29928c2ecf20Sopenharmony_ci}
29938c2ecf20Sopenharmony_ci
29948c2ecf20Sopenharmony_cistatic int ni_populate_mc_reg_table(struct radeon_device *rdev,
29958c2ecf20Sopenharmony_ci				    struct radeon_ps *radeon_boot_state)
29968c2ecf20Sopenharmony_ci{
29978c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
29988c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
29998c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
30008c2ecf20Sopenharmony_ci	struct ni_ps *boot_state = ni_get_ps(radeon_boot_state);
30018c2ecf20Sopenharmony_ci	SMC_NIslands_MCRegisters *mc_reg_table = &ni_pi->smc_mc_reg_table;
30028c2ecf20Sopenharmony_ci
30038c2ecf20Sopenharmony_ci	memset(mc_reg_table, 0, sizeof(SMC_NIslands_MCRegisters));
30048c2ecf20Sopenharmony_ci
30058c2ecf20Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_seq_index, 1);
30068c2ecf20Sopenharmony_ci
30078c2ecf20Sopenharmony_ci	ni_populate_mc_reg_addresses(rdev, mc_reg_table);
30088c2ecf20Sopenharmony_ci
30098c2ecf20Sopenharmony_ci	ni_convert_mc_reg_table_entry_to_smc(rdev, &boot_state->performance_levels[0],
30108c2ecf20Sopenharmony_ci					     &mc_reg_table->data[0]);
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_ci	ni_convert_mc_registers(&ni_pi->mc_reg_table.mc_reg_table_entry[0],
30138c2ecf20Sopenharmony_ci				&mc_reg_table->data[1],
30148c2ecf20Sopenharmony_ci				ni_pi->mc_reg_table.last,
30158c2ecf20Sopenharmony_ci				ni_pi->mc_reg_table.valid_flag);
30168c2ecf20Sopenharmony_ci
30178c2ecf20Sopenharmony_ci	ni_convert_mc_reg_table_to_smc(rdev, radeon_boot_state, mc_reg_table);
30188c2ecf20Sopenharmony_ci
30198c2ecf20Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, eg_pi->mc_reg_table_start,
30208c2ecf20Sopenharmony_ci				       (u8 *)mc_reg_table,
30218c2ecf20Sopenharmony_ci				       sizeof(SMC_NIslands_MCRegisters),
30228c2ecf20Sopenharmony_ci				       pi->sram_end);
30238c2ecf20Sopenharmony_ci}
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_cistatic int ni_upload_mc_reg_table(struct radeon_device *rdev,
30268c2ecf20Sopenharmony_ci				  struct radeon_ps *radeon_new_state)
30278c2ecf20Sopenharmony_ci{
30288c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
30298c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
30308c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
30318c2ecf20Sopenharmony_ci	struct ni_ps *ni_new_state = ni_get_ps(radeon_new_state);
30328c2ecf20Sopenharmony_ci	SMC_NIslands_MCRegisters *mc_reg_table = &ni_pi->smc_mc_reg_table;
30338c2ecf20Sopenharmony_ci	u16 address;
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_ci	memset(mc_reg_table, 0, sizeof(SMC_NIslands_MCRegisters));
30368c2ecf20Sopenharmony_ci
30378c2ecf20Sopenharmony_ci	ni_convert_mc_reg_table_to_smc(rdev, radeon_new_state, mc_reg_table);
30388c2ecf20Sopenharmony_ci
30398c2ecf20Sopenharmony_ci	address = eg_pi->mc_reg_table_start +
30408c2ecf20Sopenharmony_ci		(u16)offsetof(SMC_NIslands_MCRegisters, data[NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]);
30418c2ecf20Sopenharmony_ci
30428c2ecf20Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, address,
30438c2ecf20Sopenharmony_ci				       (u8 *)&mc_reg_table->data[NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT],
30448c2ecf20Sopenharmony_ci				       sizeof(SMC_NIslands_MCRegisterSet) * ni_new_state->performance_level_count,
30458c2ecf20Sopenharmony_ci				       pi->sram_end);
30468c2ecf20Sopenharmony_ci}
30478c2ecf20Sopenharmony_ci
30488c2ecf20Sopenharmony_cistatic int ni_init_driver_calculated_leakage_table(struct radeon_device *rdev,
30498c2ecf20Sopenharmony_ci						   PP_NIslands_CACTABLES *cac_tables)
30508c2ecf20Sopenharmony_ci{
30518c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
30528c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
30538c2ecf20Sopenharmony_ci	u32 leakage = 0;
30548c2ecf20Sopenharmony_ci	unsigned int i, j, table_size;
30558c2ecf20Sopenharmony_ci	s32 t;
30568c2ecf20Sopenharmony_ci	u32 smc_leakage, max_leakage = 0;
30578c2ecf20Sopenharmony_ci	u32 scaling_factor;
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	table_size = eg_pi->vddc_voltage_table.count;
30608c2ecf20Sopenharmony_ci
30618c2ecf20Sopenharmony_ci	if (SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES < table_size)
30628c2ecf20Sopenharmony_ci		table_size = SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES;
30638c2ecf20Sopenharmony_ci
30648c2ecf20Sopenharmony_ci	scaling_factor = ni_get_smc_power_scaling_factor(rdev);
30658c2ecf20Sopenharmony_ci
30668c2ecf20Sopenharmony_ci	for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++) {
30678c2ecf20Sopenharmony_ci		for (j = 0; j < table_size; j++) {
30688c2ecf20Sopenharmony_ci			t = (1000 * ((i + 1) * 8));
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_ci			if (t < ni_pi->cac_data.leakage_minimum_temperature)
30718c2ecf20Sopenharmony_ci				t = ni_pi->cac_data.leakage_minimum_temperature;
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci			ni_calculate_leakage_for_v_and_t(rdev,
30748c2ecf20Sopenharmony_ci							 &ni_pi->cac_data.leakage_coefficients,
30758c2ecf20Sopenharmony_ci							 eg_pi->vddc_voltage_table.entries[j].value,
30768c2ecf20Sopenharmony_ci							 t,
30778c2ecf20Sopenharmony_ci							 ni_pi->cac_data.i_leakage,
30788c2ecf20Sopenharmony_ci							 &leakage);
30798c2ecf20Sopenharmony_ci
30808c2ecf20Sopenharmony_ci			smc_leakage = ni_scale_power_for_smc(leakage, scaling_factor) / 1000;
30818c2ecf20Sopenharmony_ci			if (smc_leakage > max_leakage)
30828c2ecf20Sopenharmony_ci				max_leakage = smc_leakage;
30838c2ecf20Sopenharmony_ci
30848c2ecf20Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] = cpu_to_be32(smc_leakage);
30858c2ecf20Sopenharmony_ci		}
30868c2ecf20Sopenharmony_ci	}
30878c2ecf20Sopenharmony_ci
30888c2ecf20Sopenharmony_ci	for (j = table_size; j < SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
30898c2ecf20Sopenharmony_ci		for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++)
30908c2ecf20Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] = cpu_to_be32(max_leakage);
30918c2ecf20Sopenharmony_ci	}
30928c2ecf20Sopenharmony_ci	return 0;
30938c2ecf20Sopenharmony_ci}
30948c2ecf20Sopenharmony_ci
30958c2ecf20Sopenharmony_cistatic int ni_init_simplified_leakage_table(struct radeon_device *rdev,
30968c2ecf20Sopenharmony_ci					    PP_NIslands_CACTABLES *cac_tables)
30978c2ecf20Sopenharmony_ci{
30988c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
30998c2ecf20Sopenharmony_ci	struct radeon_cac_leakage_table *leakage_table =
31008c2ecf20Sopenharmony_ci		&rdev->pm.dpm.dyn_state.cac_leakage_table;
31018c2ecf20Sopenharmony_ci	u32 i, j, table_size;
31028c2ecf20Sopenharmony_ci	u32 smc_leakage, max_leakage = 0;
31038c2ecf20Sopenharmony_ci	u32 scaling_factor;
31048c2ecf20Sopenharmony_ci
31058c2ecf20Sopenharmony_ci	if (!leakage_table)
31068c2ecf20Sopenharmony_ci		return -EINVAL;
31078c2ecf20Sopenharmony_ci
31088c2ecf20Sopenharmony_ci	table_size = leakage_table->count;
31098c2ecf20Sopenharmony_ci
31108c2ecf20Sopenharmony_ci	if (eg_pi->vddc_voltage_table.count != table_size)
31118c2ecf20Sopenharmony_ci		table_size = (eg_pi->vddc_voltage_table.count < leakage_table->count) ?
31128c2ecf20Sopenharmony_ci			eg_pi->vddc_voltage_table.count : leakage_table->count;
31138c2ecf20Sopenharmony_ci
31148c2ecf20Sopenharmony_ci	if (SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES < table_size)
31158c2ecf20Sopenharmony_ci		table_size = SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES;
31168c2ecf20Sopenharmony_ci
31178c2ecf20Sopenharmony_ci	if (table_size == 0)
31188c2ecf20Sopenharmony_ci		return -EINVAL;
31198c2ecf20Sopenharmony_ci
31208c2ecf20Sopenharmony_ci	scaling_factor = ni_get_smc_power_scaling_factor(rdev);
31218c2ecf20Sopenharmony_ci
31228c2ecf20Sopenharmony_ci	for (j = 0; j < table_size; j++) {
31238c2ecf20Sopenharmony_ci		smc_leakage = leakage_table->entries[j].leakage;
31248c2ecf20Sopenharmony_ci
31258c2ecf20Sopenharmony_ci		if (smc_leakage > max_leakage)
31268c2ecf20Sopenharmony_ci			max_leakage = smc_leakage;
31278c2ecf20Sopenharmony_ci
31288c2ecf20Sopenharmony_ci		for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++)
31298c2ecf20Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] =
31308c2ecf20Sopenharmony_ci				cpu_to_be32(ni_scale_power_for_smc(smc_leakage, scaling_factor));
31318c2ecf20Sopenharmony_ci	}
31328c2ecf20Sopenharmony_ci
31338c2ecf20Sopenharmony_ci	for (j = table_size; j < SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
31348c2ecf20Sopenharmony_ci		for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++)
31358c2ecf20Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] =
31368c2ecf20Sopenharmony_ci				cpu_to_be32(ni_scale_power_for_smc(max_leakage, scaling_factor));
31378c2ecf20Sopenharmony_ci	}
31388c2ecf20Sopenharmony_ci	return 0;
31398c2ecf20Sopenharmony_ci}
31408c2ecf20Sopenharmony_ci
31418c2ecf20Sopenharmony_cistatic int ni_initialize_smc_cac_tables(struct radeon_device *rdev)
31428c2ecf20Sopenharmony_ci{
31438c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
31448c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
31458c2ecf20Sopenharmony_ci	PP_NIslands_CACTABLES *cac_tables = NULL;
31468c2ecf20Sopenharmony_ci	int i, ret;
31478c2ecf20Sopenharmony_ci	u32 reg;
31488c2ecf20Sopenharmony_ci
31498c2ecf20Sopenharmony_ci	if (ni_pi->enable_cac == false)
31508c2ecf20Sopenharmony_ci		return 0;
31518c2ecf20Sopenharmony_ci
31528c2ecf20Sopenharmony_ci	cac_tables = kzalloc(sizeof(PP_NIslands_CACTABLES), GFP_KERNEL);
31538c2ecf20Sopenharmony_ci	if (!cac_tables)
31548c2ecf20Sopenharmony_ci		return -ENOMEM;
31558c2ecf20Sopenharmony_ci
31568c2ecf20Sopenharmony_ci	reg = RREG32(CG_CAC_CTRL) & ~(TID_CNT_MASK | TID_UNIT_MASK);
31578c2ecf20Sopenharmony_ci	reg |= (TID_CNT(ni_pi->cac_weights->tid_cnt) |
31588c2ecf20Sopenharmony_ci		TID_UNIT(ni_pi->cac_weights->tid_unit));
31598c2ecf20Sopenharmony_ci	WREG32(CG_CAC_CTRL, reg);
31608c2ecf20Sopenharmony_ci
31618c2ecf20Sopenharmony_ci	for (i = 0; i < NISLANDS_DCCAC_MAX_LEVELS; i++)
31628c2ecf20Sopenharmony_ci		ni_pi->dc_cac_table[i] = ni_pi->cac_weights->dc_cac[i];
31638c2ecf20Sopenharmony_ci
31648c2ecf20Sopenharmony_ci	for (i = 0; i < SMC_NISLANDS_BIF_LUT_NUM_OF_ENTRIES; i++)
31658c2ecf20Sopenharmony_ci		cac_tables->cac_bif_lut[i] = ni_pi->cac_weights->pcie_cac[i];
31668c2ecf20Sopenharmony_ci
31678c2ecf20Sopenharmony_ci	ni_pi->cac_data.i_leakage = rdev->pm.dpm.cac_leakage;
31688c2ecf20Sopenharmony_ci	ni_pi->cac_data.pwr_const = 0;
31698c2ecf20Sopenharmony_ci	ni_pi->cac_data.dc_cac_value = ni_pi->dc_cac_table[NISLANDS_DCCAC_LEVEL_0];
31708c2ecf20Sopenharmony_ci	ni_pi->cac_data.bif_cac_value = 0;
31718c2ecf20Sopenharmony_ci	ni_pi->cac_data.mc_wr_weight = ni_pi->cac_weights->mc_write_weight;
31728c2ecf20Sopenharmony_ci	ni_pi->cac_data.mc_rd_weight = ni_pi->cac_weights->mc_read_weight;
31738c2ecf20Sopenharmony_ci	ni_pi->cac_data.allow_ovrflw = 0;
31748c2ecf20Sopenharmony_ci	ni_pi->cac_data.l2num_win_tdp = ni_pi->lta_window_size;
31758c2ecf20Sopenharmony_ci	ni_pi->cac_data.num_win_tdp = 0;
31768c2ecf20Sopenharmony_ci	ni_pi->cac_data.lts_truncate_n = ni_pi->lts_truncate;
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	if (ni_pi->driver_calculate_cac_leakage)
31798c2ecf20Sopenharmony_ci		ret = ni_init_driver_calculated_leakage_table(rdev, cac_tables);
31808c2ecf20Sopenharmony_ci	else
31818c2ecf20Sopenharmony_ci		ret = ni_init_simplified_leakage_table(rdev, cac_tables);
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci	if (ret)
31848c2ecf20Sopenharmony_ci		goto done_free;
31858c2ecf20Sopenharmony_ci
31868c2ecf20Sopenharmony_ci	cac_tables->pwr_const      = cpu_to_be32(ni_pi->cac_data.pwr_const);
31878c2ecf20Sopenharmony_ci	cac_tables->dc_cacValue    = cpu_to_be32(ni_pi->cac_data.dc_cac_value);
31888c2ecf20Sopenharmony_ci	cac_tables->bif_cacValue   = cpu_to_be32(ni_pi->cac_data.bif_cac_value);
31898c2ecf20Sopenharmony_ci	cac_tables->AllowOvrflw    = ni_pi->cac_data.allow_ovrflw;
31908c2ecf20Sopenharmony_ci	cac_tables->MCWrWeight     = ni_pi->cac_data.mc_wr_weight;
31918c2ecf20Sopenharmony_ci	cac_tables->MCRdWeight     = ni_pi->cac_data.mc_rd_weight;
31928c2ecf20Sopenharmony_ci	cac_tables->numWin_TDP     = ni_pi->cac_data.num_win_tdp;
31938c2ecf20Sopenharmony_ci	cac_tables->l2numWin_TDP   = ni_pi->cac_data.l2num_win_tdp;
31948c2ecf20Sopenharmony_ci	cac_tables->lts_truncate_n = ni_pi->cac_data.lts_truncate_n;
31958c2ecf20Sopenharmony_ci
31968c2ecf20Sopenharmony_ci	ret = rv770_copy_bytes_to_smc(rdev, ni_pi->cac_table_start, (u8 *)cac_tables,
31978c2ecf20Sopenharmony_ci				      sizeof(PP_NIslands_CACTABLES), pi->sram_end);
31988c2ecf20Sopenharmony_ci
31998c2ecf20Sopenharmony_cidone_free:
32008c2ecf20Sopenharmony_ci	if (ret) {
32018c2ecf20Sopenharmony_ci		ni_pi->enable_cac = false;
32028c2ecf20Sopenharmony_ci		ni_pi->enable_power_containment = false;
32038c2ecf20Sopenharmony_ci	}
32048c2ecf20Sopenharmony_ci
32058c2ecf20Sopenharmony_ci	kfree(cac_tables);
32068c2ecf20Sopenharmony_ci
32078c2ecf20Sopenharmony_ci	return 0;
32088c2ecf20Sopenharmony_ci}
32098c2ecf20Sopenharmony_ci
32108c2ecf20Sopenharmony_cistatic int ni_initialize_hardware_cac_manager(struct radeon_device *rdev)
32118c2ecf20Sopenharmony_ci{
32128c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
32138c2ecf20Sopenharmony_ci	u32 reg;
32148c2ecf20Sopenharmony_ci
32158c2ecf20Sopenharmony_ci	if (!ni_pi->enable_cac ||
32168c2ecf20Sopenharmony_ci	    !ni_pi->cac_configuration_required)
32178c2ecf20Sopenharmony_ci		return 0;
32188c2ecf20Sopenharmony_ci
32198c2ecf20Sopenharmony_ci	if (ni_pi->cac_weights == NULL)
32208c2ecf20Sopenharmony_ci		return -EINVAL;
32218c2ecf20Sopenharmony_ci
32228c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_1_WEIGHT_0) & ~(WEIGHT_TCP_SIG0_MASK |
32238c2ecf20Sopenharmony_ci						      WEIGHT_TCP_SIG1_MASK |
32248c2ecf20Sopenharmony_ci						      WEIGHT_TA_SIG_MASK);
32258c2ecf20Sopenharmony_ci	reg |= (WEIGHT_TCP_SIG0(ni_pi->cac_weights->weight_tcp_sig0) |
32268c2ecf20Sopenharmony_ci		WEIGHT_TCP_SIG1(ni_pi->cac_weights->weight_tcp_sig1) |
32278c2ecf20Sopenharmony_ci		WEIGHT_TA_SIG(ni_pi->cac_weights->weight_ta_sig));
32288c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_1_WEIGHT_0, reg);
32298c2ecf20Sopenharmony_ci
32308c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_1_WEIGHT_1) & ~(WEIGHT_TCC_EN0_MASK |
32318c2ecf20Sopenharmony_ci						      WEIGHT_TCC_EN1_MASK |
32328c2ecf20Sopenharmony_ci						      WEIGHT_TCC_EN2_MASK);
32338c2ecf20Sopenharmony_ci	reg |= (WEIGHT_TCC_EN0(ni_pi->cac_weights->weight_tcc_en0) |
32348c2ecf20Sopenharmony_ci		WEIGHT_TCC_EN1(ni_pi->cac_weights->weight_tcc_en1) |
32358c2ecf20Sopenharmony_ci		WEIGHT_TCC_EN2(ni_pi->cac_weights->weight_tcc_en2));
32368c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_1_WEIGHT_1, reg);
32378c2ecf20Sopenharmony_ci
32388c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_2_WEIGHT_0) & ~(WEIGHT_CB_EN0_MASK |
32398c2ecf20Sopenharmony_ci						      WEIGHT_CB_EN1_MASK |
32408c2ecf20Sopenharmony_ci						      WEIGHT_CB_EN2_MASK |
32418c2ecf20Sopenharmony_ci						      WEIGHT_CB_EN3_MASK);
32428c2ecf20Sopenharmony_ci	reg |= (WEIGHT_CB_EN0(ni_pi->cac_weights->weight_cb_en0) |
32438c2ecf20Sopenharmony_ci		WEIGHT_CB_EN1(ni_pi->cac_weights->weight_cb_en1) |
32448c2ecf20Sopenharmony_ci		WEIGHT_CB_EN2(ni_pi->cac_weights->weight_cb_en2) |
32458c2ecf20Sopenharmony_ci		WEIGHT_CB_EN3(ni_pi->cac_weights->weight_cb_en3));
32468c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_2_WEIGHT_0, reg);
32478c2ecf20Sopenharmony_ci
32488c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_2_WEIGHT_1) & ~(WEIGHT_DB_SIG0_MASK |
32498c2ecf20Sopenharmony_ci						      WEIGHT_DB_SIG1_MASK |
32508c2ecf20Sopenharmony_ci						      WEIGHT_DB_SIG2_MASK |
32518c2ecf20Sopenharmony_ci						      WEIGHT_DB_SIG3_MASK);
32528c2ecf20Sopenharmony_ci	reg |= (WEIGHT_DB_SIG0(ni_pi->cac_weights->weight_db_sig0) |
32538c2ecf20Sopenharmony_ci		WEIGHT_DB_SIG1(ni_pi->cac_weights->weight_db_sig1) |
32548c2ecf20Sopenharmony_ci		WEIGHT_DB_SIG2(ni_pi->cac_weights->weight_db_sig2) |
32558c2ecf20Sopenharmony_ci		WEIGHT_DB_SIG3(ni_pi->cac_weights->weight_db_sig3));
32568c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_2_WEIGHT_1, reg);
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_2_WEIGHT_2) & ~(WEIGHT_SXM_SIG0_MASK |
32598c2ecf20Sopenharmony_ci						      WEIGHT_SXM_SIG1_MASK |
32608c2ecf20Sopenharmony_ci						      WEIGHT_SXM_SIG2_MASK |
32618c2ecf20Sopenharmony_ci						      WEIGHT_SXS_SIG0_MASK |
32628c2ecf20Sopenharmony_ci						      WEIGHT_SXS_SIG1_MASK);
32638c2ecf20Sopenharmony_ci	reg |= (WEIGHT_SXM_SIG0(ni_pi->cac_weights->weight_sxm_sig0) |
32648c2ecf20Sopenharmony_ci		WEIGHT_SXM_SIG1(ni_pi->cac_weights->weight_sxm_sig1) |
32658c2ecf20Sopenharmony_ci		WEIGHT_SXM_SIG2(ni_pi->cac_weights->weight_sxm_sig2) |
32668c2ecf20Sopenharmony_ci		WEIGHT_SXS_SIG0(ni_pi->cac_weights->weight_sxs_sig0) |
32678c2ecf20Sopenharmony_ci		WEIGHT_SXS_SIG1(ni_pi->cac_weights->weight_sxs_sig1));
32688c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_2_WEIGHT_2, reg);
32698c2ecf20Sopenharmony_ci
32708c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_3_WEIGHT_0) & ~(WEIGHT_XBR_0_MASK |
32718c2ecf20Sopenharmony_ci						      WEIGHT_XBR_1_MASK |
32728c2ecf20Sopenharmony_ci						      WEIGHT_XBR_2_MASK |
32738c2ecf20Sopenharmony_ci						      WEIGHT_SPI_SIG0_MASK);
32748c2ecf20Sopenharmony_ci	reg |= (WEIGHT_XBR_0(ni_pi->cac_weights->weight_xbr_0) |
32758c2ecf20Sopenharmony_ci		WEIGHT_XBR_1(ni_pi->cac_weights->weight_xbr_1) |
32768c2ecf20Sopenharmony_ci		WEIGHT_XBR_2(ni_pi->cac_weights->weight_xbr_2) |
32778c2ecf20Sopenharmony_ci		WEIGHT_SPI_SIG0(ni_pi->cac_weights->weight_spi_sig0));
32788c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_3_WEIGHT_0, reg);
32798c2ecf20Sopenharmony_ci
32808c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_3_WEIGHT_1) & ~(WEIGHT_SPI_SIG1_MASK |
32818c2ecf20Sopenharmony_ci						      WEIGHT_SPI_SIG2_MASK |
32828c2ecf20Sopenharmony_ci						      WEIGHT_SPI_SIG3_MASK |
32838c2ecf20Sopenharmony_ci						      WEIGHT_SPI_SIG4_MASK |
32848c2ecf20Sopenharmony_ci						      WEIGHT_SPI_SIG5_MASK);
32858c2ecf20Sopenharmony_ci	reg |= (WEIGHT_SPI_SIG1(ni_pi->cac_weights->weight_spi_sig1) |
32868c2ecf20Sopenharmony_ci		WEIGHT_SPI_SIG2(ni_pi->cac_weights->weight_spi_sig2) |
32878c2ecf20Sopenharmony_ci		WEIGHT_SPI_SIG3(ni_pi->cac_weights->weight_spi_sig3) |
32888c2ecf20Sopenharmony_ci		WEIGHT_SPI_SIG4(ni_pi->cac_weights->weight_spi_sig4) |
32898c2ecf20Sopenharmony_ci		WEIGHT_SPI_SIG5(ni_pi->cac_weights->weight_spi_sig5));
32908c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_3_WEIGHT_1, reg);
32918c2ecf20Sopenharmony_ci
32928c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_0) & ~(WEIGHT_LDS_SIG0_MASK |
32938c2ecf20Sopenharmony_ci						      WEIGHT_LDS_SIG1_MASK |
32948c2ecf20Sopenharmony_ci						      WEIGHT_SC_MASK);
32958c2ecf20Sopenharmony_ci	reg |= (WEIGHT_LDS_SIG0(ni_pi->cac_weights->weight_lds_sig0) |
32968c2ecf20Sopenharmony_ci		WEIGHT_LDS_SIG1(ni_pi->cac_weights->weight_lds_sig1) |
32978c2ecf20Sopenharmony_ci		WEIGHT_SC(ni_pi->cac_weights->weight_sc));
32988c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_0, reg);
32998c2ecf20Sopenharmony_ci
33008c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_1) & ~(WEIGHT_BIF_MASK |
33018c2ecf20Sopenharmony_ci						      WEIGHT_CP_MASK |
33028c2ecf20Sopenharmony_ci						      WEIGHT_PA_SIG0_MASK |
33038c2ecf20Sopenharmony_ci						      WEIGHT_PA_SIG1_MASK |
33048c2ecf20Sopenharmony_ci						      WEIGHT_VGT_SIG0_MASK);
33058c2ecf20Sopenharmony_ci	reg |= (WEIGHT_BIF(ni_pi->cac_weights->weight_bif) |
33068c2ecf20Sopenharmony_ci		WEIGHT_CP(ni_pi->cac_weights->weight_cp) |
33078c2ecf20Sopenharmony_ci		WEIGHT_PA_SIG0(ni_pi->cac_weights->weight_pa_sig0) |
33088c2ecf20Sopenharmony_ci		WEIGHT_PA_SIG1(ni_pi->cac_weights->weight_pa_sig1) |
33098c2ecf20Sopenharmony_ci		WEIGHT_VGT_SIG0(ni_pi->cac_weights->weight_vgt_sig0));
33108c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_1, reg);
33118c2ecf20Sopenharmony_ci
33128c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_2) & ~(WEIGHT_VGT_SIG1_MASK |
33138c2ecf20Sopenharmony_ci						      WEIGHT_VGT_SIG2_MASK |
33148c2ecf20Sopenharmony_ci						      WEIGHT_DC_SIG0_MASK |
33158c2ecf20Sopenharmony_ci						      WEIGHT_DC_SIG1_MASK |
33168c2ecf20Sopenharmony_ci						      WEIGHT_DC_SIG2_MASK);
33178c2ecf20Sopenharmony_ci	reg |= (WEIGHT_VGT_SIG1(ni_pi->cac_weights->weight_vgt_sig1) |
33188c2ecf20Sopenharmony_ci		WEIGHT_VGT_SIG2(ni_pi->cac_weights->weight_vgt_sig2) |
33198c2ecf20Sopenharmony_ci		WEIGHT_DC_SIG0(ni_pi->cac_weights->weight_dc_sig0) |
33208c2ecf20Sopenharmony_ci		WEIGHT_DC_SIG1(ni_pi->cac_weights->weight_dc_sig1) |
33218c2ecf20Sopenharmony_ci		WEIGHT_DC_SIG2(ni_pi->cac_weights->weight_dc_sig2));
33228c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_2, reg);
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_3) & ~(WEIGHT_DC_SIG3_MASK |
33258c2ecf20Sopenharmony_ci						      WEIGHT_UVD_SIG0_MASK |
33268c2ecf20Sopenharmony_ci						      WEIGHT_UVD_SIG1_MASK |
33278c2ecf20Sopenharmony_ci						      WEIGHT_SPARE0_MASK |
33288c2ecf20Sopenharmony_ci						      WEIGHT_SPARE1_MASK);
33298c2ecf20Sopenharmony_ci	reg |= (WEIGHT_DC_SIG3(ni_pi->cac_weights->weight_dc_sig3) |
33308c2ecf20Sopenharmony_ci		WEIGHT_UVD_SIG0(ni_pi->cac_weights->weight_uvd_sig0) |
33318c2ecf20Sopenharmony_ci		WEIGHT_UVD_SIG1(ni_pi->cac_weights->weight_uvd_sig1) |
33328c2ecf20Sopenharmony_ci		WEIGHT_SPARE0(ni_pi->cac_weights->weight_spare0) |
33338c2ecf20Sopenharmony_ci		WEIGHT_SPARE1(ni_pi->cac_weights->weight_spare1));
33348c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_3, reg);
33358c2ecf20Sopenharmony_ci
33368c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_5_WEIGHT_0) & ~(WEIGHT_SQ_VSP_MASK |
33378c2ecf20Sopenharmony_ci						      WEIGHT_SQ_VSP0_MASK);
33388c2ecf20Sopenharmony_ci	reg |= (WEIGHT_SQ_VSP(ni_pi->cac_weights->weight_sq_vsp) |
33398c2ecf20Sopenharmony_ci		WEIGHT_SQ_VSP0(ni_pi->cac_weights->weight_sq_vsp0));
33408c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_5_WEIGHT_0, reg);
33418c2ecf20Sopenharmony_ci
33428c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_5_WEIGHT_1) & ~(WEIGHT_SQ_GPR_MASK);
33438c2ecf20Sopenharmony_ci	reg |= WEIGHT_SQ_GPR(ni_pi->cac_weights->weight_sq_gpr);
33448c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_5_WEIGHT_1, reg);
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_OVERRIDE_4) & ~(OVR_MODE_SPARE_0_MASK |
33478c2ecf20Sopenharmony_ci							OVR_VAL_SPARE_0_MASK |
33488c2ecf20Sopenharmony_ci							OVR_MODE_SPARE_1_MASK |
33498c2ecf20Sopenharmony_ci							OVR_VAL_SPARE_1_MASK);
33508c2ecf20Sopenharmony_ci	reg |= (OVR_MODE_SPARE_0(ni_pi->cac_weights->ovr_mode_spare_0) |
33518c2ecf20Sopenharmony_ci		OVR_VAL_SPARE_0(ni_pi->cac_weights->ovr_val_spare_0) |
33528c2ecf20Sopenharmony_ci		OVR_MODE_SPARE_1(ni_pi->cac_weights->ovr_mode_spare_1) |
33538c2ecf20Sopenharmony_ci		OVR_VAL_SPARE_1(ni_pi->cac_weights->ovr_val_spare_1));
33548c2ecf20Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_OVERRIDE_4, reg);
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	reg = RREG32(SQ_CAC_THRESHOLD) & ~(VSP_MASK |
33578c2ecf20Sopenharmony_ci					   VSP0_MASK |
33588c2ecf20Sopenharmony_ci					   GPR_MASK);
33598c2ecf20Sopenharmony_ci	reg |= (VSP(ni_pi->cac_weights->vsp) |
33608c2ecf20Sopenharmony_ci		VSP0(ni_pi->cac_weights->vsp0) |
33618c2ecf20Sopenharmony_ci		GPR(ni_pi->cac_weights->gpr));
33628c2ecf20Sopenharmony_ci	WREG32(SQ_CAC_THRESHOLD, reg);
33638c2ecf20Sopenharmony_ci
33648c2ecf20Sopenharmony_ci	reg = (MCDW_WR_ENABLE |
33658c2ecf20Sopenharmony_ci	       MCDX_WR_ENABLE |
33668c2ecf20Sopenharmony_ci	       MCDY_WR_ENABLE |
33678c2ecf20Sopenharmony_ci	       MCDZ_WR_ENABLE |
33688c2ecf20Sopenharmony_ci	       INDEX(0x09D4));
33698c2ecf20Sopenharmony_ci	WREG32(MC_CG_CONFIG, reg);
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci	reg = (READ_WEIGHT(ni_pi->cac_weights->mc_read_weight) |
33728c2ecf20Sopenharmony_ci	       WRITE_WEIGHT(ni_pi->cac_weights->mc_write_weight) |
33738c2ecf20Sopenharmony_ci	       ALLOW_OVERFLOW);
33748c2ecf20Sopenharmony_ci	WREG32(MC_CG_DATAPORT, reg);
33758c2ecf20Sopenharmony_ci
33768c2ecf20Sopenharmony_ci	return 0;
33778c2ecf20Sopenharmony_ci}
33788c2ecf20Sopenharmony_ci
33798c2ecf20Sopenharmony_cistatic int ni_enable_smc_cac(struct radeon_device *rdev,
33808c2ecf20Sopenharmony_ci			     struct radeon_ps *radeon_new_state,
33818c2ecf20Sopenharmony_ci			     bool enable)
33828c2ecf20Sopenharmony_ci{
33838c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
33848c2ecf20Sopenharmony_ci	int ret = 0;
33858c2ecf20Sopenharmony_ci	PPSMC_Result smc_result;
33868c2ecf20Sopenharmony_ci
33878c2ecf20Sopenharmony_ci	if (ni_pi->enable_cac) {
33888c2ecf20Sopenharmony_ci		if (enable) {
33898c2ecf20Sopenharmony_ci			if (!r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
33908c2ecf20Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_CollectCAC_PowerCorreln);
33918c2ecf20Sopenharmony_ci
33928c2ecf20Sopenharmony_ci				if (ni_pi->support_cac_long_term_average) {
33938c2ecf20Sopenharmony_ci					smc_result = rv770_send_msg_to_smc(rdev, PPSMC_CACLongTermAvgEnable);
33948c2ecf20Sopenharmony_ci					if (PPSMC_Result_OK != smc_result)
33958c2ecf20Sopenharmony_ci						ni_pi->support_cac_long_term_average = false;
33968c2ecf20Sopenharmony_ci				}
33978c2ecf20Sopenharmony_ci
33988c2ecf20Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableCac);
33998c2ecf20Sopenharmony_ci				if (PPSMC_Result_OK != smc_result)
34008c2ecf20Sopenharmony_ci					ret = -EINVAL;
34018c2ecf20Sopenharmony_ci
34028c2ecf20Sopenharmony_ci				ni_pi->cac_enabled = (PPSMC_Result_OK == smc_result) ? true : false;
34038c2ecf20Sopenharmony_ci			}
34048c2ecf20Sopenharmony_ci		} else if (ni_pi->cac_enabled) {
34058c2ecf20Sopenharmony_ci			smc_result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_DisableCac);
34068c2ecf20Sopenharmony_ci
34078c2ecf20Sopenharmony_ci			ni_pi->cac_enabled = false;
34088c2ecf20Sopenharmony_ci
34098c2ecf20Sopenharmony_ci			if (ni_pi->support_cac_long_term_average) {
34108c2ecf20Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_CACLongTermAvgDisable);
34118c2ecf20Sopenharmony_ci				if (PPSMC_Result_OK != smc_result)
34128c2ecf20Sopenharmony_ci					ni_pi->support_cac_long_term_average = false;
34138c2ecf20Sopenharmony_ci			}
34148c2ecf20Sopenharmony_ci		}
34158c2ecf20Sopenharmony_ci	}
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci	return ret;
34188c2ecf20Sopenharmony_ci}
34198c2ecf20Sopenharmony_ci
34208c2ecf20Sopenharmony_cistatic int ni_pcie_performance_request(struct radeon_device *rdev,
34218c2ecf20Sopenharmony_ci				       u8 perf_req, bool advertise)
34228c2ecf20Sopenharmony_ci{
34238c2ecf20Sopenharmony_ci#if defined(CONFIG_ACPI)
34248c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
34258c2ecf20Sopenharmony_ci
34268c2ecf20Sopenharmony_ci	if ((perf_req == PCIE_PERF_REQ_PECI_GEN1) ||
34278c2ecf20Sopenharmony_ci	    (perf_req == PCIE_PERF_REQ_PECI_GEN2)) {
34288c2ecf20Sopenharmony_ci		if (eg_pi->pcie_performance_request_registered == false)
34298c2ecf20Sopenharmony_ci			radeon_acpi_pcie_notify_device_ready(rdev);
34308c2ecf20Sopenharmony_ci		eg_pi->pcie_performance_request_registered = true;
34318c2ecf20Sopenharmony_ci		return radeon_acpi_pcie_performance_request(rdev, perf_req, advertise);
34328c2ecf20Sopenharmony_ci	} else if ((perf_req == PCIE_PERF_REQ_REMOVE_REGISTRY) &&
34338c2ecf20Sopenharmony_ci		    eg_pi->pcie_performance_request_registered) {
34348c2ecf20Sopenharmony_ci		eg_pi->pcie_performance_request_registered = false;
34358c2ecf20Sopenharmony_ci		return radeon_acpi_pcie_performance_request(rdev, perf_req, advertise);
34368c2ecf20Sopenharmony_ci	}
34378c2ecf20Sopenharmony_ci#endif
34388c2ecf20Sopenharmony_ci	return 0;
34398c2ecf20Sopenharmony_ci}
34408c2ecf20Sopenharmony_ci
34418c2ecf20Sopenharmony_cistatic int ni_advertise_gen2_capability(struct radeon_device *rdev)
34428c2ecf20Sopenharmony_ci{
34438c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
34448c2ecf20Sopenharmony_ci	u32 tmp;
34458c2ecf20Sopenharmony_ci
34468c2ecf20Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
34478c2ecf20Sopenharmony_ci
34488c2ecf20Sopenharmony_ci	if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
34498c2ecf20Sopenharmony_ci	    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
34508c2ecf20Sopenharmony_ci		pi->pcie_gen2 = true;
34518c2ecf20Sopenharmony_ci	else
34528c2ecf20Sopenharmony_ci		pi->pcie_gen2 = false;
34538c2ecf20Sopenharmony_ci
34548c2ecf20Sopenharmony_ci	if (!pi->pcie_gen2)
34558c2ecf20Sopenharmony_ci		ni_pcie_performance_request(rdev, PCIE_PERF_REQ_PECI_GEN2, true);
34568c2ecf20Sopenharmony_ci
34578c2ecf20Sopenharmony_ci	return 0;
34588c2ecf20Sopenharmony_ci}
34598c2ecf20Sopenharmony_ci
34608c2ecf20Sopenharmony_cistatic void ni_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
34618c2ecf20Sopenharmony_ci					    bool enable)
34628c2ecf20Sopenharmony_ci{
34638c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
34648c2ecf20Sopenharmony_ci	u32 tmp, bif;
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
34678c2ecf20Sopenharmony_ci
34688c2ecf20Sopenharmony_ci	if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
34698c2ecf20Sopenharmony_ci	    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
34708c2ecf20Sopenharmony_ci		if (enable) {
34718c2ecf20Sopenharmony_ci			if (!pi->boot_in_gen2) {
34728c2ecf20Sopenharmony_ci				bif = RREG32(CG_BIF_REQ_AND_RSP) & ~CG_CLIENT_REQ_MASK;
34738c2ecf20Sopenharmony_ci				bif |= CG_CLIENT_REQ(0xd);
34748c2ecf20Sopenharmony_ci				WREG32(CG_BIF_REQ_AND_RSP, bif);
34758c2ecf20Sopenharmony_ci			}
34768c2ecf20Sopenharmony_ci			tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
34778c2ecf20Sopenharmony_ci			tmp |= LC_HW_VOLTAGE_IF_CONTROL(1);
34788c2ecf20Sopenharmony_ci			tmp |= LC_GEN2_EN_STRAP;
34798c2ecf20Sopenharmony_ci
34808c2ecf20Sopenharmony_ci			tmp |= LC_CLR_FAILED_SPD_CHANGE_CNT;
34818c2ecf20Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
34828c2ecf20Sopenharmony_ci			udelay(10);
34838c2ecf20Sopenharmony_ci			tmp &= ~LC_CLR_FAILED_SPD_CHANGE_CNT;
34848c2ecf20Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
34858c2ecf20Sopenharmony_ci		} else {
34868c2ecf20Sopenharmony_ci			if (!pi->boot_in_gen2) {
34878c2ecf20Sopenharmony_ci				bif = RREG32(CG_BIF_REQ_AND_RSP) & ~CG_CLIENT_REQ_MASK;
34888c2ecf20Sopenharmony_ci				bif |= CG_CLIENT_REQ(0xd);
34898c2ecf20Sopenharmony_ci				WREG32(CG_BIF_REQ_AND_RSP, bif);
34908c2ecf20Sopenharmony_ci
34918c2ecf20Sopenharmony_ci				tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
34928c2ecf20Sopenharmony_ci				tmp &= ~LC_GEN2_EN_STRAP;
34938c2ecf20Sopenharmony_ci			}
34948c2ecf20Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
34958c2ecf20Sopenharmony_ci		}
34968c2ecf20Sopenharmony_ci	}
34978c2ecf20Sopenharmony_ci}
34988c2ecf20Sopenharmony_ci
34998c2ecf20Sopenharmony_cistatic void ni_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
35008c2ecf20Sopenharmony_ci					bool enable)
35018c2ecf20Sopenharmony_ci{
35028c2ecf20Sopenharmony_ci	ni_enable_bif_dynamic_pcie_gen2(rdev, enable);
35038c2ecf20Sopenharmony_ci
35048c2ecf20Sopenharmony_ci	if (enable)
35058c2ecf20Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE);
35068c2ecf20Sopenharmony_ci	else
35078c2ecf20Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE);
35088c2ecf20Sopenharmony_ci}
35098c2ecf20Sopenharmony_ci
35108c2ecf20Sopenharmony_civoid ni_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
35118c2ecf20Sopenharmony_ci					   struct radeon_ps *new_ps,
35128c2ecf20Sopenharmony_ci					   struct radeon_ps *old_ps)
35138c2ecf20Sopenharmony_ci{
35148c2ecf20Sopenharmony_ci	struct ni_ps *new_state = ni_get_ps(new_ps);
35158c2ecf20Sopenharmony_ci	struct ni_ps *current_state = ni_get_ps(old_ps);
35168c2ecf20Sopenharmony_ci
35178c2ecf20Sopenharmony_ci	if ((new_ps->vclk == old_ps->vclk) &&
35188c2ecf20Sopenharmony_ci	    (new_ps->dclk == old_ps->dclk))
35198c2ecf20Sopenharmony_ci		return;
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_ci	if (new_state->performance_levels[new_state->performance_level_count - 1].sclk >=
35228c2ecf20Sopenharmony_ci	    current_state->performance_levels[current_state->performance_level_count - 1].sclk)
35238c2ecf20Sopenharmony_ci		return;
35248c2ecf20Sopenharmony_ci
35258c2ecf20Sopenharmony_ci	radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
35268c2ecf20Sopenharmony_ci}
35278c2ecf20Sopenharmony_ci
35288c2ecf20Sopenharmony_civoid ni_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
35298c2ecf20Sopenharmony_ci					  struct radeon_ps *new_ps,
35308c2ecf20Sopenharmony_ci					  struct radeon_ps *old_ps)
35318c2ecf20Sopenharmony_ci{
35328c2ecf20Sopenharmony_ci	struct ni_ps *new_state = ni_get_ps(new_ps);
35338c2ecf20Sopenharmony_ci	struct ni_ps *current_state = ni_get_ps(old_ps);
35348c2ecf20Sopenharmony_ci
35358c2ecf20Sopenharmony_ci	if ((new_ps->vclk == old_ps->vclk) &&
35368c2ecf20Sopenharmony_ci	    (new_ps->dclk == old_ps->dclk))
35378c2ecf20Sopenharmony_ci		return;
35388c2ecf20Sopenharmony_ci
35398c2ecf20Sopenharmony_ci	if (new_state->performance_levels[new_state->performance_level_count - 1].sclk <
35408c2ecf20Sopenharmony_ci	    current_state->performance_levels[current_state->performance_level_count - 1].sclk)
35418c2ecf20Sopenharmony_ci		return;
35428c2ecf20Sopenharmony_ci
35438c2ecf20Sopenharmony_ci	radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
35448c2ecf20Sopenharmony_ci}
35458c2ecf20Sopenharmony_ci
35468c2ecf20Sopenharmony_civoid ni_dpm_setup_asic(struct radeon_device *rdev)
35478c2ecf20Sopenharmony_ci{
35488c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
35498c2ecf20Sopenharmony_ci	int r;
35508c2ecf20Sopenharmony_ci
35518c2ecf20Sopenharmony_ci	r = ni_mc_load_microcode(rdev);
35528c2ecf20Sopenharmony_ci	if (r)
35538c2ecf20Sopenharmony_ci		DRM_ERROR("Failed to load MC firmware!\n");
35548c2ecf20Sopenharmony_ci	ni_read_clock_registers(rdev);
35558c2ecf20Sopenharmony_ci	btc_read_arb_registers(rdev);
35568c2ecf20Sopenharmony_ci	rv770_get_memory_type(rdev);
35578c2ecf20Sopenharmony_ci	if (eg_pi->pcie_performance_request)
35588c2ecf20Sopenharmony_ci		ni_advertise_gen2_capability(rdev);
35598c2ecf20Sopenharmony_ci	rv770_get_pcie_gen2_status(rdev);
35608c2ecf20Sopenharmony_ci	rv770_enable_acpi_pm(rdev);
35618c2ecf20Sopenharmony_ci}
35628c2ecf20Sopenharmony_ci
35638c2ecf20Sopenharmony_civoid ni_update_current_ps(struct radeon_device *rdev,
35648c2ecf20Sopenharmony_ci			  struct radeon_ps *rps)
35658c2ecf20Sopenharmony_ci{
35668c2ecf20Sopenharmony_ci	struct ni_ps *new_ps = ni_get_ps(rps);
35678c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
35688c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
35698c2ecf20Sopenharmony_ci
35708c2ecf20Sopenharmony_ci	eg_pi->current_rps = *rps;
35718c2ecf20Sopenharmony_ci	ni_pi->current_ps = *new_ps;
35728c2ecf20Sopenharmony_ci	eg_pi->current_rps.ps_priv = &ni_pi->current_ps;
35738c2ecf20Sopenharmony_ci}
35748c2ecf20Sopenharmony_ci
35758c2ecf20Sopenharmony_civoid ni_update_requested_ps(struct radeon_device *rdev,
35768c2ecf20Sopenharmony_ci			    struct radeon_ps *rps)
35778c2ecf20Sopenharmony_ci{
35788c2ecf20Sopenharmony_ci	struct ni_ps *new_ps = ni_get_ps(rps);
35798c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
35808c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
35818c2ecf20Sopenharmony_ci
35828c2ecf20Sopenharmony_ci	eg_pi->requested_rps = *rps;
35838c2ecf20Sopenharmony_ci	ni_pi->requested_ps = *new_ps;
35848c2ecf20Sopenharmony_ci	eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps;
35858c2ecf20Sopenharmony_ci}
35868c2ecf20Sopenharmony_ci
35878c2ecf20Sopenharmony_ciint ni_dpm_enable(struct radeon_device *rdev)
35888c2ecf20Sopenharmony_ci{
35898c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
35908c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
35918c2ecf20Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
35928c2ecf20Sopenharmony_ci	int ret;
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci	if (pi->gfx_clock_gating)
35958c2ecf20Sopenharmony_ci		ni_cg_clockgating_default(rdev);
35968c2ecf20Sopenharmony_ci	if (btc_dpm_enabled(rdev))
35978c2ecf20Sopenharmony_ci		return -EINVAL;
35988c2ecf20Sopenharmony_ci	if (pi->mg_clock_gating)
35998c2ecf20Sopenharmony_ci		ni_mg_clockgating_default(rdev);
36008c2ecf20Sopenharmony_ci	if (eg_pi->ls_clock_gating)
36018c2ecf20Sopenharmony_ci		ni_ls_clockgating_default(rdev);
36028c2ecf20Sopenharmony_ci	if (pi->voltage_control) {
36038c2ecf20Sopenharmony_ci		rv770_enable_voltage_control(rdev, true);
36048c2ecf20Sopenharmony_ci		ret = cypress_construct_voltage_tables(rdev);
36058c2ecf20Sopenharmony_ci		if (ret) {
36068c2ecf20Sopenharmony_ci			DRM_ERROR("cypress_construct_voltage_tables failed\n");
36078c2ecf20Sopenharmony_ci			return ret;
36088c2ecf20Sopenharmony_ci		}
36098c2ecf20Sopenharmony_ci	}
36108c2ecf20Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
36118c2ecf20Sopenharmony_ci		ret = ni_initialize_mc_reg_table(rdev);
36128c2ecf20Sopenharmony_ci		if (ret)
36138c2ecf20Sopenharmony_ci			eg_pi->dynamic_ac_timing = false;
36148c2ecf20Sopenharmony_ci	}
36158c2ecf20Sopenharmony_ci	if (pi->dynamic_ss)
36168c2ecf20Sopenharmony_ci		cypress_enable_spread_spectrum(rdev, true);
36178c2ecf20Sopenharmony_ci	if (pi->thermal_protection)
36188c2ecf20Sopenharmony_ci		rv770_enable_thermal_protection(rdev, true);
36198c2ecf20Sopenharmony_ci	rv770_setup_bsp(rdev);
36208c2ecf20Sopenharmony_ci	rv770_program_git(rdev);
36218c2ecf20Sopenharmony_ci	rv770_program_tp(rdev);
36228c2ecf20Sopenharmony_ci	rv770_program_tpp(rdev);
36238c2ecf20Sopenharmony_ci	rv770_program_sstp(rdev);
36248c2ecf20Sopenharmony_ci	cypress_enable_display_gap(rdev);
36258c2ecf20Sopenharmony_ci	rv770_program_vc(rdev);
36268c2ecf20Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
36278c2ecf20Sopenharmony_ci		ni_enable_dynamic_pcie_gen2(rdev, true);
36288c2ecf20Sopenharmony_ci	ret = rv770_upload_firmware(rdev);
36298c2ecf20Sopenharmony_ci	if (ret) {
36308c2ecf20Sopenharmony_ci		DRM_ERROR("rv770_upload_firmware failed\n");
36318c2ecf20Sopenharmony_ci		return ret;
36328c2ecf20Sopenharmony_ci	}
36338c2ecf20Sopenharmony_ci	ret = ni_process_firmware_header(rdev);
36348c2ecf20Sopenharmony_ci	if (ret) {
36358c2ecf20Sopenharmony_ci		DRM_ERROR("ni_process_firmware_header failed\n");
36368c2ecf20Sopenharmony_ci		return ret;
36378c2ecf20Sopenharmony_ci	}
36388c2ecf20Sopenharmony_ci	ret = ni_initial_switch_from_arb_f0_to_f1(rdev);
36398c2ecf20Sopenharmony_ci	if (ret) {
36408c2ecf20Sopenharmony_ci		DRM_ERROR("ni_initial_switch_from_arb_f0_to_f1 failed\n");
36418c2ecf20Sopenharmony_ci		return ret;
36428c2ecf20Sopenharmony_ci	}
36438c2ecf20Sopenharmony_ci	ret = ni_init_smc_table(rdev);
36448c2ecf20Sopenharmony_ci	if (ret) {
36458c2ecf20Sopenharmony_ci		DRM_ERROR("ni_init_smc_table failed\n");
36468c2ecf20Sopenharmony_ci		return ret;
36478c2ecf20Sopenharmony_ci	}
36488c2ecf20Sopenharmony_ci	ret = ni_init_smc_spll_table(rdev);
36498c2ecf20Sopenharmony_ci	if (ret) {
36508c2ecf20Sopenharmony_ci		DRM_ERROR("ni_init_smc_spll_table failed\n");
36518c2ecf20Sopenharmony_ci		return ret;
36528c2ecf20Sopenharmony_ci	}
36538c2ecf20Sopenharmony_ci	ret = ni_init_arb_table_index(rdev);
36548c2ecf20Sopenharmony_ci	if (ret) {
36558c2ecf20Sopenharmony_ci		DRM_ERROR("ni_init_arb_table_index failed\n");
36568c2ecf20Sopenharmony_ci		return ret;
36578c2ecf20Sopenharmony_ci	}
36588c2ecf20Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
36598c2ecf20Sopenharmony_ci		ret = ni_populate_mc_reg_table(rdev, boot_ps);
36608c2ecf20Sopenharmony_ci		if (ret) {
36618c2ecf20Sopenharmony_ci			DRM_ERROR("ni_populate_mc_reg_table failed\n");
36628c2ecf20Sopenharmony_ci			return ret;
36638c2ecf20Sopenharmony_ci		}
36648c2ecf20Sopenharmony_ci	}
36658c2ecf20Sopenharmony_ci	ret = ni_initialize_smc_cac_tables(rdev);
36668c2ecf20Sopenharmony_ci	if (ret) {
36678c2ecf20Sopenharmony_ci		DRM_ERROR("ni_initialize_smc_cac_tables failed\n");
36688c2ecf20Sopenharmony_ci		return ret;
36698c2ecf20Sopenharmony_ci	}
36708c2ecf20Sopenharmony_ci	ret = ni_initialize_hardware_cac_manager(rdev);
36718c2ecf20Sopenharmony_ci	if (ret) {
36728c2ecf20Sopenharmony_ci		DRM_ERROR("ni_initialize_hardware_cac_manager failed\n");
36738c2ecf20Sopenharmony_ci		return ret;
36748c2ecf20Sopenharmony_ci	}
36758c2ecf20Sopenharmony_ci	ret = ni_populate_smc_tdp_limits(rdev, boot_ps);
36768c2ecf20Sopenharmony_ci	if (ret) {
36778c2ecf20Sopenharmony_ci		DRM_ERROR("ni_populate_smc_tdp_limits failed\n");
36788c2ecf20Sopenharmony_ci		return ret;
36798c2ecf20Sopenharmony_ci	}
36808c2ecf20Sopenharmony_ci	ni_program_response_times(rdev);
36818c2ecf20Sopenharmony_ci	r7xx_start_smc(rdev);
36828c2ecf20Sopenharmony_ci	ret = cypress_notify_smc_display_change(rdev, false);
36838c2ecf20Sopenharmony_ci	if (ret) {
36848c2ecf20Sopenharmony_ci		DRM_ERROR("cypress_notify_smc_display_change failed\n");
36858c2ecf20Sopenharmony_ci		return ret;
36868c2ecf20Sopenharmony_ci	}
36878c2ecf20Sopenharmony_ci	cypress_enable_sclk_control(rdev, true);
36888c2ecf20Sopenharmony_ci	if (eg_pi->memory_transition)
36898c2ecf20Sopenharmony_ci		cypress_enable_mclk_control(rdev, true);
36908c2ecf20Sopenharmony_ci	cypress_start_dpm(rdev);
36918c2ecf20Sopenharmony_ci	if (pi->gfx_clock_gating)
36928c2ecf20Sopenharmony_ci		ni_gfx_clockgating_enable(rdev, true);
36938c2ecf20Sopenharmony_ci	if (pi->mg_clock_gating)
36948c2ecf20Sopenharmony_ci		ni_mg_clockgating_enable(rdev, true);
36958c2ecf20Sopenharmony_ci	if (eg_pi->ls_clock_gating)
36968c2ecf20Sopenharmony_ci		ni_ls_clockgating_enable(rdev, true);
36978c2ecf20Sopenharmony_ci
36988c2ecf20Sopenharmony_ci	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
36998c2ecf20Sopenharmony_ci
37008c2ecf20Sopenharmony_ci	ni_update_current_ps(rdev, boot_ps);
37018c2ecf20Sopenharmony_ci
37028c2ecf20Sopenharmony_ci	return 0;
37038c2ecf20Sopenharmony_ci}
37048c2ecf20Sopenharmony_ci
37058c2ecf20Sopenharmony_civoid ni_dpm_disable(struct radeon_device *rdev)
37068c2ecf20Sopenharmony_ci{
37078c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
37088c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
37098c2ecf20Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
37108c2ecf20Sopenharmony_ci
37118c2ecf20Sopenharmony_ci	if (!btc_dpm_enabled(rdev))
37128c2ecf20Sopenharmony_ci		return;
37138c2ecf20Sopenharmony_ci	rv770_clear_vc(rdev);
37148c2ecf20Sopenharmony_ci	if (pi->thermal_protection)
37158c2ecf20Sopenharmony_ci		rv770_enable_thermal_protection(rdev, false);
37168c2ecf20Sopenharmony_ci	ni_enable_power_containment(rdev, boot_ps, false);
37178c2ecf20Sopenharmony_ci	ni_enable_smc_cac(rdev, boot_ps, false);
37188c2ecf20Sopenharmony_ci	cypress_enable_spread_spectrum(rdev, false);
37198c2ecf20Sopenharmony_ci	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, false);
37208c2ecf20Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
37218c2ecf20Sopenharmony_ci		ni_enable_dynamic_pcie_gen2(rdev, false);
37228c2ecf20Sopenharmony_ci
37238c2ecf20Sopenharmony_ci	if (rdev->irq.installed &&
37248c2ecf20Sopenharmony_ci	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
37258c2ecf20Sopenharmony_ci		rdev->irq.dpm_thermal = false;
37268c2ecf20Sopenharmony_ci		radeon_irq_set(rdev);
37278c2ecf20Sopenharmony_ci	}
37288c2ecf20Sopenharmony_ci
37298c2ecf20Sopenharmony_ci	if (pi->gfx_clock_gating)
37308c2ecf20Sopenharmony_ci		ni_gfx_clockgating_enable(rdev, false);
37318c2ecf20Sopenharmony_ci	if (pi->mg_clock_gating)
37328c2ecf20Sopenharmony_ci		ni_mg_clockgating_enable(rdev, false);
37338c2ecf20Sopenharmony_ci	if (eg_pi->ls_clock_gating)
37348c2ecf20Sopenharmony_ci		ni_ls_clockgating_enable(rdev, false);
37358c2ecf20Sopenharmony_ci	ni_stop_dpm(rdev);
37368c2ecf20Sopenharmony_ci	btc_reset_to_default(rdev);
37378c2ecf20Sopenharmony_ci	ni_stop_smc(rdev);
37388c2ecf20Sopenharmony_ci	ni_force_switch_to_arb_f0(rdev);
37398c2ecf20Sopenharmony_ci
37408c2ecf20Sopenharmony_ci	ni_update_current_ps(rdev, boot_ps);
37418c2ecf20Sopenharmony_ci}
37428c2ecf20Sopenharmony_ci
37438c2ecf20Sopenharmony_cistatic int ni_power_control_set_level(struct radeon_device *rdev)
37448c2ecf20Sopenharmony_ci{
37458c2ecf20Sopenharmony_ci	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
37468c2ecf20Sopenharmony_ci	int ret;
37478c2ecf20Sopenharmony_ci
37488c2ecf20Sopenharmony_ci	ret = ni_restrict_performance_levels_before_switch(rdev);
37498c2ecf20Sopenharmony_ci	if (ret)
37508c2ecf20Sopenharmony_ci		return ret;
37518c2ecf20Sopenharmony_ci	ret = rv770_halt_smc(rdev);
37528c2ecf20Sopenharmony_ci	if (ret)
37538c2ecf20Sopenharmony_ci		return ret;
37548c2ecf20Sopenharmony_ci	ret = ni_populate_smc_tdp_limits(rdev, new_ps);
37558c2ecf20Sopenharmony_ci	if (ret)
37568c2ecf20Sopenharmony_ci		return ret;
37578c2ecf20Sopenharmony_ci	ret = rv770_resume_smc(rdev);
37588c2ecf20Sopenharmony_ci	if (ret)
37598c2ecf20Sopenharmony_ci		return ret;
37608c2ecf20Sopenharmony_ci	ret = rv770_set_sw_state(rdev);
37618c2ecf20Sopenharmony_ci	if (ret)
37628c2ecf20Sopenharmony_ci		return ret;
37638c2ecf20Sopenharmony_ci
37648c2ecf20Sopenharmony_ci	return 0;
37658c2ecf20Sopenharmony_ci}
37668c2ecf20Sopenharmony_ci
37678c2ecf20Sopenharmony_ciint ni_dpm_pre_set_power_state(struct radeon_device *rdev)
37688c2ecf20Sopenharmony_ci{
37698c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
37708c2ecf20Sopenharmony_ci	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
37718c2ecf20Sopenharmony_ci	struct radeon_ps *new_ps = &requested_ps;
37728c2ecf20Sopenharmony_ci
37738c2ecf20Sopenharmony_ci	ni_update_requested_ps(rdev, new_ps);
37748c2ecf20Sopenharmony_ci
37758c2ecf20Sopenharmony_ci	ni_apply_state_adjust_rules(rdev, &eg_pi->requested_rps);
37768c2ecf20Sopenharmony_ci
37778c2ecf20Sopenharmony_ci	return 0;
37788c2ecf20Sopenharmony_ci}
37798c2ecf20Sopenharmony_ci
37808c2ecf20Sopenharmony_ciint ni_dpm_set_power_state(struct radeon_device *rdev)
37818c2ecf20Sopenharmony_ci{
37828c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
37838c2ecf20Sopenharmony_ci	struct radeon_ps *new_ps = &eg_pi->requested_rps;
37848c2ecf20Sopenharmony_ci	struct radeon_ps *old_ps = &eg_pi->current_rps;
37858c2ecf20Sopenharmony_ci	int ret;
37868c2ecf20Sopenharmony_ci
37878c2ecf20Sopenharmony_ci	ret = ni_restrict_performance_levels_before_switch(rdev);
37888c2ecf20Sopenharmony_ci	if (ret) {
37898c2ecf20Sopenharmony_ci		DRM_ERROR("ni_restrict_performance_levels_before_switch failed\n");
37908c2ecf20Sopenharmony_ci		return ret;
37918c2ecf20Sopenharmony_ci	}
37928c2ecf20Sopenharmony_ci	ni_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
37938c2ecf20Sopenharmony_ci	ret = ni_enable_power_containment(rdev, new_ps, false);
37948c2ecf20Sopenharmony_ci	if (ret) {
37958c2ecf20Sopenharmony_ci		DRM_ERROR("ni_enable_power_containment failed\n");
37968c2ecf20Sopenharmony_ci		return ret;
37978c2ecf20Sopenharmony_ci	}
37988c2ecf20Sopenharmony_ci	ret = ni_enable_smc_cac(rdev, new_ps, false);
37998c2ecf20Sopenharmony_ci	if (ret) {
38008c2ecf20Sopenharmony_ci		DRM_ERROR("ni_enable_smc_cac failed\n");
38018c2ecf20Sopenharmony_ci		return ret;
38028c2ecf20Sopenharmony_ci	}
38038c2ecf20Sopenharmony_ci	ret = rv770_halt_smc(rdev);
38048c2ecf20Sopenharmony_ci	if (ret) {
38058c2ecf20Sopenharmony_ci		DRM_ERROR("rv770_halt_smc failed\n");
38068c2ecf20Sopenharmony_ci		return ret;
38078c2ecf20Sopenharmony_ci	}
38088c2ecf20Sopenharmony_ci	if (eg_pi->smu_uvd_hs)
38098c2ecf20Sopenharmony_ci		btc_notify_uvd_to_smc(rdev, new_ps);
38108c2ecf20Sopenharmony_ci	ret = ni_upload_sw_state(rdev, new_ps);
38118c2ecf20Sopenharmony_ci	if (ret) {
38128c2ecf20Sopenharmony_ci		DRM_ERROR("ni_upload_sw_state failed\n");
38138c2ecf20Sopenharmony_ci		return ret;
38148c2ecf20Sopenharmony_ci	}
38158c2ecf20Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
38168c2ecf20Sopenharmony_ci		ret = ni_upload_mc_reg_table(rdev, new_ps);
38178c2ecf20Sopenharmony_ci		if (ret) {
38188c2ecf20Sopenharmony_ci			DRM_ERROR("ni_upload_mc_reg_table failed\n");
38198c2ecf20Sopenharmony_ci			return ret;
38208c2ecf20Sopenharmony_ci		}
38218c2ecf20Sopenharmony_ci	}
38228c2ecf20Sopenharmony_ci	ret = ni_program_memory_timing_parameters(rdev, new_ps);
38238c2ecf20Sopenharmony_ci	if (ret) {
38248c2ecf20Sopenharmony_ci		DRM_ERROR("ni_program_memory_timing_parameters failed\n");
38258c2ecf20Sopenharmony_ci		return ret;
38268c2ecf20Sopenharmony_ci	}
38278c2ecf20Sopenharmony_ci	ret = rv770_resume_smc(rdev);
38288c2ecf20Sopenharmony_ci	if (ret) {
38298c2ecf20Sopenharmony_ci		DRM_ERROR("rv770_resume_smc failed\n");
38308c2ecf20Sopenharmony_ci		return ret;
38318c2ecf20Sopenharmony_ci	}
38328c2ecf20Sopenharmony_ci	ret = rv770_set_sw_state(rdev);
38338c2ecf20Sopenharmony_ci	if (ret) {
38348c2ecf20Sopenharmony_ci		DRM_ERROR("rv770_set_sw_state failed\n");
38358c2ecf20Sopenharmony_ci		return ret;
38368c2ecf20Sopenharmony_ci	}
38378c2ecf20Sopenharmony_ci	ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
38388c2ecf20Sopenharmony_ci	ret = ni_enable_smc_cac(rdev, new_ps, true);
38398c2ecf20Sopenharmony_ci	if (ret) {
38408c2ecf20Sopenharmony_ci		DRM_ERROR("ni_enable_smc_cac failed\n");
38418c2ecf20Sopenharmony_ci		return ret;
38428c2ecf20Sopenharmony_ci	}
38438c2ecf20Sopenharmony_ci	ret = ni_enable_power_containment(rdev, new_ps, true);
38448c2ecf20Sopenharmony_ci	if (ret) {
38458c2ecf20Sopenharmony_ci		DRM_ERROR("ni_enable_power_containment failed\n");
38468c2ecf20Sopenharmony_ci		return ret;
38478c2ecf20Sopenharmony_ci	}
38488c2ecf20Sopenharmony_ci
38498c2ecf20Sopenharmony_ci	/* update tdp */
38508c2ecf20Sopenharmony_ci	ret = ni_power_control_set_level(rdev);
38518c2ecf20Sopenharmony_ci	if (ret) {
38528c2ecf20Sopenharmony_ci		DRM_ERROR("ni_power_control_set_level failed\n");
38538c2ecf20Sopenharmony_ci		return ret;
38548c2ecf20Sopenharmony_ci	}
38558c2ecf20Sopenharmony_ci
38568c2ecf20Sopenharmony_ci	return 0;
38578c2ecf20Sopenharmony_ci}
38588c2ecf20Sopenharmony_ci
38598c2ecf20Sopenharmony_civoid ni_dpm_post_set_power_state(struct radeon_device *rdev)
38608c2ecf20Sopenharmony_ci{
38618c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
38628c2ecf20Sopenharmony_ci	struct radeon_ps *new_ps = &eg_pi->requested_rps;
38638c2ecf20Sopenharmony_ci
38648c2ecf20Sopenharmony_ci	ni_update_current_ps(rdev, new_ps);
38658c2ecf20Sopenharmony_ci}
38668c2ecf20Sopenharmony_ci
38678c2ecf20Sopenharmony_ci#if 0
38688c2ecf20Sopenharmony_civoid ni_dpm_reset_asic(struct radeon_device *rdev)
38698c2ecf20Sopenharmony_ci{
38708c2ecf20Sopenharmony_ci	ni_restrict_performance_levels_before_switch(rdev);
38718c2ecf20Sopenharmony_ci	rv770_set_boot_state(rdev);
38728c2ecf20Sopenharmony_ci}
38738c2ecf20Sopenharmony_ci#endif
38748c2ecf20Sopenharmony_ci
38758c2ecf20Sopenharmony_ciunion power_info {
38768c2ecf20Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO info;
38778c2ecf20Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V2 info_2;
38788c2ecf20Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V3 info_3;
38798c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
38808c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
38818c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
38828c2ecf20Sopenharmony_ci};
38838c2ecf20Sopenharmony_ci
38848c2ecf20Sopenharmony_ciunion pplib_clock_info {
38858c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
38868c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
38878c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
38888c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
38898c2ecf20Sopenharmony_ci};
38908c2ecf20Sopenharmony_ci
38918c2ecf20Sopenharmony_ciunion pplib_power_state {
38928c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_STATE v1;
38938c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_STATE_V2 v2;
38948c2ecf20Sopenharmony_ci};
38958c2ecf20Sopenharmony_ci
38968c2ecf20Sopenharmony_cistatic void ni_parse_pplib_non_clock_info(struct radeon_device *rdev,
38978c2ecf20Sopenharmony_ci					  struct radeon_ps *rps,
38988c2ecf20Sopenharmony_ci					  struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
38998c2ecf20Sopenharmony_ci					  u8 table_rev)
39008c2ecf20Sopenharmony_ci{
39018c2ecf20Sopenharmony_ci	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
39028c2ecf20Sopenharmony_ci	rps->class = le16_to_cpu(non_clock_info->usClassification);
39038c2ecf20Sopenharmony_ci	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
39048c2ecf20Sopenharmony_ci
39058c2ecf20Sopenharmony_ci	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
39068c2ecf20Sopenharmony_ci		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
39078c2ecf20Sopenharmony_ci		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
39088c2ecf20Sopenharmony_ci	} else if (r600_is_uvd_state(rps->class, rps->class2)) {
39098c2ecf20Sopenharmony_ci		rps->vclk = RV770_DEFAULT_VCLK_FREQ;
39108c2ecf20Sopenharmony_ci		rps->dclk = RV770_DEFAULT_DCLK_FREQ;
39118c2ecf20Sopenharmony_ci	} else {
39128c2ecf20Sopenharmony_ci		rps->vclk = 0;
39138c2ecf20Sopenharmony_ci		rps->dclk = 0;
39148c2ecf20Sopenharmony_ci	}
39158c2ecf20Sopenharmony_ci
39168c2ecf20Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
39178c2ecf20Sopenharmony_ci		rdev->pm.dpm.boot_ps = rps;
39188c2ecf20Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
39198c2ecf20Sopenharmony_ci		rdev->pm.dpm.uvd_ps = rps;
39208c2ecf20Sopenharmony_ci}
39218c2ecf20Sopenharmony_ci
39228c2ecf20Sopenharmony_cistatic void ni_parse_pplib_clock_info(struct radeon_device *rdev,
39238c2ecf20Sopenharmony_ci				      struct radeon_ps *rps, int index,
39248c2ecf20Sopenharmony_ci				      union pplib_clock_info *clock_info)
39258c2ecf20Sopenharmony_ci{
39268c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
39278c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
39288c2ecf20Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
39298c2ecf20Sopenharmony_ci	struct rv7xx_pl *pl = &ps->performance_levels[index];
39308c2ecf20Sopenharmony_ci
39318c2ecf20Sopenharmony_ci	ps->performance_level_count = index + 1;
39328c2ecf20Sopenharmony_ci
39338c2ecf20Sopenharmony_ci	pl->sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
39348c2ecf20Sopenharmony_ci	pl->sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
39358c2ecf20Sopenharmony_ci	pl->mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
39368c2ecf20Sopenharmony_ci	pl->mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci	pl->vddc = le16_to_cpu(clock_info->evergreen.usVDDC);
39398c2ecf20Sopenharmony_ci	pl->vddci = le16_to_cpu(clock_info->evergreen.usVDDCI);
39408c2ecf20Sopenharmony_ci	pl->flags = le32_to_cpu(clock_info->evergreen.ulFlags);
39418c2ecf20Sopenharmony_ci
39428c2ecf20Sopenharmony_ci	/* patch up vddc if necessary */
39438c2ecf20Sopenharmony_ci	if (pl->vddc == 0xff01) {
39448c2ecf20Sopenharmony_ci		if (pi->max_vddc)
39458c2ecf20Sopenharmony_ci			pl->vddc = pi->max_vddc;
39468c2ecf20Sopenharmony_ci	}
39478c2ecf20Sopenharmony_ci
39488c2ecf20Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
39498c2ecf20Sopenharmony_ci		pi->acpi_vddc = pl->vddc;
39508c2ecf20Sopenharmony_ci		eg_pi->acpi_vddci = pl->vddci;
39518c2ecf20Sopenharmony_ci		if (ps->performance_levels[0].flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
39528c2ecf20Sopenharmony_ci			pi->acpi_pcie_gen2 = true;
39538c2ecf20Sopenharmony_ci		else
39548c2ecf20Sopenharmony_ci			pi->acpi_pcie_gen2 = false;
39558c2ecf20Sopenharmony_ci	}
39568c2ecf20Sopenharmony_ci
39578c2ecf20Sopenharmony_ci	if (rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) {
39588c2ecf20Sopenharmony_ci		eg_pi->ulv.supported = true;
39598c2ecf20Sopenharmony_ci		eg_pi->ulv.pl = pl;
39608c2ecf20Sopenharmony_ci	}
39618c2ecf20Sopenharmony_ci
39628c2ecf20Sopenharmony_ci	if (pi->min_vddc_in_table > pl->vddc)
39638c2ecf20Sopenharmony_ci		pi->min_vddc_in_table = pl->vddc;
39648c2ecf20Sopenharmony_ci
39658c2ecf20Sopenharmony_ci	if (pi->max_vddc_in_table < pl->vddc)
39668c2ecf20Sopenharmony_ci		pi->max_vddc_in_table = pl->vddc;
39678c2ecf20Sopenharmony_ci
39688c2ecf20Sopenharmony_ci	/* patch up boot state */
39698c2ecf20Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
39708c2ecf20Sopenharmony_ci		u16 vddc, vddci, mvdd;
39718c2ecf20Sopenharmony_ci		radeon_atombios_get_default_voltages(rdev, &vddc, &vddci, &mvdd);
39728c2ecf20Sopenharmony_ci		pl->mclk = rdev->clock.default_mclk;
39738c2ecf20Sopenharmony_ci		pl->sclk = rdev->clock.default_sclk;
39748c2ecf20Sopenharmony_ci		pl->vddc = vddc;
39758c2ecf20Sopenharmony_ci		pl->vddci = vddci;
39768c2ecf20Sopenharmony_ci	}
39778c2ecf20Sopenharmony_ci
39788c2ecf20Sopenharmony_ci	if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
39798c2ecf20Sopenharmony_ci	    ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
39808c2ecf20Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
39818c2ecf20Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
39828c2ecf20Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
39838c2ecf20Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
39848c2ecf20Sopenharmony_ci	}
39858c2ecf20Sopenharmony_ci}
39868c2ecf20Sopenharmony_ci
39878c2ecf20Sopenharmony_cistatic int ni_parse_power_table(struct radeon_device *rdev)
39888c2ecf20Sopenharmony_ci{
39898c2ecf20Sopenharmony_ci	struct radeon_mode_info *mode_info = &rdev->mode_info;
39908c2ecf20Sopenharmony_ci	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
39918c2ecf20Sopenharmony_ci	union pplib_power_state *power_state;
39928c2ecf20Sopenharmony_ci	int i, j;
39938c2ecf20Sopenharmony_ci	union pplib_clock_info *clock_info;
39948c2ecf20Sopenharmony_ci	union power_info *power_info;
39958c2ecf20Sopenharmony_ci	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
39968c2ecf20Sopenharmony_ci	u16 data_offset;
39978c2ecf20Sopenharmony_ci	u8 frev, crev;
39988c2ecf20Sopenharmony_ci	struct ni_ps *ps;
39998c2ecf20Sopenharmony_ci
40008c2ecf20Sopenharmony_ci	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
40018c2ecf20Sopenharmony_ci				   &frev, &crev, &data_offset))
40028c2ecf20Sopenharmony_ci		return -EINVAL;
40038c2ecf20Sopenharmony_ci	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
40048c2ecf20Sopenharmony_ci
40058c2ecf20Sopenharmony_ci	rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates,
40068c2ecf20Sopenharmony_ci				  sizeof(struct radeon_ps),
40078c2ecf20Sopenharmony_ci				  GFP_KERNEL);
40088c2ecf20Sopenharmony_ci	if (!rdev->pm.dpm.ps)
40098c2ecf20Sopenharmony_ci		return -ENOMEM;
40108c2ecf20Sopenharmony_ci
40118c2ecf20Sopenharmony_ci	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
40128c2ecf20Sopenharmony_ci		power_state = (union pplib_power_state *)
40138c2ecf20Sopenharmony_ci			(mode_info->atom_context->bios + data_offset +
40148c2ecf20Sopenharmony_ci			 le16_to_cpu(power_info->pplib.usStateArrayOffset) +
40158c2ecf20Sopenharmony_ci			 i * power_info->pplib.ucStateEntrySize);
40168c2ecf20Sopenharmony_ci		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
40178c2ecf20Sopenharmony_ci			(mode_info->atom_context->bios + data_offset +
40188c2ecf20Sopenharmony_ci			 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
40198c2ecf20Sopenharmony_ci			 (power_state->v1.ucNonClockStateIndex *
40208c2ecf20Sopenharmony_ci			  power_info->pplib.ucNonClockSize));
40218c2ecf20Sopenharmony_ci		if (power_info->pplib.ucStateEntrySize - 1) {
40228c2ecf20Sopenharmony_ci			u8 *idx;
40238c2ecf20Sopenharmony_ci			ps = kzalloc(sizeof(struct ni_ps), GFP_KERNEL);
40248c2ecf20Sopenharmony_ci			if (ps == NULL) {
40258c2ecf20Sopenharmony_ci				kfree(rdev->pm.dpm.ps);
40268c2ecf20Sopenharmony_ci				return -ENOMEM;
40278c2ecf20Sopenharmony_ci			}
40288c2ecf20Sopenharmony_ci			rdev->pm.dpm.ps[i].ps_priv = ps;
40298c2ecf20Sopenharmony_ci			ni_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
40308c2ecf20Sopenharmony_ci							 non_clock_info,
40318c2ecf20Sopenharmony_ci							 power_info->pplib.ucNonClockSize);
40328c2ecf20Sopenharmony_ci			idx = (u8 *)&power_state->v1.ucClockStateIndices[0];
40338c2ecf20Sopenharmony_ci			for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
40348c2ecf20Sopenharmony_ci				clock_info = (union pplib_clock_info *)
40358c2ecf20Sopenharmony_ci					(mode_info->atom_context->bios + data_offset +
40368c2ecf20Sopenharmony_ci					 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
40378c2ecf20Sopenharmony_ci					 (idx[j] * power_info->pplib.ucClockInfoSize));
40388c2ecf20Sopenharmony_ci				ni_parse_pplib_clock_info(rdev,
40398c2ecf20Sopenharmony_ci							  &rdev->pm.dpm.ps[i], j,
40408c2ecf20Sopenharmony_ci							  clock_info);
40418c2ecf20Sopenharmony_ci			}
40428c2ecf20Sopenharmony_ci		}
40438c2ecf20Sopenharmony_ci	}
40448c2ecf20Sopenharmony_ci	rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates;
40458c2ecf20Sopenharmony_ci	return 0;
40468c2ecf20Sopenharmony_ci}
40478c2ecf20Sopenharmony_ci
40488c2ecf20Sopenharmony_ciint ni_dpm_init(struct radeon_device *rdev)
40498c2ecf20Sopenharmony_ci{
40508c2ecf20Sopenharmony_ci	struct rv7xx_power_info *pi;
40518c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi;
40528c2ecf20Sopenharmony_ci	struct ni_power_info *ni_pi;
40538c2ecf20Sopenharmony_ci	struct atom_clock_dividers dividers;
40548c2ecf20Sopenharmony_ci	int ret;
40558c2ecf20Sopenharmony_ci
40568c2ecf20Sopenharmony_ci	ni_pi = kzalloc(sizeof(struct ni_power_info), GFP_KERNEL);
40578c2ecf20Sopenharmony_ci	if (ni_pi == NULL)
40588c2ecf20Sopenharmony_ci		return -ENOMEM;
40598c2ecf20Sopenharmony_ci	rdev->pm.dpm.priv = ni_pi;
40608c2ecf20Sopenharmony_ci	eg_pi = &ni_pi->eg;
40618c2ecf20Sopenharmony_ci	pi = &eg_pi->rv7xx;
40628c2ecf20Sopenharmony_ci
40638c2ecf20Sopenharmony_ci	rv770_get_max_vddc(rdev);
40648c2ecf20Sopenharmony_ci
40658c2ecf20Sopenharmony_ci	eg_pi->ulv.supported = false;
40668c2ecf20Sopenharmony_ci	pi->acpi_vddc = 0;
40678c2ecf20Sopenharmony_ci	eg_pi->acpi_vddci = 0;
40688c2ecf20Sopenharmony_ci	pi->min_vddc_in_table = 0;
40698c2ecf20Sopenharmony_ci	pi->max_vddc_in_table = 0;
40708c2ecf20Sopenharmony_ci
40718c2ecf20Sopenharmony_ci	ret = r600_get_platform_caps(rdev);
40728c2ecf20Sopenharmony_ci	if (ret)
40738c2ecf20Sopenharmony_ci		return ret;
40748c2ecf20Sopenharmony_ci
40758c2ecf20Sopenharmony_ci	ret = ni_parse_power_table(rdev);
40768c2ecf20Sopenharmony_ci	if (ret)
40778c2ecf20Sopenharmony_ci		return ret;
40788c2ecf20Sopenharmony_ci	ret = r600_parse_extended_power_table(rdev);
40798c2ecf20Sopenharmony_ci	if (ret)
40808c2ecf20Sopenharmony_ci		return ret;
40818c2ecf20Sopenharmony_ci
40828c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
40838c2ecf20Sopenharmony_ci		kcalloc(4,
40848c2ecf20Sopenharmony_ci			sizeof(struct radeon_clock_voltage_dependency_entry),
40858c2ecf20Sopenharmony_ci			GFP_KERNEL);
40868c2ecf20Sopenharmony_ci	if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
40878c2ecf20Sopenharmony_ci		r600_free_extended_power_table(rdev);
40888c2ecf20Sopenharmony_ci		return -ENOMEM;
40898c2ecf20Sopenharmony_ci	}
40908c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
40918c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
40928c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
40938c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;
40948c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720;
40958c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;
40968c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810;
40978c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;
40988c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900;
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_ci	ni_patch_dependency_tables_based_on_leakage(rdev);
41018c2ecf20Sopenharmony_ci
41028c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.voltage_response_time == 0)
41038c2ecf20Sopenharmony_ci		rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
41048c2ecf20Sopenharmony_ci	if (rdev->pm.dpm.backbias_response_time == 0)
41058c2ecf20Sopenharmony_ci		rdev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;
41068c2ecf20Sopenharmony_ci
41078c2ecf20Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
41088c2ecf20Sopenharmony_ci					     0, false, &dividers);
41098c2ecf20Sopenharmony_ci	if (ret)
41108c2ecf20Sopenharmony_ci		pi->ref_div = dividers.ref_div + 1;
41118c2ecf20Sopenharmony_ci	else
41128c2ecf20Sopenharmony_ci		pi->ref_div = R600_REFERENCEDIVIDER_DFLT;
41138c2ecf20Sopenharmony_ci
41148c2ecf20Sopenharmony_ci	pi->rlp = RV770_RLP_DFLT;
41158c2ecf20Sopenharmony_ci	pi->rmp = RV770_RMP_DFLT;
41168c2ecf20Sopenharmony_ci	pi->lhp = RV770_LHP_DFLT;
41178c2ecf20Sopenharmony_ci	pi->lmp = RV770_LMP_DFLT;
41188c2ecf20Sopenharmony_ci
41198c2ecf20Sopenharmony_ci	eg_pi->ats[0].rlp = RV770_RLP_DFLT;
41208c2ecf20Sopenharmony_ci	eg_pi->ats[0].rmp = RV770_RMP_DFLT;
41218c2ecf20Sopenharmony_ci	eg_pi->ats[0].lhp = RV770_LHP_DFLT;
41228c2ecf20Sopenharmony_ci	eg_pi->ats[0].lmp = RV770_LMP_DFLT;
41238c2ecf20Sopenharmony_ci
41248c2ecf20Sopenharmony_ci	eg_pi->ats[1].rlp = BTC_RLP_UVD_DFLT;
41258c2ecf20Sopenharmony_ci	eg_pi->ats[1].rmp = BTC_RMP_UVD_DFLT;
41268c2ecf20Sopenharmony_ci	eg_pi->ats[1].lhp = BTC_LHP_UVD_DFLT;
41278c2ecf20Sopenharmony_ci	eg_pi->ats[1].lmp = BTC_LMP_UVD_DFLT;
41288c2ecf20Sopenharmony_ci
41298c2ecf20Sopenharmony_ci	eg_pi->smu_uvd_hs = true;
41308c2ecf20Sopenharmony_ci
41318c2ecf20Sopenharmony_ci	if (rdev->pdev->device == 0x6707) {
41328c2ecf20Sopenharmony_ci		pi->mclk_strobe_mode_threshold = 55000;
41338c2ecf20Sopenharmony_ci		pi->mclk_edc_enable_threshold = 55000;
41348c2ecf20Sopenharmony_ci		eg_pi->mclk_edc_wr_enable_threshold = 55000;
41358c2ecf20Sopenharmony_ci	} else {
41368c2ecf20Sopenharmony_ci		pi->mclk_strobe_mode_threshold = 40000;
41378c2ecf20Sopenharmony_ci		pi->mclk_edc_enable_threshold = 40000;
41388c2ecf20Sopenharmony_ci		eg_pi->mclk_edc_wr_enable_threshold = 40000;
41398c2ecf20Sopenharmony_ci	}
41408c2ecf20Sopenharmony_ci	ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;
41418c2ecf20Sopenharmony_ci
41428c2ecf20Sopenharmony_ci	pi->voltage_control =
41438c2ecf20Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, 0);
41448c2ecf20Sopenharmony_ci
41458c2ecf20Sopenharmony_ci	pi->mvdd_control =
41468c2ecf20Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0);
41478c2ecf20Sopenharmony_ci
41488c2ecf20Sopenharmony_ci	eg_pi->vddci_control =
41498c2ecf20Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0);
41508c2ecf20Sopenharmony_ci
41518c2ecf20Sopenharmony_ci	rv770_get_engine_memory_ss(rdev);
41528c2ecf20Sopenharmony_ci
41538c2ecf20Sopenharmony_ci	pi->asi = RV770_ASI_DFLT;
41548c2ecf20Sopenharmony_ci	pi->pasi = CYPRESS_HASI_DFLT;
41558c2ecf20Sopenharmony_ci	pi->vrc = CYPRESS_VRC_DFLT;
41568c2ecf20Sopenharmony_ci
41578c2ecf20Sopenharmony_ci	pi->power_gating = false;
41588c2ecf20Sopenharmony_ci
41598c2ecf20Sopenharmony_ci	pi->gfx_clock_gating = true;
41608c2ecf20Sopenharmony_ci
41618c2ecf20Sopenharmony_ci	pi->mg_clock_gating = true;
41628c2ecf20Sopenharmony_ci	pi->mgcgtssm = true;
41638c2ecf20Sopenharmony_ci	eg_pi->ls_clock_gating = false;
41648c2ecf20Sopenharmony_ci	eg_pi->sclk_deep_sleep = false;
41658c2ecf20Sopenharmony_ci
41668c2ecf20Sopenharmony_ci	pi->dynamic_pcie_gen2 = true;
41678c2ecf20Sopenharmony_ci
41688c2ecf20Sopenharmony_ci	if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
41698c2ecf20Sopenharmony_ci		pi->thermal_protection = true;
41708c2ecf20Sopenharmony_ci	else
41718c2ecf20Sopenharmony_ci		pi->thermal_protection = false;
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_ci	pi->display_gap = true;
41748c2ecf20Sopenharmony_ci
41758c2ecf20Sopenharmony_ci	pi->dcodt = true;
41768c2ecf20Sopenharmony_ci
41778c2ecf20Sopenharmony_ci	pi->ulps = true;
41788c2ecf20Sopenharmony_ci
41798c2ecf20Sopenharmony_ci	eg_pi->dynamic_ac_timing = true;
41808c2ecf20Sopenharmony_ci	eg_pi->abm = true;
41818c2ecf20Sopenharmony_ci	eg_pi->mcls = true;
41828c2ecf20Sopenharmony_ci	eg_pi->light_sleep = true;
41838c2ecf20Sopenharmony_ci	eg_pi->memory_transition = true;
41848c2ecf20Sopenharmony_ci#if defined(CONFIG_ACPI)
41858c2ecf20Sopenharmony_ci	eg_pi->pcie_performance_request =
41868c2ecf20Sopenharmony_ci		radeon_acpi_is_pcie_performance_request_supported(rdev);
41878c2ecf20Sopenharmony_ci#else
41888c2ecf20Sopenharmony_ci	eg_pi->pcie_performance_request = false;
41898c2ecf20Sopenharmony_ci#endif
41908c2ecf20Sopenharmony_ci
41918c2ecf20Sopenharmony_ci	eg_pi->dll_default_on = false;
41928c2ecf20Sopenharmony_ci
41938c2ecf20Sopenharmony_ci	eg_pi->sclk_deep_sleep = false;
41948c2ecf20Sopenharmony_ci
41958c2ecf20Sopenharmony_ci	pi->mclk_stutter_mode_threshold = 0;
41968c2ecf20Sopenharmony_ci
41978c2ecf20Sopenharmony_ci	pi->sram_end = SMC_RAM_END;
41988c2ecf20Sopenharmony_ci
41998c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.mclk_sclk_ratio = 3;
42008c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_vddci_delta = 200;
42018c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2 = 900;
42028c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_sclk_values.count = ARRAY_SIZE(btc_valid_sclk);
42038c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_sclk_values.values = btc_valid_sclk;
42048c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
42058c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
42068c2ecf20Sopenharmony_ci	rdev->pm.dpm.dyn_state.sclk_mclk_delta = 12500;
42078c2ecf20Sopenharmony_ci
42088c2ecf20Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.at = 516;
42098c2ecf20Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.bt = 18;
42108c2ecf20Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.av = 51;
42118c2ecf20Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.bv = 2957;
42128c2ecf20Sopenharmony_ci
42138c2ecf20Sopenharmony_ci	switch (rdev->pdev->device) {
42148c2ecf20Sopenharmony_ci	case 0x6700:
42158c2ecf20Sopenharmony_ci	case 0x6701:
42168c2ecf20Sopenharmony_ci	case 0x6702:
42178c2ecf20Sopenharmony_ci	case 0x6703:
42188c2ecf20Sopenharmony_ci	case 0x6718:
42198c2ecf20Sopenharmony_ci		ni_pi->cac_weights = &cac_weights_cayman_xt;
42208c2ecf20Sopenharmony_ci		break;
42218c2ecf20Sopenharmony_ci	case 0x6705:
42228c2ecf20Sopenharmony_ci	case 0x6719:
42238c2ecf20Sopenharmony_ci	case 0x671D:
42248c2ecf20Sopenharmony_ci	case 0x671C:
42258c2ecf20Sopenharmony_ci	default:
42268c2ecf20Sopenharmony_ci		ni_pi->cac_weights = &cac_weights_cayman_pro;
42278c2ecf20Sopenharmony_ci		break;
42288c2ecf20Sopenharmony_ci	case 0x6704:
42298c2ecf20Sopenharmony_ci	case 0x6706:
42308c2ecf20Sopenharmony_ci	case 0x6707:
42318c2ecf20Sopenharmony_ci	case 0x6708:
42328c2ecf20Sopenharmony_ci	case 0x6709:
42338c2ecf20Sopenharmony_ci		ni_pi->cac_weights = &cac_weights_cayman_le;
42348c2ecf20Sopenharmony_ci		break;
42358c2ecf20Sopenharmony_ci	}
42368c2ecf20Sopenharmony_ci
42378c2ecf20Sopenharmony_ci	if (ni_pi->cac_weights->enable_power_containment_by_default) {
42388c2ecf20Sopenharmony_ci		ni_pi->enable_power_containment = true;
42398c2ecf20Sopenharmony_ci		ni_pi->enable_cac = true;
42408c2ecf20Sopenharmony_ci		ni_pi->enable_sq_ramping = true;
42418c2ecf20Sopenharmony_ci	} else {
42428c2ecf20Sopenharmony_ci		ni_pi->enable_power_containment = false;
42438c2ecf20Sopenharmony_ci		ni_pi->enable_cac = false;
42448c2ecf20Sopenharmony_ci		ni_pi->enable_sq_ramping = false;
42458c2ecf20Sopenharmony_ci	}
42468c2ecf20Sopenharmony_ci
42478c2ecf20Sopenharmony_ci	ni_pi->driver_calculate_cac_leakage = false;
42488c2ecf20Sopenharmony_ci	ni_pi->cac_configuration_required = true;
42498c2ecf20Sopenharmony_ci
42508c2ecf20Sopenharmony_ci	if (ni_pi->cac_configuration_required) {
42518c2ecf20Sopenharmony_ci		ni_pi->support_cac_long_term_average = true;
42528c2ecf20Sopenharmony_ci		ni_pi->lta_window_size = ni_pi->cac_weights->l2_lta_window_size;
42538c2ecf20Sopenharmony_ci		ni_pi->lts_truncate = ni_pi->cac_weights->lts_truncate;
42548c2ecf20Sopenharmony_ci	} else {
42558c2ecf20Sopenharmony_ci		ni_pi->support_cac_long_term_average = false;
42568c2ecf20Sopenharmony_ci		ni_pi->lta_window_size = 0;
42578c2ecf20Sopenharmony_ci		ni_pi->lts_truncate = 0;
42588c2ecf20Sopenharmony_ci	}
42598c2ecf20Sopenharmony_ci
42608c2ecf20Sopenharmony_ci	ni_pi->use_power_boost_limit = true;
42618c2ecf20Sopenharmony_ci
42628c2ecf20Sopenharmony_ci	/* make sure dc limits are valid */
42638c2ecf20Sopenharmony_ci	if ((rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) ||
42648c2ecf20Sopenharmony_ci	    (rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0))
42658c2ecf20Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc =
42668c2ecf20Sopenharmony_ci			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
42678c2ecf20Sopenharmony_ci
42688c2ecf20Sopenharmony_ci	return 0;
42698c2ecf20Sopenharmony_ci}
42708c2ecf20Sopenharmony_ci
42718c2ecf20Sopenharmony_civoid ni_dpm_fini(struct radeon_device *rdev)
42728c2ecf20Sopenharmony_ci{
42738c2ecf20Sopenharmony_ci	int i;
42748c2ecf20Sopenharmony_ci
42758c2ecf20Sopenharmony_ci	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
42768c2ecf20Sopenharmony_ci		kfree(rdev->pm.dpm.ps[i].ps_priv);
42778c2ecf20Sopenharmony_ci	}
42788c2ecf20Sopenharmony_ci	kfree(rdev->pm.dpm.ps);
42798c2ecf20Sopenharmony_ci	kfree(rdev->pm.dpm.priv);
42808c2ecf20Sopenharmony_ci	kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);
42818c2ecf20Sopenharmony_ci	r600_free_extended_power_table(rdev);
42828c2ecf20Sopenharmony_ci}
42838c2ecf20Sopenharmony_ci
42848c2ecf20Sopenharmony_civoid ni_dpm_print_power_state(struct radeon_device *rdev,
42858c2ecf20Sopenharmony_ci			      struct radeon_ps *rps)
42868c2ecf20Sopenharmony_ci{
42878c2ecf20Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
42888c2ecf20Sopenharmony_ci	struct rv7xx_pl *pl;
42898c2ecf20Sopenharmony_ci	int i;
42908c2ecf20Sopenharmony_ci
42918c2ecf20Sopenharmony_ci	r600_dpm_print_class_info(rps->class, rps->class2);
42928c2ecf20Sopenharmony_ci	r600_dpm_print_cap_info(rps->caps);
42938c2ecf20Sopenharmony_ci	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
42948c2ecf20Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
42958c2ecf20Sopenharmony_ci		pl = &ps->performance_levels[i];
42968c2ecf20Sopenharmony_ci		if (rdev->family >= CHIP_TAHITI)
42978c2ecf20Sopenharmony_ci			printk("\t\tpower level %d    sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",
42988c2ecf20Sopenharmony_ci			       i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
42998c2ecf20Sopenharmony_ci		else
43008c2ecf20Sopenharmony_ci			printk("\t\tpower level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
43018c2ecf20Sopenharmony_ci			       i, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
43028c2ecf20Sopenharmony_ci	}
43038c2ecf20Sopenharmony_ci	r600_dpm_print_ps_status(rdev, rps);
43048c2ecf20Sopenharmony_ci}
43058c2ecf20Sopenharmony_ci
43068c2ecf20Sopenharmony_civoid ni_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
43078c2ecf20Sopenharmony_ci						    struct seq_file *m)
43088c2ecf20Sopenharmony_ci{
43098c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
43108c2ecf20Sopenharmony_ci	struct radeon_ps *rps = &eg_pi->current_rps;
43118c2ecf20Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
43128c2ecf20Sopenharmony_ci	struct rv7xx_pl *pl;
43138c2ecf20Sopenharmony_ci	u32 current_index =
43148c2ecf20Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
43158c2ecf20Sopenharmony_ci		CURRENT_STATE_INDEX_SHIFT;
43168c2ecf20Sopenharmony_ci
43178c2ecf20Sopenharmony_ci	if (current_index >= ps->performance_level_count) {
43188c2ecf20Sopenharmony_ci		seq_printf(m, "invalid dpm profile %d\n", current_index);
43198c2ecf20Sopenharmony_ci	} else {
43208c2ecf20Sopenharmony_ci		pl = &ps->performance_levels[current_index];
43218c2ecf20Sopenharmony_ci		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
43228c2ecf20Sopenharmony_ci		seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
43238c2ecf20Sopenharmony_ci			   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
43248c2ecf20Sopenharmony_ci	}
43258c2ecf20Sopenharmony_ci}
43268c2ecf20Sopenharmony_ci
43278c2ecf20Sopenharmony_ciu32 ni_dpm_get_current_sclk(struct radeon_device *rdev)
43288c2ecf20Sopenharmony_ci{
43298c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
43308c2ecf20Sopenharmony_ci	struct radeon_ps *rps = &eg_pi->current_rps;
43318c2ecf20Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
43328c2ecf20Sopenharmony_ci	struct rv7xx_pl *pl;
43338c2ecf20Sopenharmony_ci	u32 current_index =
43348c2ecf20Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
43358c2ecf20Sopenharmony_ci		CURRENT_STATE_INDEX_SHIFT;
43368c2ecf20Sopenharmony_ci
43378c2ecf20Sopenharmony_ci	if (current_index >= ps->performance_level_count) {
43388c2ecf20Sopenharmony_ci		return 0;
43398c2ecf20Sopenharmony_ci	} else {
43408c2ecf20Sopenharmony_ci		pl = &ps->performance_levels[current_index];
43418c2ecf20Sopenharmony_ci		return pl->sclk;
43428c2ecf20Sopenharmony_ci	}
43438c2ecf20Sopenharmony_ci}
43448c2ecf20Sopenharmony_ci
43458c2ecf20Sopenharmony_ciu32 ni_dpm_get_current_mclk(struct radeon_device *rdev)
43468c2ecf20Sopenharmony_ci{
43478c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
43488c2ecf20Sopenharmony_ci	struct radeon_ps *rps = &eg_pi->current_rps;
43498c2ecf20Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
43508c2ecf20Sopenharmony_ci	struct rv7xx_pl *pl;
43518c2ecf20Sopenharmony_ci	u32 current_index =
43528c2ecf20Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
43538c2ecf20Sopenharmony_ci		CURRENT_STATE_INDEX_SHIFT;
43548c2ecf20Sopenharmony_ci
43558c2ecf20Sopenharmony_ci	if (current_index >= ps->performance_level_count) {
43568c2ecf20Sopenharmony_ci		return 0;
43578c2ecf20Sopenharmony_ci	} else {
43588c2ecf20Sopenharmony_ci		pl = &ps->performance_levels[current_index];
43598c2ecf20Sopenharmony_ci		return pl->mclk;
43608c2ecf20Sopenharmony_ci	}
43618c2ecf20Sopenharmony_ci}
43628c2ecf20Sopenharmony_ci
43638c2ecf20Sopenharmony_ciu32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low)
43648c2ecf20Sopenharmony_ci{
43658c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
43668c2ecf20Sopenharmony_ci	struct ni_ps *requested_state = ni_get_ps(&eg_pi->requested_rps);
43678c2ecf20Sopenharmony_ci
43688c2ecf20Sopenharmony_ci	if (low)
43698c2ecf20Sopenharmony_ci		return requested_state->performance_levels[0].sclk;
43708c2ecf20Sopenharmony_ci	else
43718c2ecf20Sopenharmony_ci		return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk;
43728c2ecf20Sopenharmony_ci}
43738c2ecf20Sopenharmony_ci
43748c2ecf20Sopenharmony_ciu32 ni_dpm_get_mclk(struct radeon_device *rdev, bool low)
43758c2ecf20Sopenharmony_ci{
43768c2ecf20Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
43778c2ecf20Sopenharmony_ci	struct ni_ps *requested_state = ni_get_ps(&eg_pi->requested_rps);
43788c2ecf20Sopenharmony_ci
43798c2ecf20Sopenharmony_ci	if (low)
43808c2ecf20Sopenharmony_ci		return requested_state->performance_levels[0].mclk;
43818c2ecf20Sopenharmony_ci	else
43828c2ecf20Sopenharmony_ci		return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk;
43838c2ecf20Sopenharmony_ci}
43848c2ecf20Sopenharmony_ci
4385