162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2012 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include <linux/math64.h>
2562306a36Sopenharmony_ci#include <linux/pci.h>
2662306a36Sopenharmony_ci#include <linux/seq_file.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include "atom.h"
2962306a36Sopenharmony_ci#include "evergreen.h"
3062306a36Sopenharmony_ci#include "ni_dpm.h"
3162306a36Sopenharmony_ci#include "nid.h"
3262306a36Sopenharmony_ci#include "r600_dpm.h"
3362306a36Sopenharmony_ci#include "rv770.h"
3462306a36Sopenharmony_ci#include "radeon.h"
3562306a36Sopenharmony_ci#include "radeon_asic.h"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F0           0x0a
3862306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F1           0x0b
3962306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F2           0x0c
4062306a36Sopenharmony_ci#define MC_CG_ARB_FREQ_F3           0x0d
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define SMC_RAM_END 0xC000
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic const struct ni_cac_weights cac_weights_cayman_xt =
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	0x15,
4762306a36Sopenharmony_ci	0x2,
4862306a36Sopenharmony_ci	0x19,
4962306a36Sopenharmony_ci	0x2,
5062306a36Sopenharmony_ci	0x8,
5162306a36Sopenharmony_ci	0x14,
5262306a36Sopenharmony_ci	0x2,
5362306a36Sopenharmony_ci	0x16,
5462306a36Sopenharmony_ci	0xE,
5562306a36Sopenharmony_ci	0x17,
5662306a36Sopenharmony_ci	0x13,
5762306a36Sopenharmony_ci	0x2B,
5862306a36Sopenharmony_ci	0x10,
5962306a36Sopenharmony_ci	0x7,
6062306a36Sopenharmony_ci	0x5,
6162306a36Sopenharmony_ci	0x5,
6262306a36Sopenharmony_ci	0x5,
6362306a36Sopenharmony_ci	0x2,
6462306a36Sopenharmony_ci	0x3,
6562306a36Sopenharmony_ci	0x9,
6662306a36Sopenharmony_ci	0x10,
6762306a36Sopenharmony_ci	0x10,
6862306a36Sopenharmony_ci	0x2B,
6962306a36Sopenharmony_ci	0xA,
7062306a36Sopenharmony_ci	0x9,
7162306a36Sopenharmony_ci	0x4,
7262306a36Sopenharmony_ci	0xD,
7362306a36Sopenharmony_ci	0xD,
7462306a36Sopenharmony_ci	0x3E,
7562306a36Sopenharmony_ci	0x18,
7662306a36Sopenharmony_ci	0x14,
7762306a36Sopenharmony_ci	0,
7862306a36Sopenharmony_ci	0x3,
7962306a36Sopenharmony_ci	0x3,
8062306a36Sopenharmony_ci	0x5,
8162306a36Sopenharmony_ci	0,
8262306a36Sopenharmony_ci	0x2,
8362306a36Sopenharmony_ci	0,
8462306a36Sopenharmony_ci	0,
8562306a36Sopenharmony_ci	0,
8662306a36Sopenharmony_ci	0,
8762306a36Sopenharmony_ci	0,
8862306a36Sopenharmony_ci	0,
8962306a36Sopenharmony_ci	0,
9062306a36Sopenharmony_ci	0,
9162306a36Sopenharmony_ci	0,
9262306a36Sopenharmony_ci	0x1CC,
9362306a36Sopenharmony_ci	0,
9462306a36Sopenharmony_ci	0x164,
9562306a36Sopenharmony_ci	1,
9662306a36Sopenharmony_ci	1,
9762306a36Sopenharmony_ci	1,
9862306a36Sopenharmony_ci	1,
9962306a36Sopenharmony_ci	12,
10062306a36Sopenharmony_ci	12,
10162306a36Sopenharmony_ci	12,
10262306a36Sopenharmony_ci	0x12,
10362306a36Sopenharmony_ci	0x1F,
10462306a36Sopenharmony_ci	132,
10562306a36Sopenharmony_ci	5,
10662306a36Sopenharmony_ci	7,
10762306a36Sopenharmony_ci	0,
10862306a36Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
10962306a36Sopenharmony_ci	{ 0, 0, 0, 0 },
11062306a36Sopenharmony_ci	true
11162306a36Sopenharmony_ci};
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistatic const struct ni_cac_weights cac_weights_cayman_pro =
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci	0x16,
11662306a36Sopenharmony_ci	0x4,
11762306a36Sopenharmony_ci	0x10,
11862306a36Sopenharmony_ci	0x2,
11962306a36Sopenharmony_ci	0xA,
12062306a36Sopenharmony_ci	0x16,
12162306a36Sopenharmony_ci	0x2,
12262306a36Sopenharmony_ci	0x18,
12362306a36Sopenharmony_ci	0x10,
12462306a36Sopenharmony_ci	0x1A,
12562306a36Sopenharmony_ci	0x16,
12662306a36Sopenharmony_ci	0x2D,
12762306a36Sopenharmony_ci	0x12,
12862306a36Sopenharmony_ci	0xA,
12962306a36Sopenharmony_ci	0x6,
13062306a36Sopenharmony_ci	0x6,
13162306a36Sopenharmony_ci	0x6,
13262306a36Sopenharmony_ci	0x2,
13362306a36Sopenharmony_ci	0x4,
13462306a36Sopenharmony_ci	0xB,
13562306a36Sopenharmony_ci	0x11,
13662306a36Sopenharmony_ci	0x11,
13762306a36Sopenharmony_ci	0x2D,
13862306a36Sopenharmony_ci	0xC,
13962306a36Sopenharmony_ci	0xC,
14062306a36Sopenharmony_ci	0x7,
14162306a36Sopenharmony_ci	0x10,
14262306a36Sopenharmony_ci	0x10,
14362306a36Sopenharmony_ci	0x3F,
14462306a36Sopenharmony_ci	0x1A,
14562306a36Sopenharmony_ci	0x16,
14662306a36Sopenharmony_ci	0,
14762306a36Sopenharmony_ci	0x7,
14862306a36Sopenharmony_ci	0x4,
14962306a36Sopenharmony_ci	0x6,
15062306a36Sopenharmony_ci	1,
15162306a36Sopenharmony_ci	0x2,
15262306a36Sopenharmony_ci	0x1,
15362306a36Sopenharmony_ci	0,
15462306a36Sopenharmony_ci	0,
15562306a36Sopenharmony_ci	0,
15662306a36Sopenharmony_ci	0,
15762306a36Sopenharmony_ci	0,
15862306a36Sopenharmony_ci	0,
15962306a36Sopenharmony_ci	0x30,
16062306a36Sopenharmony_ci	0,
16162306a36Sopenharmony_ci	0x1CF,
16262306a36Sopenharmony_ci	0,
16362306a36Sopenharmony_ci	0x166,
16462306a36Sopenharmony_ci	1,
16562306a36Sopenharmony_ci	1,
16662306a36Sopenharmony_ci	1,
16762306a36Sopenharmony_ci	1,
16862306a36Sopenharmony_ci	12,
16962306a36Sopenharmony_ci	12,
17062306a36Sopenharmony_ci	12,
17162306a36Sopenharmony_ci	0x15,
17262306a36Sopenharmony_ci	0x1F,
17362306a36Sopenharmony_ci	132,
17462306a36Sopenharmony_ci	6,
17562306a36Sopenharmony_ci	6,
17662306a36Sopenharmony_ci	0,
17762306a36Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
17862306a36Sopenharmony_ci	{ 0, 0, 0, 0 },
17962306a36Sopenharmony_ci	true
18062306a36Sopenharmony_ci};
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic const struct ni_cac_weights cac_weights_cayman_le =
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	0x7,
18562306a36Sopenharmony_ci	0xE,
18662306a36Sopenharmony_ci	0x1,
18762306a36Sopenharmony_ci	0xA,
18862306a36Sopenharmony_ci	0x1,
18962306a36Sopenharmony_ci	0x3F,
19062306a36Sopenharmony_ci	0x2,
19162306a36Sopenharmony_ci	0x18,
19262306a36Sopenharmony_ci	0x10,
19362306a36Sopenharmony_ci	0x1A,
19462306a36Sopenharmony_ci	0x1,
19562306a36Sopenharmony_ci	0x3F,
19662306a36Sopenharmony_ci	0x1,
19762306a36Sopenharmony_ci	0xE,
19862306a36Sopenharmony_ci	0x6,
19962306a36Sopenharmony_ci	0x6,
20062306a36Sopenharmony_ci	0x6,
20162306a36Sopenharmony_ci	0x2,
20262306a36Sopenharmony_ci	0x4,
20362306a36Sopenharmony_ci	0x9,
20462306a36Sopenharmony_ci	0x1A,
20562306a36Sopenharmony_ci	0x1A,
20662306a36Sopenharmony_ci	0x2C,
20762306a36Sopenharmony_ci	0xA,
20862306a36Sopenharmony_ci	0x11,
20962306a36Sopenharmony_ci	0x8,
21062306a36Sopenharmony_ci	0x19,
21162306a36Sopenharmony_ci	0x19,
21262306a36Sopenharmony_ci	0x1,
21362306a36Sopenharmony_ci	0x1,
21462306a36Sopenharmony_ci	0x1A,
21562306a36Sopenharmony_ci	0,
21662306a36Sopenharmony_ci	0x8,
21762306a36Sopenharmony_ci	0x5,
21862306a36Sopenharmony_ci	0x8,
21962306a36Sopenharmony_ci	0x1,
22062306a36Sopenharmony_ci	0x3,
22162306a36Sopenharmony_ci	0x1,
22262306a36Sopenharmony_ci	0,
22362306a36Sopenharmony_ci	0,
22462306a36Sopenharmony_ci	0,
22562306a36Sopenharmony_ci	0,
22662306a36Sopenharmony_ci	0,
22762306a36Sopenharmony_ci	0,
22862306a36Sopenharmony_ci	0x38,
22962306a36Sopenharmony_ci	0x38,
23062306a36Sopenharmony_ci	0x239,
23162306a36Sopenharmony_ci	0x3,
23262306a36Sopenharmony_ci	0x18A,
23362306a36Sopenharmony_ci	1,
23462306a36Sopenharmony_ci	1,
23562306a36Sopenharmony_ci	1,
23662306a36Sopenharmony_ci	1,
23762306a36Sopenharmony_ci	12,
23862306a36Sopenharmony_ci	12,
23962306a36Sopenharmony_ci	12,
24062306a36Sopenharmony_ci	0x15,
24162306a36Sopenharmony_ci	0x22,
24262306a36Sopenharmony_ci	132,
24362306a36Sopenharmony_ci	6,
24462306a36Sopenharmony_ci	6,
24562306a36Sopenharmony_ci	0,
24662306a36Sopenharmony_ci	{ 0, 0, 0, 0, 0, 0, 0, 0 },
24762306a36Sopenharmony_ci	{ 0, 0, 0, 0 },
24862306a36Sopenharmony_ci	true
24962306a36Sopenharmony_ci};
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci#define NISLANDS_MGCG_SEQUENCE  300
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic const u32 cayman_cgcg_cgls_default[] =
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
25662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
25762306a36Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
25862306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
25962306a36Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
26062306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
26162306a36Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
26262306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
26362306a36Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
26462306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
26562306a36Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
26662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
26762306a36Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
26862306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
26962306a36Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
27062306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
27162306a36Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
27262306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
27362306a36Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
27462306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
27562306a36Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
27662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
27762306a36Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
27862306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
27962306a36Sopenharmony_ci	0x000008f8, 0x00000020, 0xffffffff,
28062306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
28162306a36Sopenharmony_ci	0x000008f8, 0x00000021, 0xffffffff,
28262306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
28362306a36Sopenharmony_ci	0x000008f8, 0x00000022, 0xffffffff,
28462306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
28562306a36Sopenharmony_ci	0x000008f8, 0x00000023, 0xffffffff,
28662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
28762306a36Sopenharmony_ci	0x000008f8, 0x00000024, 0xffffffff,
28862306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
28962306a36Sopenharmony_ci	0x000008f8, 0x00000025, 0xffffffff,
29062306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
29162306a36Sopenharmony_ci	0x000008f8, 0x00000026, 0xffffffff,
29262306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
29362306a36Sopenharmony_ci	0x000008f8, 0x00000027, 0xffffffff,
29462306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
29562306a36Sopenharmony_ci	0x000008f8, 0x00000028, 0xffffffff,
29662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
29762306a36Sopenharmony_ci	0x000008f8, 0x00000029, 0xffffffff,
29862306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
29962306a36Sopenharmony_ci	0x000008f8, 0x0000002a, 0xffffffff,
30062306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
30162306a36Sopenharmony_ci	0x000008f8, 0x0000002b, 0xffffffff,
30262306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff
30362306a36Sopenharmony_ci};
30462306a36Sopenharmony_ci#define CAYMAN_CGCG_CGLS_DEFAULT_LENGTH sizeof(cayman_cgcg_cgls_default) / (3 * sizeof(u32))
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic const u32 cayman_cgcg_cgls_disable[] =
30762306a36Sopenharmony_ci{
30862306a36Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
30962306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
31062306a36Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
31162306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
31262306a36Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
31362306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
31462306a36Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
31562306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
31662306a36Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
31762306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
31862306a36Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
31962306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
32062306a36Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
32162306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
32262306a36Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
32362306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
32462306a36Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
32562306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
32662306a36Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
32762306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
32862306a36Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
32962306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
33062306a36Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
33162306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
33262306a36Sopenharmony_ci	0x000008f8, 0x00000020, 0xffffffff,
33362306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
33462306a36Sopenharmony_ci	0x000008f8, 0x00000021, 0xffffffff,
33562306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
33662306a36Sopenharmony_ci	0x000008f8, 0x00000022, 0xffffffff,
33762306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
33862306a36Sopenharmony_ci	0x000008f8, 0x00000023, 0xffffffff,
33962306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
34062306a36Sopenharmony_ci	0x000008f8, 0x00000024, 0xffffffff,
34162306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
34262306a36Sopenharmony_ci	0x000008f8, 0x00000025, 0xffffffff,
34362306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
34462306a36Sopenharmony_ci	0x000008f8, 0x00000026, 0xffffffff,
34562306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
34662306a36Sopenharmony_ci	0x000008f8, 0x00000027, 0xffffffff,
34762306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
34862306a36Sopenharmony_ci	0x000008f8, 0x00000028, 0xffffffff,
34962306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
35062306a36Sopenharmony_ci	0x000008f8, 0x00000029, 0xffffffff,
35162306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
35262306a36Sopenharmony_ci	0x000008f8, 0x0000002a, 0xffffffff,
35362306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
35462306a36Sopenharmony_ci	0x000008f8, 0x0000002b, 0xffffffff,
35562306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
35662306a36Sopenharmony_ci	0x00000644, 0x000f7902, 0x001f4180,
35762306a36Sopenharmony_ci	0x00000644, 0x000f3802, 0x001f4180
35862306a36Sopenharmony_ci};
35962306a36Sopenharmony_ci#define CAYMAN_CGCG_CGLS_DISABLE_LENGTH sizeof(cayman_cgcg_cgls_disable) / (3 * sizeof(u32))
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_cistatic const u32 cayman_cgcg_cgls_enable[] =
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	0x00000644, 0x000f7882, 0x001f4080,
36462306a36Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
36562306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
36662306a36Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
36762306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
36862306a36Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
36962306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
37062306a36Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
37162306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
37262306a36Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
37362306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
37462306a36Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
37562306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
37662306a36Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
37762306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
37862306a36Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
37962306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
38062306a36Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
38162306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
38262306a36Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
38362306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
38462306a36Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
38562306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
38662306a36Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
38762306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
38862306a36Sopenharmony_ci	0x000008f8, 0x00000020, 0xffffffff,
38962306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
39062306a36Sopenharmony_ci	0x000008f8, 0x00000021, 0xffffffff,
39162306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
39262306a36Sopenharmony_ci	0x000008f8, 0x00000022, 0xffffffff,
39362306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
39462306a36Sopenharmony_ci	0x000008f8, 0x00000023, 0xffffffff,
39562306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
39662306a36Sopenharmony_ci	0x000008f8, 0x00000024, 0xffffffff,
39762306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
39862306a36Sopenharmony_ci	0x000008f8, 0x00000025, 0xffffffff,
39962306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
40062306a36Sopenharmony_ci	0x000008f8, 0x00000026, 0xffffffff,
40162306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
40262306a36Sopenharmony_ci	0x000008f8, 0x00000027, 0xffffffff,
40362306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
40462306a36Sopenharmony_ci	0x000008f8, 0x00000028, 0xffffffff,
40562306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
40662306a36Sopenharmony_ci	0x000008f8, 0x00000029, 0xffffffff,
40762306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
40862306a36Sopenharmony_ci	0x000008f8, 0x0000002a, 0xffffffff,
40962306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
41062306a36Sopenharmony_ci	0x000008f8, 0x0000002b, 0xffffffff,
41162306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff
41262306a36Sopenharmony_ci};
41362306a36Sopenharmony_ci#define CAYMAN_CGCG_CGLS_ENABLE_LENGTH  sizeof(cayman_cgcg_cgls_enable) / (3 * sizeof(u32))
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_cistatic const u32 cayman_mgcg_default[] =
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
41862306a36Sopenharmony_ci	0x00003fc4, 0xc0000000, 0xffffffff,
41962306a36Sopenharmony_ci	0x00005448, 0x00000100, 0xffffffff,
42062306a36Sopenharmony_ci	0x000055e4, 0x00000100, 0xffffffff,
42162306a36Sopenharmony_ci	0x0000160c, 0x00000100, 0xffffffff,
42262306a36Sopenharmony_ci	0x00008984, 0x06000100, 0xffffffff,
42362306a36Sopenharmony_ci	0x0000c164, 0x00000100, 0xffffffff,
42462306a36Sopenharmony_ci	0x00008a18, 0x00000100, 0xffffffff,
42562306a36Sopenharmony_ci	0x0000897c, 0x06000100, 0xffffffff,
42662306a36Sopenharmony_ci	0x00008b28, 0x00000100, 0xffffffff,
42762306a36Sopenharmony_ci	0x00009144, 0x00800200, 0xffffffff,
42862306a36Sopenharmony_ci	0x00009a60, 0x00000100, 0xffffffff,
42962306a36Sopenharmony_ci	0x00009868, 0x00000100, 0xffffffff,
43062306a36Sopenharmony_ci	0x00008d58, 0x00000100, 0xffffffff,
43162306a36Sopenharmony_ci	0x00009510, 0x00000100, 0xffffffff,
43262306a36Sopenharmony_ci	0x0000949c, 0x00000100, 0xffffffff,
43362306a36Sopenharmony_ci	0x00009654, 0x00000100, 0xffffffff,
43462306a36Sopenharmony_ci	0x00009030, 0x00000100, 0xffffffff,
43562306a36Sopenharmony_ci	0x00009034, 0x00000100, 0xffffffff,
43662306a36Sopenharmony_ci	0x00009038, 0x00000100, 0xffffffff,
43762306a36Sopenharmony_ci	0x0000903c, 0x00000100, 0xffffffff,
43862306a36Sopenharmony_ci	0x00009040, 0x00000100, 0xffffffff,
43962306a36Sopenharmony_ci	0x0000a200, 0x00000100, 0xffffffff,
44062306a36Sopenharmony_ci	0x0000a204, 0x00000100, 0xffffffff,
44162306a36Sopenharmony_ci	0x0000a208, 0x00000100, 0xffffffff,
44262306a36Sopenharmony_ci	0x0000a20c, 0x00000100, 0xffffffff,
44362306a36Sopenharmony_ci	0x00009744, 0x00000100, 0xffffffff,
44462306a36Sopenharmony_ci	0x00003f80, 0x00000100, 0xffffffff,
44562306a36Sopenharmony_ci	0x0000a210, 0x00000100, 0xffffffff,
44662306a36Sopenharmony_ci	0x0000a214, 0x00000100, 0xffffffff,
44762306a36Sopenharmony_ci	0x000004d8, 0x00000100, 0xffffffff,
44862306a36Sopenharmony_ci	0x00009664, 0x00000100, 0xffffffff,
44962306a36Sopenharmony_ci	0x00009698, 0x00000100, 0xffffffff,
45062306a36Sopenharmony_ci	0x000004d4, 0x00000200, 0xffffffff,
45162306a36Sopenharmony_ci	0x000004d0, 0x00000000, 0xffffffff,
45262306a36Sopenharmony_ci	0x000030cc, 0x00000104, 0xffffffff,
45362306a36Sopenharmony_ci	0x0000d0c0, 0x00000100, 0xffffffff,
45462306a36Sopenharmony_ci	0x0000d8c0, 0x00000100, 0xffffffff,
45562306a36Sopenharmony_ci	0x0000802c, 0x40000000, 0xffffffff,
45662306a36Sopenharmony_ci	0x00003fc4, 0x40000000, 0xffffffff,
45762306a36Sopenharmony_ci	0x0000915c, 0x00010000, 0xffffffff,
45862306a36Sopenharmony_ci	0x00009160, 0x00030002, 0xffffffff,
45962306a36Sopenharmony_ci	0x00009164, 0x00050004, 0xffffffff,
46062306a36Sopenharmony_ci	0x00009168, 0x00070006, 0xffffffff,
46162306a36Sopenharmony_ci	0x00009178, 0x00070000, 0xffffffff,
46262306a36Sopenharmony_ci	0x0000917c, 0x00030002, 0xffffffff,
46362306a36Sopenharmony_ci	0x00009180, 0x00050004, 0xffffffff,
46462306a36Sopenharmony_ci	0x0000918c, 0x00010006, 0xffffffff,
46562306a36Sopenharmony_ci	0x00009190, 0x00090008, 0xffffffff,
46662306a36Sopenharmony_ci	0x00009194, 0x00070000, 0xffffffff,
46762306a36Sopenharmony_ci	0x00009198, 0x00030002, 0xffffffff,
46862306a36Sopenharmony_ci	0x0000919c, 0x00050004, 0xffffffff,
46962306a36Sopenharmony_ci	0x000091a8, 0x00010006, 0xffffffff,
47062306a36Sopenharmony_ci	0x000091ac, 0x00090008, 0xffffffff,
47162306a36Sopenharmony_ci	0x000091b0, 0x00070000, 0xffffffff,
47262306a36Sopenharmony_ci	0x000091b4, 0x00030002, 0xffffffff,
47362306a36Sopenharmony_ci	0x000091b8, 0x00050004, 0xffffffff,
47462306a36Sopenharmony_ci	0x000091c4, 0x00010006, 0xffffffff,
47562306a36Sopenharmony_ci	0x000091c8, 0x00090008, 0xffffffff,
47662306a36Sopenharmony_ci	0x000091cc, 0x00070000, 0xffffffff,
47762306a36Sopenharmony_ci	0x000091d0, 0x00030002, 0xffffffff,
47862306a36Sopenharmony_ci	0x000091d4, 0x00050004, 0xffffffff,
47962306a36Sopenharmony_ci	0x000091e0, 0x00010006, 0xffffffff,
48062306a36Sopenharmony_ci	0x000091e4, 0x00090008, 0xffffffff,
48162306a36Sopenharmony_ci	0x000091e8, 0x00000000, 0xffffffff,
48262306a36Sopenharmony_ci	0x000091ec, 0x00070000, 0xffffffff,
48362306a36Sopenharmony_ci	0x000091f0, 0x00030002, 0xffffffff,
48462306a36Sopenharmony_ci	0x000091f4, 0x00050004, 0xffffffff,
48562306a36Sopenharmony_ci	0x00009200, 0x00010006, 0xffffffff,
48662306a36Sopenharmony_ci	0x00009204, 0x00090008, 0xffffffff,
48762306a36Sopenharmony_ci	0x00009208, 0x00070000, 0xffffffff,
48862306a36Sopenharmony_ci	0x0000920c, 0x00030002, 0xffffffff,
48962306a36Sopenharmony_ci	0x00009210, 0x00050004, 0xffffffff,
49062306a36Sopenharmony_ci	0x0000921c, 0x00010006, 0xffffffff,
49162306a36Sopenharmony_ci	0x00009220, 0x00090008, 0xffffffff,
49262306a36Sopenharmony_ci	0x00009224, 0x00070000, 0xffffffff,
49362306a36Sopenharmony_ci	0x00009228, 0x00030002, 0xffffffff,
49462306a36Sopenharmony_ci	0x0000922c, 0x00050004, 0xffffffff,
49562306a36Sopenharmony_ci	0x00009238, 0x00010006, 0xffffffff,
49662306a36Sopenharmony_ci	0x0000923c, 0x00090008, 0xffffffff,
49762306a36Sopenharmony_ci	0x00009240, 0x00070000, 0xffffffff,
49862306a36Sopenharmony_ci	0x00009244, 0x00030002, 0xffffffff,
49962306a36Sopenharmony_ci	0x00009248, 0x00050004, 0xffffffff,
50062306a36Sopenharmony_ci	0x00009254, 0x00010006, 0xffffffff,
50162306a36Sopenharmony_ci	0x00009258, 0x00090008, 0xffffffff,
50262306a36Sopenharmony_ci	0x0000925c, 0x00070000, 0xffffffff,
50362306a36Sopenharmony_ci	0x00009260, 0x00030002, 0xffffffff,
50462306a36Sopenharmony_ci	0x00009264, 0x00050004, 0xffffffff,
50562306a36Sopenharmony_ci	0x00009270, 0x00010006, 0xffffffff,
50662306a36Sopenharmony_ci	0x00009274, 0x00090008, 0xffffffff,
50762306a36Sopenharmony_ci	0x00009278, 0x00070000, 0xffffffff,
50862306a36Sopenharmony_ci	0x0000927c, 0x00030002, 0xffffffff,
50962306a36Sopenharmony_ci	0x00009280, 0x00050004, 0xffffffff,
51062306a36Sopenharmony_ci	0x0000928c, 0x00010006, 0xffffffff,
51162306a36Sopenharmony_ci	0x00009290, 0x00090008, 0xffffffff,
51262306a36Sopenharmony_ci	0x000092a8, 0x00070000, 0xffffffff,
51362306a36Sopenharmony_ci	0x000092ac, 0x00030002, 0xffffffff,
51462306a36Sopenharmony_ci	0x000092b0, 0x00050004, 0xffffffff,
51562306a36Sopenharmony_ci	0x000092bc, 0x00010006, 0xffffffff,
51662306a36Sopenharmony_ci	0x000092c0, 0x00090008, 0xffffffff,
51762306a36Sopenharmony_ci	0x000092c4, 0x00070000, 0xffffffff,
51862306a36Sopenharmony_ci	0x000092c8, 0x00030002, 0xffffffff,
51962306a36Sopenharmony_ci	0x000092cc, 0x00050004, 0xffffffff,
52062306a36Sopenharmony_ci	0x000092d8, 0x00010006, 0xffffffff,
52162306a36Sopenharmony_ci	0x000092dc, 0x00090008, 0xffffffff,
52262306a36Sopenharmony_ci	0x00009294, 0x00000000, 0xffffffff,
52362306a36Sopenharmony_ci	0x0000802c, 0x40010000, 0xffffffff,
52462306a36Sopenharmony_ci	0x00003fc4, 0x40010000, 0xffffffff,
52562306a36Sopenharmony_ci	0x0000915c, 0x00010000, 0xffffffff,
52662306a36Sopenharmony_ci	0x00009160, 0x00030002, 0xffffffff,
52762306a36Sopenharmony_ci	0x00009164, 0x00050004, 0xffffffff,
52862306a36Sopenharmony_ci	0x00009168, 0x00070006, 0xffffffff,
52962306a36Sopenharmony_ci	0x00009178, 0x00070000, 0xffffffff,
53062306a36Sopenharmony_ci	0x0000917c, 0x00030002, 0xffffffff,
53162306a36Sopenharmony_ci	0x00009180, 0x00050004, 0xffffffff,
53262306a36Sopenharmony_ci	0x0000918c, 0x00010006, 0xffffffff,
53362306a36Sopenharmony_ci	0x00009190, 0x00090008, 0xffffffff,
53462306a36Sopenharmony_ci	0x00009194, 0x00070000, 0xffffffff,
53562306a36Sopenharmony_ci	0x00009198, 0x00030002, 0xffffffff,
53662306a36Sopenharmony_ci	0x0000919c, 0x00050004, 0xffffffff,
53762306a36Sopenharmony_ci	0x000091a8, 0x00010006, 0xffffffff,
53862306a36Sopenharmony_ci	0x000091ac, 0x00090008, 0xffffffff,
53962306a36Sopenharmony_ci	0x000091b0, 0x00070000, 0xffffffff,
54062306a36Sopenharmony_ci	0x000091b4, 0x00030002, 0xffffffff,
54162306a36Sopenharmony_ci	0x000091b8, 0x00050004, 0xffffffff,
54262306a36Sopenharmony_ci	0x000091c4, 0x00010006, 0xffffffff,
54362306a36Sopenharmony_ci	0x000091c8, 0x00090008, 0xffffffff,
54462306a36Sopenharmony_ci	0x000091cc, 0x00070000, 0xffffffff,
54562306a36Sopenharmony_ci	0x000091d0, 0x00030002, 0xffffffff,
54662306a36Sopenharmony_ci	0x000091d4, 0x00050004, 0xffffffff,
54762306a36Sopenharmony_ci	0x000091e0, 0x00010006, 0xffffffff,
54862306a36Sopenharmony_ci	0x000091e4, 0x00090008, 0xffffffff,
54962306a36Sopenharmony_ci	0x000091e8, 0x00000000, 0xffffffff,
55062306a36Sopenharmony_ci	0x000091ec, 0x00070000, 0xffffffff,
55162306a36Sopenharmony_ci	0x000091f0, 0x00030002, 0xffffffff,
55262306a36Sopenharmony_ci	0x000091f4, 0x00050004, 0xffffffff,
55362306a36Sopenharmony_ci	0x00009200, 0x00010006, 0xffffffff,
55462306a36Sopenharmony_ci	0x00009204, 0x00090008, 0xffffffff,
55562306a36Sopenharmony_ci	0x00009208, 0x00070000, 0xffffffff,
55662306a36Sopenharmony_ci	0x0000920c, 0x00030002, 0xffffffff,
55762306a36Sopenharmony_ci	0x00009210, 0x00050004, 0xffffffff,
55862306a36Sopenharmony_ci	0x0000921c, 0x00010006, 0xffffffff,
55962306a36Sopenharmony_ci	0x00009220, 0x00090008, 0xffffffff,
56062306a36Sopenharmony_ci	0x00009224, 0x00070000, 0xffffffff,
56162306a36Sopenharmony_ci	0x00009228, 0x00030002, 0xffffffff,
56262306a36Sopenharmony_ci	0x0000922c, 0x00050004, 0xffffffff,
56362306a36Sopenharmony_ci	0x00009238, 0x00010006, 0xffffffff,
56462306a36Sopenharmony_ci	0x0000923c, 0x00090008, 0xffffffff,
56562306a36Sopenharmony_ci	0x00009240, 0x00070000, 0xffffffff,
56662306a36Sopenharmony_ci	0x00009244, 0x00030002, 0xffffffff,
56762306a36Sopenharmony_ci	0x00009248, 0x00050004, 0xffffffff,
56862306a36Sopenharmony_ci	0x00009254, 0x00010006, 0xffffffff,
56962306a36Sopenharmony_ci	0x00009258, 0x00090008, 0xffffffff,
57062306a36Sopenharmony_ci	0x0000925c, 0x00070000, 0xffffffff,
57162306a36Sopenharmony_ci	0x00009260, 0x00030002, 0xffffffff,
57262306a36Sopenharmony_ci	0x00009264, 0x00050004, 0xffffffff,
57362306a36Sopenharmony_ci	0x00009270, 0x00010006, 0xffffffff,
57462306a36Sopenharmony_ci	0x00009274, 0x00090008, 0xffffffff,
57562306a36Sopenharmony_ci	0x00009278, 0x00070000, 0xffffffff,
57662306a36Sopenharmony_ci	0x0000927c, 0x00030002, 0xffffffff,
57762306a36Sopenharmony_ci	0x00009280, 0x00050004, 0xffffffff,
57862306a36Sopenharmony_ci	0x0000928c, 0x00010006, 0xffffffff,
57962306a36Sopenharmony_ci	0x00009290, 0x00090008, 0xffffffff,
58062306a36Sopenharmony_ci	0x000092a8, 0x00070000, 0xffffffff,
58162306a36Sopenharmony_ci	0x000092ac, 0x00030002, 0xffffffff,
58262306a36Sopenharmony_ci	0x000092b0, 0x00050004, 0xffffffff,
58362306a36Sopenharmony_ci	0x000092bc, 0x00010006, 0xffffffff,
58462306a36Sopenharmony_ci	0x000092c0, 0x00090008, 0xffffffff,
58562306a36Sopenharmony_ci	0x000092c4, 0x00070000, 0xffffffff,
58662306a36Sopenharmony_ci	0x000092c8, 0x00030002, 0xffffffff,
58762306a36Sopenharmony_ci	0x000092cc, 0x00050004, 0xffffffff,
58862306a36Sopenharmony_ci	0x000092d8, 0x00010006, 0xffffffff,
58962306a36Sopenharmony_ci	0x000092dc, 0x00090008, 0xffffffff,
59062306a36Sopenharmony_ci	0x00009294, 0x00000000, 0xffffffff,
59162306a36Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
59262306a36Sopenharmony_ci	0x00003fc4, 0xc0000000, 0xffffffff,
59362306a36Sopenharmony_ci	0x000008f8, 0x00000010, 0xffffffff,
59462306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
59562306a36Sopenharmony_ci	0x000008f8, 0x00000011, 0xffffffff,
59662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
59762306a36Sopenharmony_ci	0x000008f8, 0x00000012, 0xffffffff,
59862306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
59962306a36Sopenharmony_ci	0x000008f8, 0x00000013, 0xffffffff,
60062306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
60162306a36Sopenharmony_ci	0x000008f8, 0x00000014, 0xffffffff,
60262306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
60362306a36Sopenharmony_ci	0x000008f8, 0x00000015, 0xffffffff,
60462306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
60562306a36Sopenharmony_ci	0x000008f8, 0x00000016, 0xffffffff,
60662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
60762306a36Sopenharmony_ci	0x000008f8, 0x00000017, 0xffffffff,
60862306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
60962306a36Sopenharmony_ci	0x000008f8, 0x00000018, 0xffffffff,
61062306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
61162306a36Sopenharmony_ci	0x000008f8, 0x00000019, 0xffffffff,
61262306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
61362306a36Sopenharmony_ci	0x000008f8, 0x0000001a, 0xffffffff,
61462306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
61562306a36Sopenharmony_ci	0x000008f8, 0x0000001b, 0xffffffff,
61662306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff
61762306a36Sopenharmony_ci};
61862306a36Sopenharmony_ci#define CAYMAN_MGCG_DEFAULT_LENGTH sizeof(cayman_mgcg_default) / (3 * sizeof(u32))
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic const u32 cayman_mgcg_disable[] =
62162306a36Sopenharmony_ci{
62262306a36Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
62362306a36Sopenharmony_ci	0x000008f8, 0x00000000, 0xffffffff,
62462306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
62562306a36Sopenharmony_ci	0x000008f8, 0x00000001, 0xffffffff,
62662306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
62762306a36Sopenharmony_ci	0x000008f8, 0x00000002, 0xffffffff,
62862306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
62962306a36Sopenharmony_ci	0x000008f8, 0x00000003, 0xffffffff,
63062306a36Sopenharmony_ci	0x000008fc, 0xffffffff, 0xffffffff,
63162306a36Sopenharmony_ci	0x00009150, 0x00600000, 0xffffffff
63262306a36Sopenharmony_ci};
63362306a36Sopenharmony_ci#define CAYMAN_MGCG_DISABLE_LENGTH   sizeof(cayman_mgcg_disable) / (3 * sizeof(u32))
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_cistatic const u32 cayman_mgcg_enable[] =
63662306a36Sopenharmony_ci{
63762306a36Sopenharmony_ci	0x0000802c, 0xc0000000, 0xffffffff,
63862306a36Sopenharmony_ci	0x000008f8, 0x00000000, 0xffffffff,
63962306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
64062306a36Sopenharmony_ci	0x000008f8, 0x00000001, 0xffffffff,
64162306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
64262306a36Sopenharmony_ci	0x000008f8, 0x00000002, 0xffffffff,
64362306a36Sopenharmony_ci	0x000008fc, 0x00600000, 0xffffffff,
64462306a36Sopenharmony_ci	0x000008f8, 0x00000003, 0xffffffff,
64562306a36Sopenharmony_ci	0x000008fc, 0x00000000, 0xffffffff,
64662306a36Sopenharmony_ci	0x00009150, 0x96944200, 0xffffffff
64762306a36Sopenharmony_ci};
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci#define CAYMAN_MGCG_ENABLE_LENGTH   sizeof(cayman_mgcg_enable) / (3 * sizeof(u32))
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci#define NISLANDS_SYSLS_SEQUENCE  100
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic const u32 cayman_sysls_default[] =
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	/* Register,   Value,     Mask bits */
65662306a36Sopenharmony_ci	0x000055e8, 0x00000000, 0xffffffff,
65762306a36Sopenharmony_ci	0x0000d0bc, 0x00000000, 0xffffffff,
65862306a36Sopenharmony_ci	0x0000d8bc, 0x00000000, 0xffffffff,
65962306a36Sopenharmony_ci	0x000015c0, 0x000c1401, 0xffffffff,
66062306a36Sopenharmony_ci	0x0000264c, 0x000c0400, 0xffffffff,
66162306a36Sopenharmony_ci	0x00002648, 0x000c0400, 0xffffffff,
66262306a36Sopenharmony_ci	0x00002650, 0x000c0400, 0xffffffff,
66362306a36Sopenharmony_ci	0x000020b8, 0x000c0400, 0xffffffff,
66462306a36Sopenharmony_ci	0x000020bc, 0x000c0400, 0xffffffff,
66562306a36Sopenharmony_ci	0x000020c0, 0x000c0c80, 0xffffffff,
66662306a36Sopenharmony_ci	0x0000f4a0, 0x000000c0, 0xffffffff,
66762306a36Sopenharmony_ci	0x0000f4a4, 0x00680fff, 0xffffffff,
66862306a36Sopenharmony_ci	0x00002f50, 0x00000404, 0xffffffff,
66962306a36Sopenharmony_ci	0x000004c8, 0x00000001, 0xffffffff,
67062306a36Sopenharmony_ci	0x000064ec, 0x00000000, 0xffffffff,
67162306a36Sopenharmony_ci	0x00000c7c, 0x00000000, 0xffffffff,
67262306a36Sopenharmony_ci	0x00008dfc, 0x00000000, 0xffffffff
67362306a36Sopenharmony_ci};
67462306a36Sopenharmony_ci#define CAYMAN_SYSLS_DEFAULT_LENGTH sizeof(cayman_sysls_default) / (3 * sizeof(u32))
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic const u32 cayman_sysls_disable[] =
67762306a36Sopenharmony_ci{
67862306a36Sopenharmony_ci	/* Register,   Value,     Mask bits */
67962306a36Sopenharmony_ci	0x0000d0c0, 0x00000000, 0xffffffff,
68062306a36Sopenharmony_ci	0x0000d8c0, 0x00000000, 0xffffffff,
68162306a36Sopenharmony_ci	0x000055e8, 0x00000000, 0xffffffff,
68262306a36Sopenharmony_ci	0x0000d0bc, 0x00000000, 0xffffffff,
68362306a36Sopenharmony_ci	0x0000d8bc, 0x00000000, 0xffffffff,
68462306a36Sopenharmony_ci	0x000015c0, 0x00041401, 0xffffffff,
68562306a36Sopenharmony_ci	0x0000264c, 0x00040400, 0xffffffff,
68662306a36Sopenharmony_ci	0x00002648, 0x00040400, 0xffffffff,
68762306a36Sopenharmony_ci	0x00002650, 0x00040400, 0xffffffff,
68862306a36Sopenharmony_ci	0x000020b8, 0x00040400, 0xffffffff,
68962306a36Sopenharmony_ci	0x000020bc, 0x00040400, 0xffffffff,
69062306a36Sopenharmony_ci	0x000020c0, 0x00040c80, 0xffffffff,
69162306a36Sopenharmony_ci	0x0000f4a0, 0x000000c0, 0xffffffff,
69262306a36Sopenharmony_ci	0x0000f4a4, 0x00680000, 0xffffffff,
69362306a36Sopenharmony_ci	0x00002f50, 0x00000404, 0xffffffff,
69462306a36Sopenharmony_ci	0x000004c8, 0x00000001, 0xffffffff,
69562306a36Sopenharmony_ci	0x000064ec, 0x00007ffd, 0xffffffff,
69662306a36Sopenharmony_ci	0x00000c7c, 0x0000ff00, 0xffffffff,
69762306a36Sopenharmony_ci	0x00008dfc, 0x0000007f, 0xffffffff
69862306a36Sopenharmony_ci};
69962306a36Sopenharmony_ci#define CAYMAN_SYSLS_DISABLE_LENGTH sizeof(cayman_sysls_disable) / (3 * sizeof(u32))
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_cistatic const u32 cayman_sysls_enable[] =
70262306a36Sopenharmony_ci{
70362306a36Sopenharmony_ci	/* Register,   Value,     Mask bits */
70462306a36Sopenharmony_ci	0x000055e8, 0x00000001, 0xffffffff,
70562306a36Sopenharmony_ci	0x0000d0bc, 0x00000100, 0xffffffff,
70662306a36Sopenharmony_ci	0x0000d8bc, 0x00000100, 0xffffffff,
70762306a36Sopenharmony_ci	0x000015c0, 0x000c1401, 0xffffffff,
70862306a36Sopenharmony_ci	0x0000264c, 0x000c0400, 0xffffffff,
70962306a36Sopenharmony_ci	0x00002648, 0x000c0400, 0xffffffff,
71062306a36Sopenharmony_ci	0x00002650, 0x000c0400, 0xffffffff,
71162306a36Sopenharmony_ci	0x000020b8, 0x000c0400, 0xffffffff,
71262306a36Sopenharmony_ci	0x000020bc, 0x000c0400, 0xffffffff,
71362306a36Sopenharmony_ci	0x000020c0, 0x000c0c80, 0xffffffff,
71462306a36Sopenharmony_ci	0x0000f4a0, 0x000000c0, 0xffffffff,
71562306a36Sopenharmony_ci	0x0000f4a4, 0x00680fff, 0xffffffff,
71662306a36Sopenharmony_ci	0x00002f50, 0x00000903, 0xffffffff,
71762306a36Sopenharmony_ci	0x000004c8, 0x00000000, 0xffffffff,
71862306a36Sopenharmony_ci	0x000064ec, 0x00000000, 0xffffffff,
71962306a36Sopenharmony_ci	0x00000c7c, 0x00000000, 0xffffffff,
72062306a36Sopenharmony_ci	0x00008dfc, 0x00000000, 0xffffffff
72162306a36Sopenharmony_ci};
72262306a36Sopenharmony_ci#define CAYMAN_SYSLS_ENABLE_LENGTH sizeof(cayman_sysls_enable) / (3 * sizeof(u32))
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ciextern int ni_mc_load_microcode(struct radeon_device *rdev);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_cistruct ni_power_info *ni_get_pi(struct radeon_device *rdev)
72762306a36Sopenharmony_ci{
72862306a36Sopenharmony_ci	struct ni_power_info *pi = rdev->pm.dpm.priv;
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	return pi;
73162306a36Sopenharmony_ci}
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_cistruct ni_ps *ni_get_ps(struct radeon_ps *rps)
73462306a36Sopenharmony_ci{
73562306a36Sopenharmony_ci	struct ni_ps *ps = rps->ps_priv;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	return ps;
73862306a36Sopenharmony_ci}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_cistatic void ni_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff,
74162306a36Sopenharmony_ci						     u16 v, s32 t,
74262306a36Sopenharmony_ci						     u32 ileakage,
74362306a36Sopenharmony_ci						     u32 *leakage)
74462306a36Sopenharmony_ci{
74562306a36Sopenharmony_ci	s64 kt, kv, leakage_w, i_leakage, vddc, temperature;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	i_leakage = div64_s64(drm_int2fixp(ileakage), 1000);
74862306a36Sopenharmony_ci	vddc = div64_s64(drm_int2fixp(v), 1000);
74962306a36Sopenharmony_ci	temperature = div64_s64(drm_int2fixp(t), 1000);
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	kt = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->at), 1000),
75262306a36Sopenharmony_ci			  drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bt), 1000), temperature)));
75362306a36Sopenharmony_ci	kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 1000),
75462306a36Sopenharmony_ci			  drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 1000), vddc)));
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc);
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	*leakage = drm_fixp2int(leakage_w * 1000);
75962306a36Sopenharmony_ci}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_cistatic void ni_calculate_leakage_for_v_and_t(struct radeon_device *rdev,
76262306a36Sopenharmony_ci					     const struct ni_leakage_coeffients *coeff,
76362306a36Sopenharmony_ci					     u16 v,
76462306a36Sopenharmony_ci					     s32 t,
76562306a36Sopenharmony_ci					     u32 i_leakage,
76662306a36Sopenharmony_ci					     u32 *leakage)
76762306a36Sopenharmony_ci{
76862306a36Sopenharmony_ci	ni_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage);
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cibool ni_dpm_vblank_too_short(struct radeon_device *rdev)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
77462306a36Sopenharmony_ci	u32 vblank_time = r600_dpm_get_vblank_time(rdev);
77562306a36Sopenharmony_ci	/* we never hit the non-gddr5 limit so disable it */
77662306a36Sopenharmony_ci	u32 switch_limit = pi->mem_gddr5 ? 450 : 0;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	if (vblank_time < switch_limit)
77962306a36Sopenharmony_ci		return true;
78062306a36Sopenharmony_ci	else
78162306a36Sopenharmony_ci		return false;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistatic void ni_apply_state_adjust_rules(struct radeon_device *rdev,
78662306a36Sopenharmony_ci					struct radeon_ps *rps)
78762306a36Sopenharmony_ci{
78862306a36Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
78962306a36Sopenharmony_ci	struct radeon_clock_and_voltage_limits *max_limits;
79062306a36Sopenharmony_ci	bool disable_mclk_switching;
79162306a36Sopenharmony_ci	u32 mclk;
79262306a36Sopenharmony_ci	u16 vddci;
79362306a36Sopenharmony_ci	int i;
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
79662306a36Sopenharmony_ci	    ni_dpm_vblank_too_short(rdev))
79762306a36Sopenharmony_ci		disable_mclk_switching = true;
79862306a36Sopenharmony_ci	else
79962306a36Sopenharmony_ci		disable_mclk_switching = false;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	if (rdev->pm.dpm.ac_power)
80262306a36Sopenharmony_ci		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
80362306a36Sopenharmony_ci	else
80462306a36Sopenharmony_ci		max_limits = &rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	if (rdev->pm.dpm.ac_power == false) {
80762306a36Sopenharmony_ci		for (i = 0; i < ps->performance_level_count; i++) {
80862306a36Sopenharmony_ci			if (ps->performance_levels[i].mclk > max_limits->mclk)
80962306a36Sopenharmony_ci				ps->performance_levels[i].mclk = max_limits->mclk;
81062306a36Sopenharmony_ci			if (ps->performance_levels[i].sclk > max_limits->sclk)
81162306a36Sopenharmony_ci				ps->performance_levels[i].sclk = max_limits->sclk;
81262306a36Sopenharmony_ci			if (ps->performance_levels[i].vddc > max_limits->vddc)
81362306a36Sopenharmony_ci				ps->performance_levels[i].vddc = max_limits->vddc;
81462306a36Sopenharmony_ci			if (ps->performance_levels[i].vddci > max_limits->vddci)
81562306a36Sopenharmony_ci				ps->performance_levels[i].vddci = max_limits->vddci;
81662306a36Sopenharmony_ci		}
81762306a36Sopenharmony_ci	}
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	/* XXX validate the min clocks required for display */
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci	/* adjust low state */
82262306a36Sopenharmony_ci	if (disable_mclk_switching) {
82362306a36Sopenharmony_ci		ps->performance_levels[0].mclk =
82462306a36Sopenharmony_ci			ps->performance_levels[ps->performance_level_count - 1].mclk;
82562306a36Sopenharmony_ci		ps->performance_levels[0].vddci =
82662306a36Sopenharmony_ci			ps->performance_levels[ps->performance_level_count - 1].vddci;
82762306a36Sopenharmony_ci	}
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
83062306a36Sopenharmony_ci				  &ps->performance_levels[0].sclk,
83162306a36Sopenharmony_ci				  &ps->performance_levels[0].mclk);
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	for (i = 1; i < ps->performance_level_count; i++) {
83462306a36Sopenharmony_ci		if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk)
83562306a36Sopenharmony_ci			ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk;
83662306a36Sopenharmony_ci		if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc)
83762306a36Sopenharmony_ci			ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc;
83862306a36Sopenharmony_ci	}
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	/* adjust remaining states */
84162306a36Sopenharmony_ci	if (disable_mclk_switching) {
84262306a36Sopenharmony_ci		mclk = ps->performance_levels[0].mclk;
84362306a36Sopenharmony_ci		vddci = ps->performance_levels[0].vddci;
84462306a36Sopenharmony_ci		for (i = 1; i < ps->performance_level_count; i++) {
84562306a36Sopenharmony_ci			if (mclk < ps->performance_levels[i].mclk)
84662306a36Sopenharmony_ci				mclk = ps->performance_levels[i].mclk;
84762306a36Sopenharmony_ci			if (vddci < ps->performance_levels[i].vddci)
84862306a36Sopenharmony_ci				vddci = ps->performance_levels[i].vddci;
84962306a36Sopenharmony_ci		}
85062306a36Sopenharmony_ci		for (i = 0; i < ps->performance_level_count; i++) {
85162306a36Sopenharmony_ci			ps->performance_levels[i].mclk = mclk;
85262306a36Sopenharmony_ci			ps->performance_levels[i].vddci = vddci;
85362306a36Sopenharmony_ci		}
85462306a36Sopenharmony_ci	} else {
85562306a36Sopenharmony_ci		for (i = 1; i < ps->performance_level_count; i++) {
85662306a36Sopenharmony_ci			if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk)
85762306a36Sopenharmony_ci				ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk;
85862306a36Sopenharmony_ci			if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci)
85962306a36Sopenharmony_ci				ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci;
86062306a36Sopenharmony_ci		}
86162306a36Sopenharmony_ci	}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	for (i = 1; i < ps->performance_level_count; i++)
86462306a36Sopenharmony_ci		btc_skip_blacklist_clocks(rdev, max_limits->sclk, max_limits->mclk,
86562306a36Sopenharmony_ci					  &ps->performance_levels[i].sclk,
86662306a36Sopenharmony_ci					  &ps->performance_levels[i].mclk);
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++)
86962306a36Sopenharmony_ci		btc_adjust_clock_combinations(rdev, max_limits,
87062306a36Sopenharmony_ci					      &ps->performance_levels[i]);
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
87362306a36Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk,
87462306a36Sopenharmony_ci						   ps->performance_levels[i].sclk,
87562306a36Sopenharmony_ci						   max_limits->vddc,  &ps->performance_levels[i].vddc);
87662306a36Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddci_dependency_on_mclk,
87762306a36Sopenharmony_ci						   ps->performance_levels[i].mclk,
87862306a36Sopenharmony_ci						   max_limits->vddci, &ps->performance_levels[i].vddci);
87962306a36Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk,
88062306a36Sopenharmony_ci						   ps->performance_levels[i].mclk,
88162306a36Sopenharmony_ci						   max_limits->vddc,  &ps->performance_levels[i].vddc);
88262306a36Sopenharmony_ci		btc_apply_voltage_dependency_rules(&rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk,
88362306a36Sopenharmony_ci						   rdev->clock.current_dispclk,
88462306a36Sopenharmony_ci						   max_limits->vddc,  &ps->performance_levels[i].vddc);
88562306a36Sopenharmony_ci	}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
88862306a36Sopenharmony_ci		btc_apply_voltage_delta_rules(rdev,
88962306a36Sopenharmony_ci					      max_limits->vddc, max_limits->vddci,
89062306a36Sopenharmony_ci					      &ps->performance_levels[i].vddc,
89162306a36Sopenharmony_ci					      &ps->performance_levels[i].vddci);
89262306a36Sopenharmony_ci	}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	ps->dc_compatible = true;
89562306a36Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
89662306a36Sopenharmony_ci		if (ps->performance_levels[i].vddc > rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc)
89762306a36Sopenharmony_ci			ps->dc_compatible = false;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci		if (ps->performance_levels[i].vddc < rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2)
90062306a36Sopenharmony_ci			ps->performance_levels[i].flags &= ~ATOM_PPLIB_R600_FLAGS_PCIEGEN2;
90162306a36Sopenharmony_ci	}
90262306a36Sopenharmony_ci}
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_cistatic void ni_cg_clockgating_default(struct radeon_device *rdev)
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci	u32 count;
90762306a36Sopenharmony_ci	const u32 *ps = NULL;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	ps = (const u32 *)&cayman_cgcg_cgls_default;
91062306a36Sopenharmony_ci	count = CAYMAN_CGCG_CGLS_DEFAULT_LENGTH;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
91362306a36Sopenharmony_ci}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_cistatic void ni_gfx_clockgating_enable(struct radeon_device *rdev,
91662306a36Sopenharmony_ci				      bool enable)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	u32 count;
91962306a36Sopenharmony_ci	const u32 *ps = NULL;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	if (enable) {
92262306a36Sopenharmony_ci		ps = (const u32 *)&cayman_cgcg_cgls_enable;
92362306a36Sopenharmony_ci		count = CAYMAN_CGCG_CGLS_ENABLE_LENGTH;
92462306a36Sopenharmony_ci	} else {
92562306a36Sopenharmony_ci		ps = (const u32 *)&cayman_cgcg_cgls_disable;
92662306a36Sopenharmony_ci		count = CAYMAN_CGCG_CGLS_DISABLE_LENGTH;
92762306a36Sopenharmony_ci	}
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
93062306a36Sopenharmony_ci}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_cistatic void ni_mg_clockgating_default(struct radeon_device *rdev)
93362306a36Sopenharmony_ci{
93462306a36Sopenharmony_ci	u32 count;
93562306a36Sopenharmony_ci	const u32 *ps = NULL;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	ps = (const u32 *)&cayman_mgcg_default;
93862306a36Sopenharmony_ci	count = CAYMAN_MGCG_DEFAULT_LENGTH;
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic void ni_mg_clockgating_enable(struct radeon_device *rdev,
94462306a36Sopenharmony_ci				     bool enable)
94562306a36Sopenharmony_ci{
94662306a36Sopenharmony_ci	u32 count;
94762306a36Sopenharmony_ci	const u32 *ps = NULL;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	if (enable) {
95062306a36Sopenharmony_ci		ps = (const u32 *)&cayman_mgcg_enable;
95162306a36Sopenharmony_ci		count = CAYMAN_MGCG_ENABLE_LENGTH;
95262306a36Sopenharmony_ci	} else {
95362306a36Sopenharmony_ci		ps = (const u32 *)&cayman_mgcg_disable;
95462306a36Sopenharmony_ci		count = CAYMAN_MGCG_DISABLE_LENGTH;
95562306a36Sopenharmony_ci	}
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
95862306a36Sopenharmony_ci}
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_cistatic void ni_ls_clockgating_default(struct radeon_device *rdev)
96162306a36Sopenharmony_ci{
96262306a36Sopenharmony_ci	u32 count;
96362306a36Sopenharmony_ci	const u32 *ps = NULL;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	ps = (const u32 *)&cayman_sysls_default;
96662306a36Sopenharmony_ci	count = CAYMAN_SYSLS_DEFAULT_LENGTH;
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
96962306a36Sopenharmony_ci}
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_cistatic void ni_ls_clockgating_enable(struct radeon_device *rdev,
97262306a36Sopenharmony_ci				     bool enable)
97362306a36Sopenharmony_ci{
97462306a36Sopenharmony_ci	u32 count;
97562306a36Sopenharmony_ci	const u32 *ps = NULL;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	if (enable) {
97862306a36Sopenharmony_ci		ps = (const u32 *)&cayman_sysls_enable;
97962306a36Sopenharmony_ci		count = CAYMAN_SYSLS_ENABLE_LENGTH;
98062306a36Sopenharmony_ci	} else {
98162306a36Sopenharmony_ci		ps = (const u32 *)&cayman_sysls_disable;
98262306a36Sopenharmony_ci		count = CAYMAN_SYSLS_DISABLE_LENGTH;
98362306a36Sopenharmony_ci	}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	btc_program_mgcg_hw_sequence(rdev, ps, count);
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci}
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_cistatic int ni_patch_single_dependency_table_based_on_leakage(struct radeon_device *rdev,
99062306a36Sopenharmony_ci							     struct radeon_clock_voltage_dependency_table *table)
99162306a36Sopenharmony_ci{
99262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
99362306a36Sopenharmony_ci	u32 i;
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	if (table) {
99662306a36Sopenharmony_ci		for (i = 0; i < table->count; i++) {
99762306a36Sopenharmony_ci			if (0xff01 == table->entries[i].v) {
99862306a36Sopenharmony_ci				if (pi->max_vddc == 0)
99962306a36Sopenharmony_ci					return -EINVAL;
100062306a36Sopenharmony_ci				table->entries[i].v = pi->max_vddc;
100162306a36Sopenharmony_ci			}
100262306a36Sopenharmony_ci		}
100362306a36Sopenharmony_ci	}
100462306a36Sopenharmony_ci	return 0;
100562306a36Sopenharmony_ci}
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_cistatic int ni_patch_dependency_tables_based_on_leakage(struct radeon_device *rdev)
100862306a36Sopenharmony_ci{
100962306a36Sopenharmony_ci	int ret = 0;
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	ret = ni_patch_single_dependency_table_based_on_leakage(rdev,
101262306a36Sopenharmony_ci								&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk);
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	ret = ni_patch_single_dependency_table_based_on_leakage(rdev,
101562306a36Sopenharmony_ci								&rdev->pm.dpm.dyn_state.vddc_dependency_on_mclk);
101662306a36Sopenharmony_ci	return ret;
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_cistatic void ni_stop_dpm(struct radeon_device *rdev)
102062306a36Sopenharmony_ci{
102162306a36Sopenharmony_ci	WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
102262306a36Sopenharmony_ci}
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci#if 0
102562306a36Sopenharmony_cistatic int ni_notify_hw_of_power_source(struct radeon_device *rdev,
102662306a36Sopenharmony_ci					bool ac_power)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	if (ac_power)
102962306a36Sopenharmony_ci		return (rv770_send_msg_to_smc(rdev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ?
103062306a36Sopenharmony_ci			0 : -EINVAL;
103162306a36Sopenharmony_ci
103262306a36Sopenharmony_ci	return 0;
103362306a36Sopenharmony_ci}
103462306a36Sopenharmony_ci#endif
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_cistatic PPSMC_Result ni_send_msg_to_smc_with_parameter(struct radeon_device *rdev,
103762306a36Sopenharmony_ci						      PPSMC_Msg msg, u32 parameter)
103862306a36Sopenharmony_ci{
103962306a36Sopenharmony_ci	WREG32(SMC_SCRATCH0, parameter);
104062306a36Sopenharmony_ci	return rv770_send_msg_to_smc(rdev, msg);
104162306a36Sopenharmony_ci}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_cistatic int ni_restrict_performance_levels_before_switch(struct radeon_device *rdev)
104462306a36Sopenharmony_ci{
104562306a36Sopenharmony_ci	if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
104662306a36Sopenharmony_ci		return -EINVAL;
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	return (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ?
104962306a36Sopenharmony_ci		0 : -EINVAL;
105062306a36Sopenharmony_ci}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ciint ni_dpm_force_performance_level(struct radeon_device *rdev,
105362306a36Sopenharmony_ci				   enum radeon_dpm_forced_level level)
105462306a36Sopenharmony_ci{
105562306a36Sopenharmony_ci	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
105662306a36Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
105762306a36Sopenharmony_ci			return -EINVAL;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK)
106062306a36Sopenharmony_ci			return -EINVAL;
106162306a36Sopenharmony_ci	} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
106262306a36Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
106362306a36Sopenharmony_ci			return -EINVAL;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK)
106662306a36Sopenharmony_ci			return -EINVAL;
106762306a36Sopenharmony_ci	} else if (level == RADEON_DPM_FORCED_LEVEL_AUTO) {
106862306a36Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK)
106962306a36Sopenharmony_ci			return -EINVAL;
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci		if (ni_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_SetEnabledLevels, 0) != PPSMC_Result_OK)
107262306a36Sopenharmony_ci			return -EINVAL;
107362306a36Sopenharmony_ci	}
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	rdev->pm.dpm.forced_level = level;
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	return 0;
107862306a36Sopenharmony_ci}
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_cistatic void ni_stop_smc(struct radeon_device *rdev)
108162306a36Sopenharmony_ci{
108262306a36Sopenharmony_ci	u32 tmp;
108362306a36Sopenharmony_ci	int i;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	for (i = 0; i < rdev->usec_timeout; i++) {
108662306a36Sopenharmony_ci		tmp = RREG32(LB_SYNC_RESET_SEL) & LB_SYNC_RESET_SEL_MASK;
108762306a36Sopenharmony_ci		if (tmp != 1)
108862306a36Sopenharmony_ci			break;
108962306a36Sopenharmony_ci		udelay(1);
109062306a36Sopenharmony_ci	}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	udelay(100);
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	r7xx_stop_smc(rdev);
109562306a36Sopenharmony_ci}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_cistatic int ni_process_firmware_header(struct radeon_device *rdev)
109862306a36Sopenharmony_ci{
109962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
110062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
110162306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
110262306a36Sopenharmony_ci	u32 tmp;
110362306a36Sopenharmony_ci	int ret;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
110662306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
110762306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_stateTable,
110862306a36Sopenharmony_ci					&tmp, pi->sram_end);
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	if (ret)
111162306a36Sopenharmony_ci		return ret;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	pi->state_table_start = (u16)tmp;
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
111662306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
111762306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_softRegisters,
111862306a36Sopenharmony_ci					&tmp, pi->sram_end);
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	if (ret)
112162306a36Sopenharmony_ci		return ret;
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	pi->soft_regs_start = (u16)tmp;
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
112662306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
112762306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable,
112862306a36Sopenharmony_ci					&tmp, pi->sram_end);
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	if (ret)
113162306a36Sopenharmony_ci		return ret;
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci	eg_pi->mc_reg_table_start = (u16)tmp;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
113662306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
113762306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_fanTable,
113862306a36Sopenharmony_ci					&tmp, pi->sram_end);
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	if (ret)
114162306a36Sopenharmony_ci		return ret;
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	ni_pi->fan_table_start = (u16)tmp;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
114662306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
114762306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable,
114862306a36Sopenharmony_ci					&tmp, pi->sram_end);
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	if (ret)
115162306a36Sopenharmony_ci		return ret;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	ni_pi->arb_table_start = (u16)tmp;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
115662306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
115762306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_cacTable,
115862306a36Sopenharmony_ci					&tmp, pi->sram_end);
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	if (ret)
116162306a36Sopenharmony_ci		return ret;
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	ni_pi->cac_table_start = (u16)tmp;
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev,
116662306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_LOCATION +
116762306a36Sopenharmony_ci					NISLANDS_SMC_FIRMWARE_HEADER_spllTable,
116862306a36Sopenharmony_ci					&tmp, pi->sram_end);
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	if (ret)
117162306a36Sopenharmony_ci		return ret;
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	ni_pi->spll_table_start = (u16)tmp;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	return ret;
117762306a36Sopenharmony_ci}
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_cistatic void ni_read_clock_registers(struct radeon_device *rdev)
118062306a36Sopenharmony_ci{
118162306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL);
118462306a36Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2);
118562306a36Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3);
118662306a36Sopenharmony_ci	ni_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4);
118762306a36Sopenharmony_ci	ni_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM);
118862306a36Sopenharmony_ci	ni_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
118962306a36Sopenharmony_ci	ni_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL);
119062306a36Sopenharmony_ci	ni_pi->clock_registers.mpll_ad_func_cntl_2 = RREG32(MPLL_AD_FUNC_CNTL_2);
119162306a36Sopenharmony_ci	ni_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL);
119262306a36Sopenharmony_ci	ni_pi->clock_registers.mpll_dq_func_cntl_2 = RREG32(MPLL_DQ_FUNC_CNTL_2);
119362306a36Sopenharmony_ci	ni_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL);
119462306a36Sopenharmony_ci	ni_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL);
119562306a36Sopenharmony_ci	ni_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1);
119662306a36Sopenharmony_ci	ni_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2);
119762306a36Sopenharmony_ci}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci#if 0
120062306a36Sopenharmony_cistatic int ni_enter_ulp_state(struct radeon_device *rdev)
120162306a36Sopenharmony_ci{
120262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (pi->gfx_clock_gating) {
120562306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
120662306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
120762306a36Sopenharmony_ci		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
120862306a36Sopenharmony_ci		RREG32(GB_ADDR_CONFIG);
120962306a36Sopenharmony_ci	}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_SwitchToMinimumPower),
121262306a36Sopenharmony_ci		 ~HOST_SMC_MSG_MASK);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	udelay(25000);
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	return 0;
121762306a36Sopenharmony_ci}
121862306a36Sopenharmony_ci#endif
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_cistatic void ni_program_response_times(struct radeon_device *rdev)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	u32 voltage_response_time, backbias_response_time, acpi_delay_time, vbi_time_out;
122362306a36Sopenharmony_ci	u32 vddc_dly, bb_dly, acpi_dly, vbi_dly, mclk_switch_limit;
122462306a36Sopenharmony_ci	u32 reference_clock;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mvdd_chg_time, 1);
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci	voltage_response_time = (u32)rdev->pm.dpm.voltage_response_time;
122962306a36Sopenharmony_ci	backbias_response_time = (u32)rdev->pm.dpm.backbias_response_time;
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	if (voltage_response_time == 0)
123262306a36Sopenharmony_ci		voltage_response_time = 1000;
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	if (backbias_response_time == 0)
123562306a36Sopenharmony_ci		backbias_response_time = 1000;
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	acpi_delay_time = 15000;
123862306a36Sopenharmony_ci	vbi_time_out = 100000;
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	reference_clock = radeon_get_xclk(rdev);
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	vddc_dly = (voltage_response_time  * reference_clock) / 1600;
124362306a36Sopenharmony_ci	bb_dly   = (backbias_response_time * reference_clock) / 1600;
124462306a36Sopenharmony_ci	acpi_dly = (acpi_delay_time * reference_clock) / 1600;
124562306a36Sopenharmony_ci	vbi_dly  = (vbi_time_out * reference_clock) / 1600;
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	mclk_switch_limit = (460 * reference_clock) / 100;
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_vreg,  vddc_dly);
125062306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_bbias, bb_dly);
125162306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_delay_acpi,  acpi_dly);
125262306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);
125362306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA);
125462306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_mclk_switch_lim, mclk_switch_limit);
125562306a36Sopenharmony_ci}
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_cistatic void ni_populate_smc_voltage_table(struct radeon_device *rdev,
125862306a36Sopenharmony_ci					  struct atom_voltage_table *voltage_table,
125962306a36Sopenharmony_ci					  NISLANDS_SMC_STATETABLE *table)
126062306a36Sopenharmony_ci{
126162306a36Sopenharmony_ci	unsigned int i;
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	for (i = 0; i < voltage_table->count; i++) {
126462306a36Sopenharmony_ci		table->highSMIO[i] = 0;
126562306a36Sopenharmony_ci		table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low);
126662306a36Sopenharmony_ci	}
126762306a36Sopenharmony_ci}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_cistatic void ni_populate_smc_voltage_tables(struct radeon_device *rdev,
127062306a36Sopenharmony_ci					   NISLANDS_SMC_STATETABLE *table)
127162306a36Sopenharmony_ci{
127262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
127362306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
127462306a36Sopenharmony_ci	unsigned char i;
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	if (eg_pi->vddc_voltage_table.count) {
127762306a36Sopenharmony_ci		ni_populate_smc_voltage_table(rdev, &eg_pi->vddc_voltage_table, table);
127862306a36Sopenharmony_ci		table->voltageMaskTable.highMask[NISLANDS_SMC_VOLTAGEMASK_VDDC] = 0;
127962306a36Sopenharmony_ci		table->voltageMaskTable.lowMask[NISLANDS_SMC_VOLTAGEMASK_VDDC] =
128062306a36Sopenharmony_ci			cpu_to_be32(eg_pi->vddc_voltage_table.mask_low);
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci		for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) {
128362306a36Sopenharmony_ci			if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) {
128462306a36Sopenharmony_ci				table->maxVDDCIndexInPPTable = i;
128562306a36Sopenharmony_ci				break;
128662306a36Sopenharmony_ci			}
128762306a36Sopenharmony_ci		}
128862306a36Sopenharmony_ci	}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	if (eg_pi->vddci_voltage_table.count) {
129162306a36Sopenharmony_ci		ni_populate_smc_voltage_table(rdev, &eg_pi->vddci_voltage_table, table);
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci		table->voltageMaskTable.highMask[NISLANDS_SMC_VOLTAGEMASK_VDDCI] = 0;
129462306a36Sopenharmony_ci		table->voltageMaskTable.lowMask[NISLANDS_SMC_VOLTAGEMASK_VDDCI] =
129562306a36Sopenharmony_ci			cpu_to_be32(eg_pi->vddci_voltage_table.mask_low);
129662306a36Sopenharmony_ci	}
129762306a36Sopenharmony_ci}
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_cistatic int ni_populate_voltage_value(struct radeon_device *rdev,
130062306a36Sopenharmony_ci				     struct atom_voltage_table *table,
130162306a36Sopenharmony_ci				     u16 value,
130262306a36Sopenharmony_ci				     NISLANDS_SMC_VOLTAGE_VALUE *voltage)
130362306a36Sopenharmony_ci{
130462306a36Sopenharmony_ci	unsigned int i;
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	for (i = 0; i < table->count; i++) {
130762306a36Sopenharmony_ci		if (value <= table->entries[i].value) {
130862306a36Sopenharmony_ci			voltage->index = (u8)i;
130962306a36Sopenharmony_ci			voltage->value = cpu_to_be16(table->entries[i].value);
131062306a36Sopenharmony_ci			break;
131162306a36Sopenharmony_ci		}
131262306a36Sopenharmony_ci	}
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	if (i >= table->count)
131562306a36Sopenharmony_ci		return -EINVAL;
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci	return 0;
131862306a36Sopenharmony_ci}
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_cistatic void ni_populate_mvdd_value(struct radeon_device *rdev,
132162306a36Sopenharmony_ci				   u32 mclk,
132262306a36Sopenharmony_ci				   NISLANDS_SMC_VOLTAGE_VALUE *voltage)
132362306a36Sopenharmony_ci{
132462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
132562306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	if (!pi->mvdd_control) {
132862306a36Sopenharmony_ci		voltage->index = eg_pi->mvdd_high_index;
132962306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
133062306a36Sopenharmony_ci		return;
133162306a36Sopenharmony_ci	}
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	if (mclk <= pi->mvdd_split_frequency) {
133462306a36Sopenharmony_ci		voltage->index = eg_pi->mvdd_low_index;
133562306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_LOW_VALUE);
133662306a36Sopenharmony_ci	} else {
133762306a36Sopenharmony_ci		voltage->index = eg_pi->mvdd_high_index;
133862306a36Sopenharmony_ci		voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
133962306a36Sopenharmony_ci	}
134062306a36Sopenharmony_ci}
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_cistatic int ni_get_std_voltage_value(struct radeon_device *rdev,
134362306a36Sopenharmony_ci				    NISLANDS_SMC_VOLTAGE_VALUE *voltage,
134462306a36Sopenharmony_ci				    u16 *std_voltage)
134562306a36Sopenharmony_ci{
134662306a36Sopenharmony_ci	if (rdev->pm.dpm.dyn_state.cac_leakage_table.entries &&
134762306a36Sopenharmony_ci	    ((u32)voltage->index < rdev->pm.dpm.dyn_state.cac_leakage_table.count))
134862306a36Sopenharmony_ci		*std_voltage = rdev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc;
134962306a36Sopenharmony_ci	else
135062306a36Sopenharmony_ci		*std_voltage = be16_to_cpu(voltage->value);
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci	return 0;
135362306a36Sopenharmony_ci}
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_cistatic void ni_populate_std_voltage_value(struct radeon_device *rdev,
135662306a36Sopenharmony_ci					  u16 value, u8 index,
135762306a36Sopenharmony_ci					  NISLANDS_SMC_VOLTAGE_VALUE *voltage)
135862306a36Sopenharmony_ci{
135962306a36Sopenharmony_ci	voltage->index = index;
136062306a36Sopenharmony_ci	voltage->value = cpu_to_be16(value);
136162306a36Sopenharmony_ci}
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_cistatic u32 ni_get_smc_power_scaling_factor(struct radeon_device *rdev)
136462306a36Sopenharmony_ci{
136562306a36Sopenharmony_ci	u32 xclk_period;
136662306a36Sopenharmony_ci	u32 xclk = radeon_get_xclk(rdev);
136762306a36Sopenharmony_ci	u32 tmp = RREG32(CG_CAC_CTRL) & TID_CNT_MASK;
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci	xclk_period = (1000000000UL / xclk);
137062306a36Sopenharmony_ci	xclk_period /= 10000UL;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	return tmp * xclk_period;
137362306a36Sopenharmony_ci}
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_cistatic u32 ni_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor)
137662306a36Sopenharmony_ci{
137762306a36Sopenharmony_ci	return (power_in_watts * scaling_factor) << 2;
137862306a36Sopenharmony_ci}
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_cistatic u32 ni_calculate_power_boost_limit(struct radeon_device *rdev,
138162306a36Sopenharmony_ci					  struct radeon_ps *radeon_state,
138262306a36Sopenharmony_ci					  u32 near_tdp_limit)
138362306a36Sopenharmony_ci{
138462306a36Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
138562306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
138662306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
138762306a36Sopenharmony_ci	u32 power_boost_limit = 0;
138862306a36Sopenharmony_ci	int ret;
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	if (ni_pi->enable_power_containment &&
139162306a36Sopenharmony_ci	    ni_pi->use_power_boost_limit) {
139262306a36Sopenharmony_ci		NISLANDS_SMC_VOLTAGE_VALUE vddc;
139362306a36Sopenharmony_ci		u16 std_vddc_med;
139462306a36Sopenharmony_ci		u16 std_vddc_high;
139562306a36Sopenharmony_ci		u64 tmp, n, d;
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci		if (state->performance_level_count < 3)
139862306a36Sopenharmony_ci			return 0;
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci		ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
140162306a36Sopenharmony_ci						state->performance_levels[state->performance_level_count - 2].vddc,
140262306a36Sopenharmony_ci						&vddc);
140362306a36Sopenharmony_ci		if (ret)
140462306a36Sopenharmony_ci			return 0;
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_ci		ret = ni_get_std_voltage_value(rdev, &vddc, &std_vddc_med);
140762306a36Sopenharmony_ci		if (ret)
140862306a36Sopenharmony_ci			return 0;
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_ci		ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
141162306a36Sopenharmony_ci						state->performance_levels[state->performance_level_count - 1].vddc,
141262306a36Sopenharmony_ci						&vddc);
141362306a36Sopenharmony_ci		if (ret)
141462306a36Sopenharmony_ci			return 0;
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci		ret = ni_get_std_voltage_value(rdev, &vddc, &std_vddc_high);
141762306a36Sopenharmony_ci		if (ret)
141862306a36Sopenharmony_ci			return 0;
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci		n = ((u64)near_tdp_limit * ((u64)std_vddc_med * (u64)std_vddc_med) * 90);
142162306a36Sopenharmony_ci		d = ((u64)std_vddc_high * (u64)std_vddc_high * 100);
142262306a36Sopenharmony_ci		tmp = div64_u64(n, d);
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci		if (tmp >> 32)
142562306a36Sopenharmony_ci			return 0;
142662306a36Sopenharmony_ci		power_boost_limit = (u32)tmp;
142762306a36Sopenharmony_ci	}
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	return power_boost_limit;
143062306a36Sopenharmony_ci}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cistatic int ni_calculate_adjusted_tdp_limits(struct radeon_device *rdev,
143362306a36Sopenharmony_ci					    bool adjust_polarity,
143462306a36Sopenharmony_ci					    u32 tdp_adjustment,
143562306a36Sopenharmony_ci					    u32 *tdp_limit,
143662306a36Sopenharmony_ci					    u32 *near_tdp_limit)
143762306a36Sopenharmony_ci{
143862306a36Sopenharmony_ci	if (tdp_adjustment > (u32)rdev->pm.dpm.tdp_od_limit)
143962306a36Sopenharmony_ci		return -EINVAL;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	if (adjust_polarity) {
144262306a36Sopenharmony_ci		*tdp_limit = ((100 + tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
144362306a36Sopenharmony_ci		*near_tdp_limit = rdev->pm.dpm.near_tdp_limit + (*tdp_limit - rdev->pm.dpm.tdp_limit);
144462306a36Sopenharmony_ci	} else {
144562306a36Sopenharmony_ci		*tdp_limit = ((100 - tdp_adjustment) * rdev->pm.dpm.tdp_limit) / 100;
144662306a36Sopenharmony_ci		*near_tdp_limit = rdev->pm.dpm.near_tdp_limit - (rdev->pm.dpm.tdp_limit - *tdp_limit);
144762306a36Sopenharmony_ci	}
144862306a36Sopenharmony_ci
144962306a36Sopenharmony_ci	return 0;
145062306a36Sopenharmony_ci}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_cistatic int ni_populate_smc_tdp_limits(struct radeon_device *rdev,
145362306a36Sopenharmony_ci				      struct radeon_ps *radeon_state)
145462306a36Sopenharmony_ci{
145562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
145662306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	if (ni_pi->enable_power_containment) {
145962306a36Sopenharmony_ci		NISLANDS_SMC_STATETABLE *smc_table = &ni_pi->smc_statetable;
146062306a36Sopenharmony_ci		u32 scaling_factor = ni_get_smc_power_scaling_factor(rdev);
146162306a36Sopenharmony_ci		u32 tdp_limit;
146262306a36Sopenharmony_ci		u32 near_tdp_limit;
146362306a36Sopenharmony_ci		u32 power_boost_limit;
146462306a36Sopenharmony_ci		int ret;
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci		if (scaling_factor == 0)
146762306a36Sopenharmony_ci			return -EINVAL;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci		memset(smc_table, 0, sizeof(NISLANDS_SMC_STATETABLE));
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci		ret = ni_calculate_adjusted_tdp_limits(rdev,
147262306a36Sopenharmony_ci						       false, /* ??? */
147362306a36Sopenharmony_ci						       rdev->pm.dpm.tdp_adjustment,
147462306a36Sopenharmony_ci						       &tdp_limit,
147562306a36Sopenharmony_ci						       &near_tdp_limit);
147662306a36Sopenharmony_ci		if (ret)
147762306a36Sopenharmony_ci			return ret;
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci		power_boost_limit = ni_calculate_power_boost_limit(rdev, radeon_state,
148062306a36Sopenharmony_ci								   near_tdp_limit);
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci		smc_table->dpm2Params.TDPLimit =
148362306a36Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc(tdp_limit, scaling_factor));
148462306a36Sopenharmony_ci		smc_table->dpm2Params.NearTDPLimit =
148562306a36Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc(near_tdp_limit, scaling_factor));
148662306a36Sopenharmony_ci		smc_table->dpm2Params.SafePowerLimit =
148762306a36Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc((near_tdp_limit * NISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100,
148862306a36Sopenharmony_ci							   scaling_factor));
148962306a36Sopenharmony_ci		smc_table->dpm2Params.PowerBoostLimit =
149062306a36Sopenharmony_ci			cpu_to_be32(ni_scale_power_for_smc(power_boost_limit, scaling_factor));
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci		ret = rv770_copy_bytes_to_smc(rdev,
149362306a36Sopenharmony_ci					      (u16)(pi->state_table_start + offsetof(NISLANDS_SMC_STATETABLE, dpm2Params) +
149462306a36Sopenharmony_ci						    offsetof(PP_NIslands_DPM2Parameters, TDPLimit)),
149562306a36Sopenharmony_ci					      (u8 *)(&smc_table->dpm2Params.TDPLimit),
149662306a36Sopenharmony_ci					      sizeof(u32) * 4, pi->sram_end);
149762306a36Sopenharmony_ci		if (ret)
149862306a36Sopenharmony_ci			return ret;
149962306a36Sopenharmony_ci	}
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	return 0;
150262306a36Sopenharmony_ci}
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ciint ni_copy_and_switch_arb_sets(struct radeon_device *rdev,
150562306a36Sopenharmony_ci				u32 arb_freq_src, u32 arb_freq_dest)
150662306a36Sopenharmony_ci{
150762306a36Sopenharmony_ci	u32 mc_arb_dram_timing;
150862306a36Sopenharmony_ci	u32 mc_arb_dram_timing2;
150962306a36Sopenharmony_ci	u32 burst_time;
151062306a36Sopenharmony_ci	u32 mc_cg_config;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	switch (arb_freq_src) {
151362306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F0:
151462306a36Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING);
151562306a36Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
151662306a36Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT;
151762306a36Sopenharmony_ci		break;
151862306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F1:
151962306a36Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_1);
152062306a36Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1);
152162306a36Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT;
152262306a36Sopenharmony_ci		break;
152362306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F2:
152462306a36Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_2);
152562306a36Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2);
152662306a36Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT;
152762306a36Sopenharmony_ci		break;
152862306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F3:
152962306a36Sopenharmony_ci		mc_arb_dram_timing  = RREG32(MC_ARB_DRAM_TIMING_3);
153062306a36Sopenharmony_ci		mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3);
153162306a36Sopenharmony_ci		burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT;
153262306a36Sopenharmony_ci		break;
153362306a36Sopenharmony_ci	default:
153462306a36Sopenharmony_ci		return -EINVAL;
153562306a36Sopenharmony_ci	}
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci	switch (arb_freq_dest) {
153862306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F0:
153962306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing);
154062306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2);
154162306a36Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK);
154262306a36Sopenharmony_ci		break;
154362306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F1:
154462306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing);
154562306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2);
154662306a36Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK);
154762306a36Sopenharmony_ci		break;
154862306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F2:
154962306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing);
155062306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2);
155162306a36Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK);
155262306a36Sopenharmony_ci		break;
155362306a36Sopenharmony_ci	case MC_CG_ARB_FREQ_F3:
155462306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing);
155562306a36Sopenharmony_ci		WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2);
155662306a36Sopenharmony_ci		WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK);
155762306a36Sopenharmony_ci		break;
155862306a36Sopenharmony_ci	default:
155962306a36Sopenharmony_ci		return -EINVAL;
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F;
156362306a36Sopenharmony_ci	WREG32(MC_CG_CONFIG, mc_cg_config);
156462306a36Sopenharmony_ci	WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK);
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci	return 0;
156762306a36Sopenharmony_ci}
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_cistatic int ni_init_arb_table_index(struct radeon_device *rdev)
157062306a36Sopenharmony_ci{
157162306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
157262306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
157362306a36Sopenharmony_ci	u32 tmp;
157462306a36Sopenharmony_ci	int ret;
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev, ni_pi->arb_table_start,
157762306a36Sopenharmony_ci					&tmp, pi->sram_end);
157862306a36Sopenharmony_ci	if (ret)
157962306a36Sopenharmony_ci		return ret;
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	tmp &= 0x00FFFFFF;
158262306a36Sopenharmony_ci	tmp |= ((u32)MC_CG_ARB_FREQ_F1) << 24;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	return rv770_write_smc_sram_dword(rdev, ni_pi->arb_table_start,
158562306a36Sopenharmony_ci					  tmp, pi->sram_end);
158662306a36Sopenharmony_ci}
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_cistatic int ni_initial_switch_from_arb_f0_to_f1(struct radeon_device *rdev)
158962306a36Sopenharmony_ci{
159062306a36Sopenharmony_ci	return ni_copy_and_switch_arb_sets(rdev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1);
159162306a36Sopenharmony_ci}
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_cistatic int ni_force_switch_to_arb_f0(struct radeon_device *rdev)
159462306a36Sopenharmony_ci{
159562306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
159662306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
159762306a36Sopenharmony_ci	u32 tmp;
159862306a36Sopenharmony_ci	int ret;
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	ret = rv770_read_smc_sram_dword(rdev, ni_pi->arb_table_start,
160162306a36Sopenharmony_ci					&tmp, pi->sram_end);
160262306a36Sopenharmony_ci	if (ret)
160362306a36Sopenharmony_ci		return ret;
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_ci	tmp = (tmp >> 24) & 0xff;
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci	if (tmp == MC_CG_ARB_FREQ_F0)
160862306a36Sopenharmony_ci		return 0;
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_ci	return ni_copy_and_switch_arb_sets(rdev, tmp, MC_CG_ARB_FREQ_F0);
161162306a36Sopenharmony_ci}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_cistatic int ni_populate_memory_timing_parameters(struct radeon_device *rdev,
161462306a36Sopenharmony_ci						struct rv7xx_pl *pl,
161562306a36Sopenharmony_ci						SMC_NIslands_MCArbDramTimingRegisterSet *arb_regs)
161662306a36Sopenharmony_ci{
161762306a36Sopenharmony_ci	u32 dram_timing;
161862306a36Sopenharmony_ci	u32 dram_timing2;
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci	arb_regs->mc_arb_rfsh_rate =
162162306a36Sopenharmony_ci		(u8)rv770_calculate_memory_refresh_rate(rdev, pl->sclk);
162262306a36Sopenharmony_ci
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	radeon_atom_set_engine_dram_timings(rdev, pl->sclk, pl->mclk);
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_ci	dram_timing = RREG32(MC_ARB_DRAM_TIMING);
162762306a36Sopenharmony_ci	dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2);
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci	arb_regs->mc_arb_dram_timing  = cpu_to_be32(dram_timing);
163062306a36Sopenharmony_ci	arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2);
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	return 0;
163362306a36Sopenharmony_ci}
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_cistatic int ni_do_program_memory_timing_parameters(struct radeon_device *rdev,
163662306a36Sopenharmony_ci						  struct radeon_ps *radeon_state,
163762306a36Sopenharmony_ci						  unsigned int first_arb_set)
163862306a36Sopenharmony_ci{
163962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
164062306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
164162306a36Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
164262306a36Sopenharmony_ci	SMC_NIslands_MCArbDramTimingRegisterSet arb_regs = { 0 };
164362306a36Sopenharmony_ci	int i, ret = 0;
164462306a36Sopenharmony_ci
164562306a36Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
164662306a36Sopenharmony_ci		ret = ni_populate_memory_timing_parameters(rdev, &state->performance_levels[i], &arb_regs);
164762306a36Sopenharmony_ci		if (ret)
164862306a36Sopenharmony_ci			break;
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci		ret = rv770_copy_bytes_to_smc(rdev,
165162306a36Sopenharmony_ci					      (u16)(ni_pi->arb_table_start +
165262306a36Sopenharmony_ci						    offsetof(SMC_NIslands_MCArbDramTimingRegisters, data) +
165362306a36Sopenharmony_ci						    sizeof(SMC_NIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i)),
165462306a36Sopenharmony_ci					      (u8 *)&arb_regs,
165562306a36Sopenharmony_ci					      (u16)sizeof(SMC_NIslands_MCArbDramTimingRegisterSet),
165662306a36Sopenharmony_ci					      pi->sram_end);
165762306a36Sopenharmony_ci		if (ret)
165862306a36Sopenharmony_ci			break;
165962306a36Sopenharmony_ci	}
166062306a36Sopenharmony_ci	return ret;
166162306a36Sopenharmony_ci}
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_cistatic int ni_program_memory_timing_parameters(struct radeon_device *rdev,
166462306a36Sopenharmony_ci					       struct radeon_ps *radeon_new_state)
166562306a36Sopenharmony_ci{
166662306a36Sopenharmony_ci	return ni_do_program_memory_timing_parameters(rdev, radeon_new_state,
166762306a36Sopenharmony_ci						      NISLANDS_DRIVER_STATE_ARB_INDEX);
166862306a36Sopenharmony_ci}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_cistatic void ni_populate_initial_mvdd_value(struct radeon_device *rdev,
167162306a36Sopenharmony_ci					   struct NISLANDS_SMC_VOLTAGE_VALUE *voltage)
167262306a36Sopenharmony_ci{
167362306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_ci	voltage->index = eg_pi->mvdd_high_index;
167662306a36Sopenharmony_ci	voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
167762306a36Sopenharmony_ci}
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_cistatic int ni_populate_smc_initial_state(struct radeon_device *rdev,
168062306a36Sopenharmony_ci					 struct radeon_ps *radeon_initial_state,
168162306a36Sopenharmony_ci					 NISLANDS_SMC_STATETABLE *table)
168262306a36Sopenharmony_ci{
168362306a36Sopenharmony_ci	struct ni_ps *initial_state = ni_get_ps(radeon_initial_state);
168462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
168562306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
168662306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
168762306a36Sopenharmony_ci	u32 reg;
168862306a36Sopenharmony_ci	int ret;
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci	table->initialState.level.mclk.vMPLL_AD_FUNC_CNTL =
169162306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ad_func_cntl);
169262306a36Sopenharmony_ci	table->initialState.level.mclk.vMPLL_AD_FUNC_CNTL_2 =
169362306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ad_func_cntl_2);
169462306a36Sopenharmony_ci	table->initialState.level.mclk.vMPLL_DQ_FUNC_CNTL =
169562306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_dq_func_cntl);
169662306a36Sopenharmony_ci	table->initialState.level.mclk.vMPLL_DQ_FUNC_CNTL_2 =
169762306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_dq_func_cntl_2);
169862306a36Sopenharmony_ci	table->initialState.level.mclk.vMCLK_PWRMGT_CNTL =
169962306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mclk_pwrmgt_cntl);
170062306a36Sopenharmony_ci	table->initialState.level.mclk.vDLL_CNTL =
170162306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.dll_cntl);
170262306a36Sopenharmony_ci	table->initialState.level.mclk.vMPLL_SS =
170362306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ss1);
170462306a36Sopenharmony_ci	table->initialState.level.mclk.vMPLL_SS2 =
170562306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.mpll_ss2);
170662306a36Sopenharmony_ci	table->initialState.level.mclk.mclk_value =
170762306a36Sopenharmony_ci		cpu_to_be32(initial_state->performance_levels[0].mclk);
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL =
171062306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl);
171162306a36Sopenharmony_ci	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_2 =
171262306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_2);
171362306a36Sopenharmony_ci	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_3 =
171462306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_3);
171562306a36Sopenharmony_ci	table->initialState.level.sclk.vCG_SPLL_FUNC_CNTL_4 =
171662306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_func_cntl_4);
171762306a36Sopenharmony_ci	table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM =
171862306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_spread_spectrum);
171962306a36Sopenharmony_ci	table->initialState.level.sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
172062306a36Sopenharmony_ci		cpu_to_be32(ni_pi->clock_registers.cg_spll_spread_spectrum_2);
172162306a36Sopenharmony_ci	table->initialState.level.sclk.sclk_value =
172262306a36Sopenharmony_ci		cpu_to_be32(initial_state->performance_levels[0].sclk);
172362306a36Sopenharmony_ci	table->initialState.level.arbRefreshState =
172462306a36Sopenharmony_ci		NISLANDS_INITIAL_STATE_ARB_INDEX;
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	table->initialState.level.ACIndex = 0;
172762306a36Sopenharmony_ci
172862306a36Sopenharmony_ci	ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
172962306a36Sopenharmony_ci					initial_state->performance_levels[0].vddc,
173062306a36Sopenharmony_ci					&table->initialState.level.vddc);
173162306a36Sopenharmony_ci	if (!ret) {
173262306a36Sopenharmony_ci		u16 std_vddc;
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci		ret = ni_get_std_voltage_value(rdev,
173562306a36Sopenharmony_ci					       &table->initialState.level.vddc,
173662306a36Sopenharmony_ci					       &std_vddc);
173762306a36Sopenharmony_ci		if (!ret)
173862306a36Sopenharmony_ci			ni_populate_std_voltage_value(rdev, std_vddc,
173962306a36Sopenharmony_ci						      table->initialState.level.vddc.index,
174062306a36Sopenharmony_ci						      &table->initialState.level.std_vddc);
174162306a36Sopenharmony_ci	}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci	if (eg_pi->vddci_control)
174462306a36Sopenharmony_ci		ni_populate_voltage_value(rdev,
174562306a36Sopenharmony_ci					  &eg_pi->vddci_voltage_table,
174662306a36Sopenharmony_ci					  initial_state->performance_levels[0].vddci,
174762306a36Sopenharmony_ci					  &table->initialState.level.vddci);
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	ni_populate_initial_mvdd_value(rdev, &table->initialState.level.mvdd);
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci	reg = CG_R(0xffff) | CG_L(0);
175262306a36Sopenharmony_ci	table->initialState.level.aT = cpu_to_be32(reg);
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	table->initialState.level.bSP = cpu_to_be32(pi->dsp);
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	if (pi->boot_in_gen2)
175762306a36Sopenharmony_ci		table->initialState.level.gen2PCIE = 1;
175862306a36Sopenharmony_ci	else
175962306a36Sopenharmony_ci		table->initialState.level.gen2PCIE = 0;
176062306a36Sopenharmony_ci
176162306a36Sopenharmony_ci	if (pi->mem_gddr5) {
176262306a36Sopenharmony_ci		table->initialState.level.strobeMode =
176362306a36Sopenharmony_ci			cypress_get_strobe_mode_settings(rdev,
176462306a36Sopenharmony_ci							 initial_state->performance_levels[0].mclk);
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci		if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold)
176762306a36Sopenharmony_ci			table->initialState.level.mcFlags = NISLANDS_SMC_MC_EDC_RD_FLAG | NISLANDS_SMC_MC_EDC_WR_FLAG;
176862306a36Sopenharmony_ci		else
176962306a36Sopenharmony_ci			table->initialState.level.mcFlags =  0;
177062306a36Sopenharmony_ci	}
177162306a36Sopenharmony_ci
177262306a36Sopenharmony_ci	table->initialState.levelCount = 1;
177362306a36Sopenharmony_ci
177462306a36Sopenharmony_ci	table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci	table->initialState.level.dpm2.MaxPS = 0;
177762306a36Sopenharmony_ci	table->initialState.level.dpm2.NearTDPDec = 0;
177862306a36Sopenharmony_ci	table->initialState.level.dpm2.AboveSafeInc = 0;
177962306a36Sopenharmony_ci	table->initialState.level.dpm2.BelowSafeInc = 0;
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	reg = MIN_POWER_MASK | MAX_POWER_MASK;
178262306a36Sopenharmony_ci	table->initialState.level.SQPowerThrottle = cpu_to_be32(reg);
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
178562306a36Sopenharmony_ci	table->initialState.level.SQPowerThrottle_2 = cpu_to_be32(reg);
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	return 0;
178862306a36Sopenharmony_ci}
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_cistatic int ni_populate_smc_acpi_state(struct radeon_device *rdev,
179162306a36Sopenharmony_ci				      NISLANDS_SMC_STATETABLE *table)
179262306a36Sopenharmony_ci{
179362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
179462306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
179562306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
179662306a36Sopenharmony_ci	u32 mpll_ad_func_cntl   = ni_pi->clock_registers.mpll_ad_func_cntl;
179762306a36Sopenharmony_ci	u32 mpll_ad_func_cntl_2 = ni_pi->clock_registers.mpll_ad_func_cntl_2;
179862306a36Sopenharmony_ci	u32 mpll_dq_func_cntl   = ni_pi->clock_registers.mpll_dq_func_cntl;
179962306a36Sopenharmony_ci	u32 mpll_dq_func_cntl_2 = ni_pi->clock_registers.mpll_dq_func_cntl_2;
180062306a36Sopenharmony_ci	u32 spll_func_cntl      = ni_pi->clock_registers.cg_spll_func_cntl;
180162306a36Sopenharmony_ci	u32 spll_func_cntl_2    = ni_pi->clock_registers.cg_spll_func_cntl_2;
180262306a36Sopenharmony_ci	u32 spll_func_cntl_3    = ni_pi->clock_registers.cg_spll_func_cntl_3;
180362306a36Sopenharmony_ci	u32 spll_func_cntl_4    = ni_pi->clock_registers.cg_spll_func_cntl_4;
180462306a36Sopenharmony_ci	u32 mclk_pwrmgt_cntl    = ni_pi->clock_registers.mclk_pwrmgt_cntl;
180562306a36Sopenharmony_ci	u32 dll_cntl            = ni_pi->clock_registers.dll_cntl;
180662306a36Sopenharmony_ci	u32 reg;
180762306a36Sopenharmony_ci	int ret;
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_ci	table->ACPIState = table->initialState;
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_ci	table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	if (pi->acpi_vddc) {
181462306a36Sopenharmony_ci		ret = ni_populate_voltage_value(rdev,
181562306a36Sopenharmony_ci						&eg_pi->vddc_voltage_table,
181662306a36Sopenharmony_ci						pi->acpi_vddc, &table->ACPIState.level.vddc);
181762306a36Sopenharmony_ci		if (!ret) {
181862306a36Sopenharmony_ci			u16 std_vddc;
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci			ret = ni_get_std_voltage_value(rdev,
182162306a36Sopenharmony_ci						       &table->ACPIState.level.vddc, &std_vddc);
182262306a36Sopenharmony_ci			if (!ret)
182362306a36Sopenharmony_ci				ni_populate_std_voltage_value(rdev, std_vddc,
182462306a36Sopenharmony_ci							      table->ACPIState.level.vddc.index,
182562306a36Sopenharmony_ci							      &table->ACPIState.level.std_vddc);
182662306a36Sopenharmony_ci		}
182762306a36Sopenharmony_ci
182862306a36Sopenharmony_ci		if (pi->pcie_gen2) {
182962306a36Sopenharmony_ci			if (pi->acpi_pcie_gen2)
183062306a36Sopenharmony_ci				table->ACPIState.level.gen2PCIE = 1;
183162306a36Sopenharmony_ci			else
183262306a36Sopenharmony_ci				table->ACPIState.level.gen2PCIE = 0;
183362306a36Sopenharmony_ci		} else {
183462306a36Sopenharmony_ci			table->ACPIState.level.gen2PCIE = 0;
183562306a36Sopenharmony_ci		}
183662306a36Sopenharmony_ci	} else {
183762306a36Sopenharmony_ci		ret = ni_populate_voltage_value(rdev,
183862306a36Sopenharmony_ci						&eg_pi->vddc_voltage_table,
183962306a36Sopenharmony_ci						pi->min_vddc_in_table,
184062306a36Sopenharmony_ci						&table->ACPIState.level.vddc);
184162306a36Sopenharmony_ci		if (!ret) {
184262306a36Sopenharmony_ci			u16 std_vddc;
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci			ret = ni_get_std_voltage_value(rdev,
184562306a36Sopenharmony_ci						       &table->ACPIState.level.vddc,
184662306a36Sopenharmony_ci						       &std_vddc);
184762306a36Sopenharmony_ci			if (!ret)
184862306a36Sopenharmony_ci				ni_populate_std_voltage_value(rdev, std_vddc,
184962306a36Sopenharmony_ci							      table->ACPIState.level.vddc.index,
185062306a36Sopenharmony_ci							      &table->ACPIState.level.std_vddc);
185162306a36Sopenharmony_ci		}
185262306a36Sopenharmony_ci		table->ACPIState.level.gen2PCIE = 0;
185362306a36Sopenharmony_ci	}
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	if (eg_pi->acpi_vddci) {
185662306a36Sopenharmony_ci		if (eg_pi->vddci_control)
185762306a36Sopenharmony_ci			ni_populate_voltage_value(rdev,
185862306a36Sopenharmony_ci						  &eg_pi->vddci_voltage_table,
185962306a36Sopenharmony_ci						  eg_pi->acpi_vddci,
186062306a36Sopenharmony_ci						  &table->ACPIState.level.vddci);
186162306a36Sopenharmony_ci	}
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_ci	mpll_ad_func_cntl &= ~PDNB;
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci	mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	if (pi->mem_gddr5)
186962306a36Sopenharmony_ci		mpll_dq_func_cntl &= ~PDNB;
187062306a36Sopenharmony_ci	mpll_dq_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN | BYPASS;
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci	mclk_pwrmgt_cntl |= (MRDCKA0_RESET |
187462306a36Sopenharmony_ci			     MRDCKA1_RESET |
187562306a36Sopenharmony_ci			     MRDCKB0_RESET |
187662306a36Sopenharmony_ci			     MRDCKB1_RESET |
187762306a36Sopenharmony_ci			     MRDCKC0_RESET |
187862306a36Sopenharmony_ci			     MRDCKC1_RESET |
187962306a36Sopenharmony_ci			     MRDCKD0_RESET |
188062306a36Sopenharmony_ci			     MRDCKD1_RESET);
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci	mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
188362306a36Sopenharmony_ci			      MRDCKA1_PDNB |
188462306a36Sopenharmony_ci			      MRDCKB0_PDNB |
188562306a36Sopenharmony_ci			      MRDCKB1_PDNB |
188662306a36Sopenharmony_ci			      MRDCKC0_PDNB |
188762306a36Sopenharmony_ci			      MRDCKC1_PDNB |
188862306a36Sopenharmony_ci			      MRDCKD0_PDNB |
188962306a36Sopenharmony_ci			      MRDCKD1_PDNB);
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci	dll_cntl |= (MRDCKA0_BYPASS |
189262306a36Sopenharmony_ci		     MRDCKA1_BYPASS |
189362306a36Sopenharmony_ci		     MRDCKB0_BYPASS |
189462306a36Sopenharmony_ci		     MRDCKB1_BYPASS |
189562306a36Sopenharmony_ci		     MRDCKC0_BYPASS |
189662306a36Sopenharmony_ci		     MRDCKC1_BYPASS |
189762306a36Sopenharmony_ci		     MRDCKD0_BYPASS |
189862306a36Sopenharmony_ci		     MRDCKD1_BYPASS);
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
190162306a36Sopenharmony_ci	spll_func_cntl_2 |= SCLK_MUX_SEL(4);
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	table->ACPIState.level.mclk.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
190462306a36Sopenharmony_ci	table->ACPIState.level.mclk.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
190562306a36Sopenharmony_ci	table->ACPIState.level.mclk.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
190662306a36Sopenharmony_ci	table->ACPIState.level.mclk.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
190762306a36Sopenharmony_ci	table->ACPIState.level.mclk.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
190862306a36Sopenharmony_ci	table->ACPIState.level.mclk.vDLL_CNTL = cpu_to_be32(dll_cntl);
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	table->ACPIState.level.mclk.mclk_value = 0;
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
191362306a36Sopenharmony_ci	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
191462306a36Sopenharmony_ci	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
191562306a36Sopenharmony_ci	table->ACPIState.level.sclk.vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(spll_func_cntl_4);
191662306a36Sopenharmony_ci
191762306a36Sopenharmony_ci	table->ACPIState.level.sclk.sclk_value = 0;
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	ni_populate_mvdd_value(rdev, 0, &table->ACPIState.level.mvdd);
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing)
192262306a36Sopenharmony_ci		table->ACPIState.level.ACIndex = 1;
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	table->ACPIState.level.dpm2.MaxPS = 0;
192562306a36Sopenharmony_ci	table->ACPIState.level.dpm2.NearTDPDec = 0;
192662306a36Sopenharmony_ci	table->ACPIState.level.dpm2.AboveSafeInc = 0;
192762306a36Sopenharmony_ci	table->ACPIState.level.dpm2.BelowSafeInc = 0;
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	reg = MIN_POWER_MASK | MAX_POWER_MASK;
193062306a36Sopenharmony_ci	table->ACPIState.level.SQPowerThrottle = cpu_to_be32(reg);
193162306a36Sopenharmony_ci
193262306a36Sopenharmony_ci	reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
193362306a36Sopenharmony_ci	table->ACPIState.level.SQPowerThrottle_2 = cpu_to_be32(reg);
193462306a36Sopenharmony_ci
193562306a36Sopenharmony_ci	return 0;
193662306a36Sopenharmony_ci}
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_cistatic int ni_init_smc_table(struct radeon_device *rdev)
193962306a36Sopenharmony_ci{
194062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
194162306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
194262306a36Sopenharmony_ci	int ret;
194362306a36Sopenharmony_ci	struct radeon_ps *radeon_boot_state = rdev->pm.dpm.boot_ps;
194462306a36Sopenharmony_ci	NISLANDS_SMC_STATETABLE *table = &ni_pi->smc_statetable;
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci	memset(table, 0, sizeof(NISLANDS_SMC_STATETABLE));
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	ni_populate_smc_voltage_tables(rdev, table);
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	switch (rdev->pm.int_thermal_type) {
195162306a36Sopenharmony_ci	case THERMAL_TYPE_NI:
195262306a36Sopenharmony_ci	case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
195362306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
195462306a36Sopenharmony_ci		break;
195562306a36Sopenharmony_ci	case THERMAL_TYPE_NONE:
195662306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;
195762306a36Sopenharmony_ci		break;
195862306a36Sopenharmony_ci	default:
195962306a36Sopenharmony_ci		table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
196062306a36Sopenharmony_ci		break;
196162306a36Sopenharmony_ci	}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC)
196462306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT)
196762306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT;
196862306a36Sopenharmony_ci
196962306a36Sopenharmony_ci	if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
197062306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	if (pi->mem_gddr5)
197362306a36Sopenharmony_ci		table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci	ret = ni_populate_smc_initial_state(rdev, radeon_boot_state, table);
197662306a36Sopenharmony_ci	if (ret)
197762306a36Sopenharmony_ci		return ret;
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_ci	ret = ni_populate_smc_acpi_state(rdev, table);
198062306a36Sopenharmony_ci	if (ret)
198162306a36Sopenharmony_ci		return ret;
198262306a36Sopenharmony_ci
198362306a36Sopenharmony_ci	table->driverState.flags = table->initialState.flags;
198462306a36Sopenharmony_ci	table->driverState.levelCount = table->initialState.levelCount;
198562306a36Sopenharmony_ci	table->driverState.levels[0] = table->initialState.level;
198662306a36Sopenharmony_ci
198762306a36Sopenharmony_ci	table->ULVState = table->initialState;
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	ret = ni_do_program_memory_timing_parameters(rdev, radeon_boot_state,
199062306a36Sopenharmony_ci						     NISLANDS_INITIAL_STATE_ARB_INDEX);
199162306a36Sopenharmony_ci	if (ret)
199262306a36Sopenharmony_ci		return ret;
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, pi->state_table_start, (u8 *)table,
199562306a36Sopenharmony_ci				       sizeof(NISLANDS_SMC_STATETABLE), pi->sram_end);
199662306a36Sopenharmony_ci}
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_cistatic int ni_calculate_sclk_params(struct radeon_device *rdev,
199962306a36Sopenharmony_ci				    u32 engine_clock,
200062306a36Sopenharmony_ci				    NISLANDS_SMC_SCLK_VALUE *sclk)
200162306a36Sopenharmony_ci{
200262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
200362306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
200462306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
200562306a36Sopenharmony_ci	u32 spll_func_cntl = ni_pi->clock_registers.cg_spll_func_cntl;
200662306a36Sopenharmony_ci	u32 spll_func_cntl_2 = ni_pi->clock_registers.cg_spll_func_cntl_2;
200762306a36Sopenharmony_ci	u32 spll_func_cntl_3 = ni_pi->clock_registers.cg_spll_func_cntl_3;
200862306a36Sopenharmony_ci	u32 spll_func_cntl_4 = ni_pi->clock_registers.cg_spll_func_cntl_4;
200962306a36Sopenharmony_ci	u32 cg_spll_spread_spectrum = ni_pi->clock_registers.cg_spll_spread_spectrum;
201062306a36Sopenharmony_ci	u32 cg_spll_spread_spectrum_2 = ni_pi->clock_registers.cg_spll_spread_spectrum_2;
201162306a36Sopenharmony_ci	u64 tmp;
201262306a36Sopenharmony_ci	u32 reference_clock = rdev->clock.spll.reference_freq;
201362306a36Sopenharmony_ci	u32 reference_divider;
201462306a36Sopenharmony_ci	u32 fbdiv;
201562306a36Sopenharmony_ci	int ret;
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
201862306a36Sopenharmony_ci					     engine_clock, false, &dividers);
201962306a36Sopenharmony_ci	if (ret)
202062306a36Sopenharmony_ci		return ret;
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	reference_divider = 1 + dividers.ref_div;
202362306a36Sopenharmony_ci
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16834;
202662306a36Sopenharmony_ci	do_div(tmp, reference_clock);
202762306a36Sopenharmony_ci	fbdiv = (u32) tmp;
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci	spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK);
203062306a36Sopenharmony_ci	spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
203162306a36Sopenharmony_ci	spll_func_cntl |= SPLL_PDIV_A(dividers.post_div);
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
203462306a36Sopenharmony_ci	spll_func_cntl_2 |= SCLK_MUX_SEL(2);
203562306a36Sopenharmony_ci
203662306a36Sopenharmony_ci	spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
203762306a36Sopenharmony_ci	spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
203862306a36Sopenharmony_ci	spll_func_cntl_3 |= SPLL_DITHEN;
203962306a36Sopenharmony_ci
204062306a36Sopenharmony_ci	if (pi->sclk_ss) {
204162306a36Sopenharmony_ci		struct radeon_atom_ss ss;
204262306a36Sopenharmony_ci		u32 vco_freq = engine_clock * dividers.post_div;
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_ci		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
204562306a36Sopenharmony_ci						     ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
204662306a36Sopenharmony_ci			u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
204762306a36Sopenharmony_ci			u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000);
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci			cg_spll_spread_spectrum &= ~CLK_S_MASK;
205062306a36Sopenharmony_ci			cg_spll_spread_spectrum |= CLK_S(clk_s);
205162306a36Sopenharmony_ci			cg_spll_spread_spectrum |= SSEN;
205262306a36Sopenharmony_ci
205362306a36Sopenharmony_ci			cg_spll_spread_spectrum_2 &= ~CLK_V_MASK;
205462306a36Sopenharmony_ci			cg_spll_spread_spectrum_2 |= CLK_V(clk_v);
205562306a36Sopenharmony_ci		}
205662306a36Sopenharmony_ci	}
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_ci	sclk->sclk_value = engine_clock;
205962306a36Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl;
206062306a36Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2;
206162306a36Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3;
206262306a36Sopenharmony_ci	sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4;
206362306a36Sopenharmony_ci	sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum;
206462306a36Sopenharmony_ci	sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2;
206562306a36Sopenharmony_ci
206662306a36Sopenharmony_ci	return 0;
206762306a36Sopenharmony_ci}
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_cistatic int ni_populate_sclk_value(struct radeon_device *rdev,
207062306a36Sopenharmony_ci				  u32 engine_clock,
207162306a36Sopenharmony_ci				  NISLANDS_SMC_SCLK_VALUE *sclk)
207262306a36Sopenharmony_ci{
207362306a36Sopenharmony_ci	NISLANDS_SMC_SCLK_VALUE sclk_tmp;
207462306a36Sopenharmony_ci	int ret;
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	ret = ni_calculate_sclk_params(rdev, engine_clock, &sclk_tmp);
207762306a36Sopenharmony_ci	if (!ret) {
207862306a36Sopenharmony_ci		sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value);
207962306a36Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL);
208062306a36Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2);
208162306a36Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3);
208262306a36Sopenharmony_ci		sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4);
208362306a36Sopenharmony_ci		sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM);
208462306a36Sopenharmony_ci		sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2);
208562306a36Sopenharmony_ci	}
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	return ret;
208862306a36Sopenharmony_ci}
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_cistatic int ni_init_smc_spll_table(struct radeon_device *rdev)
209162306a36Sopenharmony_ci{
209262306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
209362306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
209462306a36Sopenharmony_ci	SMC_NISLANDS_SPLL_DIV_TABLE *spll_table;
209562306a36Sopenharmony_ci	NISLANDS_SMC_SCLK_VALUE sclk_params;
209662306a36Sopenharmony_ci	u32 fb_div;
209762306a36Sopenharmony_ci	u32 p_div;
209862306a36Sopenharmony_ci	u32 clk_s;
209962306a36Sopenharmony_ci	u32 clk_v;
210062306a36Sopenharmony_ci	u32 sclk = 0;
210162306a36Sopenharmony_ci	int i, ret;
210262306a36Sopenharmony_ci	u32 tmp;
210362306a36Sopenharmony_ci
210462306a36Sopenharmony_ci	if (ni_pi->spll_table_start == 0)
210562306a36Sopenharmony_ci		return -EINVAL;
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci	spll_table = kzalloc(sizeof(SMC_NISLANDS_SPLL_DIV_TABLE), GFP_KERNEL);
210862306a36Sopenharmony_ci	if (spll_table == NULL)
210962306a36Sopenharmony_ci		return -ENOMEM;
211062306a36Sopenharmony_ci
211162306a36Sopenharmony_ci	for (i = 0; i < 256; i++) {
211262306a36Sopenharmony_ci		ret = ni_calculate_sclk_params(rdev, sclk, &sclk_params);
211362306a36Sopenharmony_ci		if (ret)
211462306a36Sopenharmony_ci			break;
211562306a36Sopenharmony_ci
211662306a36Sopenharmony_ci		p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT;
211762306a36Sopenharmony_ci		fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT;
211862306a36Sopenharmony_ci		clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT;
211962306a36Sopenharmony_ci		clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT;
212062306a36Sopenharmony_ci
212162306a36Sopenharmony_ci		fb_div &= ~0x00001FFF;
212262306a36Sopenharmony_ci		fb_div >>= 1;
212362306a36Sopenharmony_ci		clk_v >>= 6;
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci		if (p_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT))
212662306a36Sopenharmony_ci			ret = -EINVAL;
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci		if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
212962306a36Sopenharmony_ci			ret = -EINVAL;
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_ci		if (fb_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT))
213262306a36Sopenharmony_ci			ret = -EINVAL;
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ci		if (clk_v & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))
213562306a36Sopenharmony_ci			ret = -EINVAL;
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci		if (ret)
213862306a36Sopenharmony_ci			break;
213962306a36Sopenharmony_ci
214062306a36Sopenharmony_ci		tmp = ((fb_div << SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) |
214162306a36Sopenharmony_ci			((p_div << SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_PDIV_MASK);
214262306a36Sopenharmony_ci		spll_table->freq[i] = cpu_to_be32(tmp);
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci		tmp = ((clk_v << SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK) |
214562306a36Sopenharmony_ci			((clk_s << SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK);
214662306a36Sopenharmony_ci		spll_table->ss[i] = cpu_to_be32(tmp);
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_ci		sclk += 512;
214962306a36Sopenharmony_ci	}
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_ci	if (!ret)
215262306a36Sopenharmony_ci		ret = rv770_copy_bytes_to_smc(rdev, ni_pi->spll_table_start, (u8 *)spll_table,
215362306a36Sopenharmony_ci					      sizeof(SMC_NISLANDS_SPLL_DIV_TABLE), pi->sram_end);
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	kfree(spll_table);
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci	return ret;
215862306a36Sopenharmony_ci}
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_cistatic int ni_populate_mclk_value(struct radeon_device *rdev,
216162306a36Sopenharmony_ci				  u32 engine_clock,
216262306a36Sopenharmony_ci				  u32 memory_clock,
216362306a36Sopenharmony_ci				  NISLANDS_SMC_MCLK_VALUE *mclk,
216462306a36Sopenharmony_ci				  bool strobe_mode,
216562306a36Sopenharmony_ci				  bool dll_state_on)
216662306a36Sopenharmony_ci{
216762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
216862306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
216962306a36Sopenharmony_ci	u32 mpll_ad_func_cntl = ni_pi->clock_registers.mpll_ad_func_cntl;
217062306a36Sopenharmony_ci	u32 mpll_ad_func_cntl_2 = ni_pi->clock_registers.mpll_ad_func_cntl_2;
217162306a36Sopenharmony_ci	u32 mpll_dq_func_cntl = ni_pi->clock_registers.mpll_dq_func_cntl;
217262306a36Sopenharmony_ci	u32 mpll_dq_func_cntl_2 = ni_pi->clock_registers.mpll_dq_func_cntl_2;
217362306a36Sopenharmony_ci	u32 mclk_pwrmgt_cntl = ni_pi->clock_registers.mclk_pwrmgt_cntl;
217462306a36Sopenharmony_ci	u32 dll_cntl = ni_pi->clock_registers.dll_cntl;
217562306a36Sopenharmony_ci	u32 mpll_ss1 = ni_pi->clock_registers.mpll_ss1;
217662306a36Sopenharmony_ci	u32 mpll_ss2 = ni_pi->clock_registers.mpll_ss2;
217762306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
217862306a36Sopenharmony_ci	u32 ibias;
217962306a36Sopenharmony_ci	u32 dll_speed;
218062306a36Sopenharmony_ci	int ret;
218162306a36Sopenharmony_ci	u32 mc_seq_misc7;
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
218462306a36Sopenharmony_ci					     memory_clock, strobe_mode, &dividers);
218562306a36Sopenharmony_ci	if (ret)
218662306a36Sopenharmony_ci		return ret;
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci	if (!strobe_mode) {
218962306a36Sopenharmony_ci		mc_seq_misc7 = RREG32(MC_SEQ_MISC7);
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci		if (mc_seq_misc7 & 0x8000000)
219262306a36Sopenharmony_ci			dividers.post_div = 1;
219362306a36Sopenharmony_ci	}
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci	ibias = cypress_map_clkf_to_ibias(rdev, dividers.whole_fb_div);
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	mpll_ad_func_cntl &= ~(CLKR_MASK |
219862306a36Sopenharmony_ci			       YCLK_POST_DIV_MASK |
219962306a36Sopenharmony_ci			       CLKF_MASK |
220062306a36Sopenharmony_ci			       CLKFRAC_MASK |
220162306a36Sopenharmony_ci			       IBIAS_MASK);
220262306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKR(dividers.ref_div);
220362306a36Sopenharmony_ci	mpll_ad_func_cntl |= YCLK_POST_DIV(dividers.post_div);
220462306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKF(dividers.whole_fb_div);
220562306a36Sopenharmony_ci	mpll_ad_func_cntl |= CLKFRAC(dividers.frac_fb_div);
220662306a36Sopenharmony_ci	mpll_ad_func_cntl |= IBIAS(ibias);
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci	if (dividers.vco_mode)
220962306a36Sopenharmony_ci		mpll_ad_func_cntl_2 |= VCO_MODE;
221062306a36Sopenharmony_ci	else
221162306a36Sopenharmony_ci		mpll_ad_func_cntl_2 &= ~VCO_MODE;
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci	if (pi->mem_gddr5) {
221462306a36Sopenharmony_ci		mpll_dq_func_cntl &= ~(CLKR_MASK |
221562306a36Sopenharmony_ci				       YCLK_POST_DIV_MASK |
221662306a36Sopenharmony_ci				       CLKF_MASK |
221762306a36Sopenharmony_ci				       CLKFRAC_MASK |
221862306a36Sopenharmony_ci				       IBIAS_MASK);
221962306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKR(dividers.ref_div);
222062306a36Sopenharmony_ci		mpll_dq_func_cntl |= YCLK_POST_DIV(dividers.post_div);
222162306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKF(dividers.whole_fb_div);
222262306a36Sopenharmony_ci		mpll_dq_func_cntl |= CLKFRAC(dividers.frac_fb_div);
222362306a36Sopenharmony_ci		mpll_dq_func_cntl |= IBIAS(ibias);
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci		if (strobe_mode)
222662306a36Sopenharmony_ci			mpll_dq_func_cntl &= ~PDNB;
222762306a36Sopenharmony_ci		else
222862306a36Sopenharmony_ci			mpll_dq_func_cntl |= PDNB;
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ci		if (dividers.vco_mode)
223162306a36Sopenharmony_ci			mpll_dq_func_cntl_2 |= VCO_MODE;
223262306a36Sopenharmony_ci		else
223362306a36Sopenharmony_ci			mpll_dq_func_cntl_2 &= ~VCO_MODE;
223462306a36Sopenharmony_ci	}
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	if (pi->mclk_ss) {
223762306a36Sopenharmony_ci		struct radeon_atom_ss ss;
223862306a36Sopenharmony_ci		u32 vco_freq = memory_clock * dividers.post_div;
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci		if (radeon_atombios_get_asic_ss_info(rdev, &ss,
224162306a36Sopenharmony_ci						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
224262306a36Sopenharmony_ci			u32 reference_clock = rdev->clock.mpll.reference_freq;
224362306a36Sopenharmony_ci			u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
224462306a36Sopenharmony_ci			u32 clk_s, clk_v;
224562306a36Sopenharmony_ci
224662306a36Sopenharmony_ci			if (!decoded_ref)
224762306a36Sopenharmony_ci				return -EINVAL;
224862306a36Sopenharmony_ci			clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
224962306a36Sopenharmony_ci			clk_v = ss.percentage *
225062306a36Sopenharmony_ci				(0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci			mpll_ss1 &= ~CLKV_MASK;
225362306a36Sopenharmony_ci			mpll_ss1 |= CLKV(clk_v);
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci			mpll_ss2 &= ~CLKS_MASK;
225662306a36Sopenharmony_ci			mpll_ss2 |= CLKS(clk_s);
225762306a36Sopenharmony_ci		}
225862306a36Sopenharmony_ci	}
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci	dll_speed = rv740_get_dll_speed(pi->mem_gddr5,
226162306a36Sopenharmony_ci					memory_clock);
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK;
226462306a36Sopenharmony_ci	mclk_pwrmgt_cntl |= DLL_SPEED(dll_speed);
226562306a36Sopenharmony_ci	if (dll_state_on)
226662306a36Sopenharmony_ci		mclk_pwrmgt_cntl |= (MRDCKA0_PDNB |
226762306a36Sopenharmony_ci				     MRDCKA1_PDNB |
226862306a36Sopenharmony_ci				     MRDCKB0_PDNB |
226962306a36Sopenharmony_ci				     MRDCKB1_PDNB |
227062306a36Sopenharmony_ci				     MRDCKC0_PDNB |
227162306a36Sopenharmony_ci				     MRDCKC1_PDNB |
227262306a36Sopenharmony_ci				     MRDCKD0_PDNB |
227362306a36Sopenharmony_ci				     MRDCKD1_PDNB);
227462306a36Sopenharmony_ci	else
227562306a36Sopenharmony_ci		mclk_pwrmgt_cntl &= ~(MRDCKA0_PDNB |
227662306a36Sopenharmony_ci				      MRDCKA1_PDNB |
227762306a36Sopenharmony_ci				      MRDCKB0_PDNB |
227862306a36Sopenharmony_ci				      MRDCKB1_PDNB |
227962306a36Sopenharmony_ci				      MRDCKC0_PDNB |
228062306a36Sopenharmony_ci				      MRDCKC1_PDNB |
228162306a36Sopenharmony_ci				      MRDCKD0_PDNB |
228262306a36Sopenharmony_ci				      MRDCKD1_PDNB);
228362306a36Sopenharmony_ci
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci	mclk->mclk_value = cpu_to_be32(memory_clock);
228662306a36Sopenharmony_ci	mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
228762306a36Sopenharmony_ci	mclk->vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
228862306a36Sopenharmony_ci	mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
228962306a36Sopenharmony_ci	mclk->vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
229062306a36Sopenharmony_ci	mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
229162306a36Sopenharmony_ci	mclk->vDLL_CNTL = cpu_to_be32(dll_cntl);
229262306a36Sopenharmony_ci	mclk->vMPLL_SS = cpu_to_be32(mpll_ss1);
229362306a36Sopenharmony_ci	mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2);
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci	return 0;
229662306a36Sopenharmony_ci}
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_cistatic void ni_populate_smc_sp(struct radeon_device *rdev,
229962306a36Sopenharmony_ci			       struct radeon_ps *radeon_state,
230062306a36Sopenharmony_ci			       NISLANDS_SMC_SWSTATE *smc_state)
230162306a36Sopenharmony_ci{
230262306a36Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(radeon_state);
230362306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
230462306a36Sopenharmony_ci	int i;
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_ci	for (i = 0; i < ps->performance_level_count - 1; i++)
230762306a36Sopenharmony_ci		smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_ci	smc_state->levels[ps->performance_level_count - 1].bSP =
231062306a36Sopenharmony_ci		cpu_to_be32(pi->psp);
231162306a36Sopenharmony_ci}
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_cistatic int ni_convert_power_level_to_smc(struct radeon_device *rdev,
231462306a36Sopenharmony_ci					 struct rv7xx_pl *pl,
231562306a36Sopenharmony_ci					 NISLANDS_SMC_HW_PERFORMANCE_LEVEL *level)
231662306a36Sopenharmony_ci{
231762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
231862306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
231962306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
232062306a36Sopenharmony_ci	int ret;
232162306a36Sopenharmony_ci	bool dll_state_on;
232262306a36Sopenharmony_ci	u16 std_vddc;
232362306a36Sopenharmony_ci	u32 tmp = RREG32(DC_STUTTER_CNTL);
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	level->gen2PCIE = pi->pcie_gen2 ?
232662306a36Sopenharmony_ci		((pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0) : 0;
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci	ret = ni_populate_sclk_value(rdev, pl->sclk, &level->sclk);
232962306a36Sopenharmony_ci	if (ret)
233062306a36Sopenharmony_ci		return ret;
233162306a36Sopenharmony_ci
233262306a36Sopenharmony_ci	level->mcFlags =  0;
233362306a36Sopenharmony_ci	if (pi->mclk_stutter_mode_threshold &&
233462306a36Sopenharmony_ci	    (pl->mclk <= pi->mclk_stutter_mode_threshold) &&
233562306a36Sopenharmony_ci	    !eg_pi->uvd_enabled &&
233662306a36Sopenharmony_ci	    (tmp & DC_STUTTER_ENABLE_A) &&
233762306a36Sopenharmony_ci	    (tmp & DC_STUTTER_ENABLE_B))
233862306a36Sopenharmony_ci		level->mcFlags |= NISLANDS_SMC_MC_STUTTER_EN;
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_ci	if (pi->mem_gddr5) {
234162306a36Sopenharmony_ci		if (pl->mclk > pi->mclk_edc_enable_threshold)
234262306a36Sopenharmony_ci			level->mcFlags |= NISLANDS_SMC_MC_EDC_RD_FLAG;
234362306a36Sopenharmony_ci		if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold)
234462306a36Sopenharmony_ci			level->mcFlags |= NISLANDS_SMC_MC_EDC_WR_FLAG;
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci		level->strobeMode = cypress_get_strobe_mode_settings(rdev, pl->mclk);
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_ci		if (level->strobeMode & NISLANDS_SMC_STROBE_ENABLE) {
234962306a36Sopenharmony_ci			if (cypress_get_mclk_frequency_ratio(rdev, pl->mclk, true) >=
235062306a36Sopenharmony_ci			    ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf))
235162306a36Sopenharmony_ci				dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false;
235262306a36Sopenharmony_ci			else
235362306a36Sopenharmony_ci				dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false;
235462306a36Sopenharmony_ci		} else {
235562306a36Sopenharmony_ci			dll_state_on = false;
235662306a36Sopenharmony_ci			if (pl->mclk > ni_pi->mclk_rtt_mode_threshold)
235762306a36Sopenharmony_ci				level->mcFlags |= NISLANDS_SMC_MC_RTT_ENABLE;
235862306a36Sopenharmony_ci		}
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci		ret = ni_populate_mclk_value(rdev, pl->sclk, pl->mclk,
236162306a36Sopenharmony_ci					     &level->mclk,
236262306a36Sopenharmony_ci					     (level->strobeMode & NISLANDS_SMC_STROBE_ENABLE) != 0,
236362306a36Sopenharmony_ci					     dll_state_on);
236462306a36Sopenharmony_ci	} else
236562306a36Sopenharmony_ci		ret = ni_populate_mclk_value(rdev, pl->sclk, pl->mclk, &level->mclk, 1, 1);
236662306a36Sopenharmony_ci
236762306a36Sopenharmony_ci	if (ret)
236862306a36Sopenharmony_ci		return ret;
236962306a36Sopenharmony_ci
237062306a36Sopenharmony_ci	ret = ni_populate_voltage_value(rdev, &eg_pi->vddc_voltage_table,
237162306a36Sopenharmony_ci					pl->vddc, &level->vddc);
237262306a36Sopenharmony_ci	if (ret)
237362306a36Sopenharmony_ci		return ret;
237462306a36Sopenharmony_ci
237562306a36Sopenharmony_ci	ret = ni_get_std_voltage_value(rdev, &level->vddc, &std_vddc);
237662306a36Sopenharmony_ci	if (ret)
237762306a36Sopenharmony_ci		return ret;
237862306a36Sopenharmony_ci
237962306a36Sopenharmony_ci	ni_populate_std_voltage_value(rdev, std_vddc,
238062306a36Sopenharmony_ci				      level->vddc.index, &level->std_vddc);
238162306a36Sopenharmony_ci
238262306a36Sopenharmony_ci	if (eg_pi->vddci_control) {
238362306a36Sopenharmony_ci		ret = ni_populate_voltage_value(rdev, &eg_pi->vddci_voltage_table,
238462306a36Sopenharmony_ci						pl->vddci, &level->vddci);
238562306a36Sopenharmony_ci		if (ret)
238662306a36Sopenharmony_ci			return ret;
238762306a36Sopenharmony_ci	}
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	ni_populate_mvdd_value(rdev, pl->mclk, &level->mvdd);
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci	return ret;
239262306a36Sopenharmony_ci}
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_cistatic int ni_populate_smc_t(struct radeon_device *rdev,
239562306a36Sopenharmony_ci			     struct radeon_ps *radeon_state,
239662306a36Sopenharmony_ci			     NISLANDS_SMC_SWSTATE *smc_state)
239762306a36Sopenharmony_ci{
239862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
239962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
240062306a36Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
240162306a36Sopenharmony_ci	u32 a_t;
240262306a36Sopenharmony_ci	u32 t_l, t_h;
240362306a36Sopenharmony_ci	u32 high_bsp;
240462306a36Sopenharmony_ci	int i, ret;
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	if (state->performance_level_count >= 9)
240762306a36Sopenharmony_ci		return -EINVAL;
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	if (state->performance_level_count < 2) {
241062306a36Sopenharmony_ci		a_t = CG_R(0xffff) | CG_L(0);
241162306a36Sopenharmony_ci		smc_state->levels[0].aT = cpu_to_be32(a_t);
241262306a36Sopenharmony_ci		return 0;
241362306a36Sopenharmony_ci	}
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_ci	smc_state->levels[0].aT = cpu_to_be32(0);
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_ci	for (i = 0; i <= state->performance_level_count - 2; i++) {
241862306a36Sopenharmony_ci		if (eg_pi->uvd_enabled)
241962306a36Sopenharmony_ci			ret = r600_calculate_at(
242062306a36Sopenharmony_ci				1000 * (i * (eg_pi->smu_uvd_hs ? 2 : 8) + 2),
242162306a36Sopenharmony_ci				100 * R600_AH_DFLT,
242262306a36Sopenharmony_ci				state->performance_levels[i + 1].sclk,
242362306a36Sopenharmony_ci				state->performance_levels[i].sclk,
242462306a36Sopenharmony_ci				&t_l,
242562306a36Sopenharmony_ci				&t_h);
242662306a36Sopenharmony_ci		else
242762306a36Sopenharmony_ci			ret = r600_calculate_at(
242862306a36Sopenharmony_ci				1000 * (i + 1),
242962306a36Sopenharmony_ci				100 * R600_AH_DFLT,
243062306a36Sopenharmony_ci				state->performance_levels[i + 1].sclk,
243162306a36Sopenharmony_ci				state->performance_levels[i].sclk,
243262306a36Sopenharmony_ci				&t_l,
243362306a36Sopenharmony_ci				&t_h);
243462306a36Sopenharmony_ci
243562306a36Sopenharmony_ci		if (ret) {
243662306a36Sopenharmony_ci			t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT;
243762306a36Sopenharmony_ci			t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT;
243862306a36Sopenharmony_ci		}
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci		a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK;
244162306a36Sopenharmony_ci		a_t |= CG_R(t_l * pi->bsp / 20000);
244262306a36Sopenharmony_ci		smc_state->levels[i].aT = cpu_to_be32(a_t);
244362306a36Sopenharmony_ci
244462306a36Sopenharmony_ci		high_bsp = (i == state->performance_level_count - 2) ?
244562306a36Sopenharmony_ci			pi->pbsp : pi->bsp;
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci		a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000);
244862306a36Sopenharmony_ci		smc_state->levels[i + 1].aT = cpu_to_be32(a_t);
244962306a36Sopenharmony_ci	}
245062306a36Sopenharmony_ci
245162306a36Sopenharmony_ci	return 0;
245262306a36Sopenharmony_ci}
245362306a36Sopenharmony_ci
245462306a36Sopenharmony_cistatic int ni_populate_power_containment_values(struct radeon_device *rdev,
245562306a36Sopenharmony_ci						struct radeon_ps *radeon_state,
245662306a36Sopenharmony_ci						NISLANDS_SMC_SWSTATE *smc_state)
245762306a36Sopenharmony_ci{
245862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
245962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
246062306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
246162306a36Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
246262306a36Sopenharmony_ci	u32 prev_sclk;
246362306a36Sopenharmony_ci	u32 max_sclk;
246462306a36Sopenharmony_ci	u32 min_sclk;
246562306a36Sopenharmony_ci	int i, ret;
246662306a36Sopenharmony_ci	u32 tdp_limit;
246762306a36Sopenharmony_ci	u32 near_tdp_limit;
246862306a36Sopenharmony_ci	u32 power_boost_limit;
246962306a36Sopenharmony_ci	u8 max_ps_percent;
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	if (ni_pi->enable_power_containment == false)
247262306a36Sopenharmony_ci		return 0;
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	if (state->performance_level_count == 0)
247562306a36Sopenharmony_ci		return -EINVAL;
247662306a36Sopenharmony_ci
247762306a36Sopenharmony_ci	if (smc_state->levelCount != state->performance_level_count)
247862306a36Sopenharmony_ci		return -EINVAL;
247962306a36Sopenharmony_ci
248062306a36Sopenharmony_ci	ret = ni_calculate_adjusted_tdp_limits(rdev,
248162306a36Sopenharmony_ci					       false, /* ??? */
248262306a36Sopenharmony_ci					       rdev->pm.dpm.tdp_adjustment,
248362306a36Sopenharmony_ci					       &tdp_limit,
248462306a36Sopenharmony_ci					       &near_tdp_limit);
248562306a36Sopenharmony_ci	if (ret)
248662306a36Sopenharmony_ci		return ret;
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci	power_boost_limit = ni_calculate_power_boost_limit(rdev, radeon_state, near_tdp_limit);
248962306a36Sopenharmony_ci
249062306a36Sopenharmony_ci	ret = rv770_write_smc_sram_dword(rdev,
249162306a36Sopenharmony_ci					 pi->state_table_start +
249262306a36Sopenharmony_ci					 offsetof(NISLANDS_SMC_STATETABLE, dpm2Params) +
249362306a36Sopenharmony_ci					 offsetof(PP_NIslands_DPM2Parameters, PowerBoostLimit),
249462306a36Sopenharmony_ci					 ni_scale_power_for_smc(power_boost_limit, ni_get_smc_power_scaling_factor(rdev)),
249562306a36Sopenharmony_ci					 pi->sram_end);
249662306a36Sopenharmony_ci	if (ret)
249762306a36Sopenharmony_ci		power_boost_limit = 0;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	smc_state->levels[0].dpm2.MaxPS = 0;
250062306a36Sopenharmony_ci	smc_state->levels[0].dpm2.NearTDPDec = 0;
250162306a36Sopenharmony_ci	smc_state->levels[0].dpm2.AboveSafeInc = 0;
250262306a36Sopenharmony_ci	smc_state->levels[0].dpm2.BelowSafeInc = 0;
250362306a36Sopenharmony_ci	smc_state->levels[0].stateFlags |= power_boost_limit ? PPSMC_STATEFLAG_POWERBOOST : 0;
250462306a36Sopenharmony_ci
250562306a36Sopenharmony_ci	for (i = 1; i < state->performance_level_count; i++) {
250662306a36Sopenharmony_ci		prev_sclk = state->performance_levels[i-1].sclk;
250762306a36Sopenharmony_ci		max_sclk  = state->performance_levels[i].sclk;
250862306a36Sopenharmony_ci		max_ps_percent = (i != (state->performance_level_count - 1)) ?
250962306a36Sopenharmony_ci			NISLANDS_DPM2_MAXPS_PERCENT_M : NISLANDS_DPM2_MAXPS_PERCENT_H;
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ci		if (max_sclk < prev_sclk)
251262306a36Sopenharmony_ci			return -EINVAL;
251362306a36Sopenharmony_ci
251462306a36Sopenharmony_ci		if ((max_ps_percent == 0) || (prev_sclk == max_sclk) || eg_pi->uvd_enabled)
251562306a36Sopenharmony_ci			min_sclk = max_sclk;
251662306a36Sopenharmony_ci		else if (1 == i)
251762306a36Sopenharmony_ci			min_sclk = prev_sclk;
251862306a36Sopenharmony_ci		else
251962306a36Sopenharmony_ci			min_sclk = (prev_sclk * (u32)max_ps_percent) / 100;
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci		if (min_sclk < state->performance_levels[0].sclk)
252262306a36Sopenharmony_ci			min_sclk = state->performance_levels[0].sclk;
252362306a36Sopenharmony_ci
252462306a36Sopenharmony_ci		if (min_sclk == 0)
252562306a36Sopenharmony_ci			return -EINVAL;
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_ci		smc_state->levels[i].dpm2.MaxPS =
252862306a36Sopenharmony_ci			(u8)((NISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk);
252962306a36Sopenharmony_ci		smc_state->levels[i].dpm2.NearTDPDec = NISLANDS_DPM2_NEAR_TDP_DEC;
253062306a36Sopenharmony_ci		smc_state->levels[i].dpm2.AboveSafeInc = NISLANDS_DPM2_ABOVE_SAFE_INC;
253162306a36Sopenharmony_ci		smc_state->levels[i].dpm2.BelowSafeInc = NISLANDS_DPM2_BELOW_SAFE_INC;
253262306a36Sopenharmony_ci		smc_state->levels[i].stateFlags |=
253362306a36Sopenharmony_ci			((i != (state->performance_level_count - 1)) && power_boost_limit) ?
253462306a36Sopenharmony_ci			PPSMC_STATEFLAG_POWERBOOST : 0;
253562306a36Sopenharmony_ci	}
253662306a36Sopenharmony_ci
253762306a36Sopenharmony_ci	return 0;
253862306a36Sopenharmony_ci}
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_cistatic int ni_populate_sq_ramping_values(struct radeon_device *rdev,
254162306a36Sopenharmony_ci					 struct radeon_ps *radeon_state,
254262306a36Sopenharmony_ci					 NISLANDS_SMC_SWSTATE *smc_state)
254362306a36Sopenharmony_ci{
254462306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
254562306a36Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
254662306a36Sopenharmony_ci	u32 sq_power_throttle;
254762306a36Sopenharmony_ci	u32 sq_power_throttle2;
254862306a36Sopenharmony_ci	bool enable_sq_ramping = ni_pi->enable_sq_ramping;
254962306a36Sopenharmony_ci	int i;
255062306a36Sopenharmony_ci
255162306a36Sopenharmony_ci	if (state->performance_level_count == 0)
255262306a36Sopenharmony_ci		return -EINVAL;
255362306a36Sopenharmony_ci
255462306a36Sopenharmony_ci	if (smc_state->levelCount != state->performance_level_count)
255562306a36Sopenharmony_ci		return -EINVAL;
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	if (rdev->pm.dpm.sq_ramping_threshold == 0)
255862306a36Sopenharmony_ci		return -EINVAL;
255962306a36Sopenharmony_ci
256062306a36Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT))
256162306a36Sopenharmony_ci		enable_sq_ramping = false;
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT))
256462306a36Sopenharmony_ci		enable_sq_ramping = false;
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT))
256762306a36Sopenharmony_ci		enable_sq_ramping = false;
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT))
257062306a36Sopenharmony_ci		enable_sq_ramping = false;
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci	if (NISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT))
257362306a36Sopenharmony_ci		enable_sq_ramping = false;
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
257662306a36Sopenharmony_ci		sq_power_throttle  = 0;
257762306a36Sopenharmony_ci		sq_power_throttle2 = 0;
257862306a36Sopenharmony_ci
257962306a36Sopenharmony_ci		if ((state->performance_levels[i].sclk >= rdev->pm.dpm.sq_ramping_threshold) &&
258062306a36Sopenharmony_ci		    enable_sq_ramping) {
258162306a36Sopenharmony_ci			sq_power_throttle |= MAX_POWER(NISLANDS_DPM2_SQ_RAMP_MAX_POWER);
258262306a36Sopenharmony_ci			sq_power_throttle |= MIN_POWER(NISLANDS_DPM2_SQ_RAMP_MIN_POWER);
258362306a36Sopenharmony_ci			sq_power_throttle2 |= MAX_POWER_DELTA(NISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA);
258462306a36Sopenharmony_ci			sq_power_throttle2 |= STI_SIZE(NISLANDS_DPM2_SQ_RAMP_STI_SIZE);
258562306a36Sopenharmony_ci			sq_power_throttle2 |= LTI_RATIO(NISLANDS_DPM2_SQ_RAMP_LTI_RATIO);
258662306a36Sopenharmony_ci		} else {
258762306a36Sopenharmony_ci			sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK;
258862306a36Sopenharmony_ci			sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK;
258962306a36Sopenharmony_ci		}
259062306a36Sopenharmony_ci
259162306a36Sopenharmony_ci		smc_state->levels[i].SQPowerThrottle   = cpu_to_be32(sq_power_throttle);
259262306a36Sopenharmony_ci		smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2);
259362306a36Sopenharmony_ci	}
259462306a36Sopenharmony_ci
259562306a36Sopenharmony_ci	return 0;
259662306a36Sopenharmony_ci}
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_cistatic int ni_enable_power_containment(struct radeon_device *rdev,
259962306a36Sopenharmony_ci				       struct radeon_ps *radeon_new_state,
260062306a36Sopenharmony_ci				       bool enable)
260162306a36Sopenharmony_ci{
260262306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
260362306a36Sopenharmony_ci	PPSMC_Result smc_result;
260462306a36Sopenharmony_ci	int ret = 0;
260562306a36Sopenharmony_ci
260662306a36Sopenharmony_ci	if (ni_pi->enable_power_containment) {
260762306a36Sopenharmony_ci		if (enable) {
260862306a36Sopenharmony_ci			if (!r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
260962306a36Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_TDPClampingActive);
261062306a36Sopenharmony_ci				if (smc_result != PPSMC_Result_OK) {
261162306a36Sopenharmony_ci					ret = -EINVAL;
261262306a36Sopenharmony_ci					ni_pi->pc_enabled = false;
261362306a36Sopenharmony_ci				} else {
261462306a36Sopenharmony_ci					ni_pi->pc_enabled = true;
261562306a36Sopenharmony_ci				}
261662306a36Sopenharmony_ci			}
261762306a36Sopenharmony_ci		} else {
261862306a36Sopenharmony_ci			smc_result = rv770_send_msg_to_smc(rdev, PPSMC_TDPClampingInactive);
261962306a36Sopenharmony_ci			if (smc_result != PPSMC_Result_OK)
262062306a36Sopenharmony_ci				ret = -EINVAL;
262162306a36Sopenharmony_ci			ni_pi->pc_enabled = false;
262262306a36Sopenharmony_ci		}
262362306a36Sopenharmony_ci	}
262462306a36Sopenharmony_ci
262562306a36Sopenharmony_ci	return ret;
262662306a36Sopenharmony_ci}
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_cistatic int ni_convert_power_state_to_smc(struct radeon_device *rdev,
262962306a36Sopenharmony_ci					 struct radeon_ps *radeon_state,
263062306a36Sopenharmony_ci					 NISLANDS_SMC_SWSTATE *smc_state)
263162306a36Sopenharmony_ci{
263262306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
263362306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
263462306a36Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
263562306a36Sopenharmony_ci	int i, ret;
263662306a36Sopenharmony_ci	u32 threshold = state->performance_levels[state->performance_level_count - 1].sclk * 100 / 100;
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	if (!(radeon_state->caps & ATOM_PPLIB_DISALLOW_ON_DC))
263962306a36Sopenharmony_ci		smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
264062306a36Sopenharmony_ci
264162306a36Sopenharmony_ci	smc_state->levelCount = 0;
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_ci	if (state->performance_level_count > NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE)
264462306a36Sopenharmony_ci		return -EINVAL;
264562306a36Sopenharmony_ci
264662306a36Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
264762306a36Sopenharmony_ci		ret = ni_convert_power_level_to_smc(rdev, &state->performance_levels[i],
264862306a36Sopenharmony_ci						    &smc_state->levels[i]);
264962306a36Sopenharmony_ci		smc_state->levels[i].arbRefreshState =
265062306a36Sopenharmony_ci			(u8)(NISLANDS_DRIVER_STATE_ARB_INDEX + i);
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci		if (ret)
265362306a36Sopenharmony_ci			return ret;
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci		if (ni_pi->enable_power_containment)
265662306a36Sopenharmony_ci			smc_state->levels[i].displayWatermark =
265762306a36Sopenharmony_ci				(state->performance_levels[i].sclk < threshold) ?
265862306a36Sopenharmony_ci				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
265962306a36Sopenharmony_ci		else
266062306a36Sopenharmony_ci			smc_state->levels[i].displayWatermark = (i < 2) ?
266162306a36Sopenharmony_ci				PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH;
266262306a36Sopenharmony_ci
266362306a36Sopenharmony_ci		if (eg_pi->dynamic_ac_timing)
266462306a36Sopenharmony_ci			smc_state->levels[i].ACIndex = NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i;
266562306a36Sopenharmony_ci		else
266662306a36Sopenharmony_ci			smc_state->levels[i].ACIndex = 0;
266762306a36Sopenharmony_ci
266862306a36Sopenharmony_ci		smc_state->levelCount++;
266962306a36Sopenharmony_ci	}
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_watermark_threshold,
267262306a36Sopenharmony_ci				      cpu_to_be32(threshold / 512));
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci	ni_populate_smc_sp(rdev, radeon_state, smc_state);
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	ret = ni_populate_power_containment_values(rdev, radeon_state, smc_state);
267762306a36Sopenharmony_ci	if (ret)
267862306a36Sopenharmony_ci		ni_pi->enable_power_containment = false;
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_ci	ret = ni_populate_sq_ramping_values(rdev, radeon_state, smc_state);
268162306a36Sopenharmony_ci	if (ret)
268262306a36Sopenharmony_ci		ni_pi->enable_sq_ramping = false;
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	return ni_populate_smc_t(rdev, radeon_state, smc_state);
268562306a36Sopenharmony_ci}
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_cistatic int ni_upload_sw_state(struct radeon_device *rdev,
268862306a36Sopenharmony_ci			      struct radeon_ps *radeon_new_state)
268962306a36Sopenharmony_ci{
269062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
269162306a36Sopenharmony_ci	u16 address = pi->state_table_start +
269262306a36Sopenharmony_ci		offsetof(NISLANDS_SMC_STATETABLE, driverState);
269362306a36Sopenharmony_ci	NISLANDS_SMC_SWSTATE *smc_state;
269462306a36Sopenharmony_ci	size_t state_size = struct_size(smc_state, levels,
269562306a36Sopenharmony_ci			NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE);
269662306a36Sopenharmony_ci	int ret;
269762306a36Sopenharmony_ci
269862306a36Sopenharmony_ci	smc_state = kzalloc(state_size, GFP_KERNEL);
269962306a36Sopenharmony_ci	if (smc_state == NULL)
270062306a36Sopenharmony_ci		return -ENOMEM;
270162306a36Sopenharmony_ci
270262306a36Sopenharmony_ci	ret = ni_convert_power_state_to_smc(rdev, radeon_new_state, smc_state);
270362306a36Sopenharmony_ci	if (ret)
270462306a36Sopenharmony_ci		goto done;
270562306a36Sopenharmony_ci
270662306a36Sopenharmony_ci	ret = rv770_copy_bytes_to_smc(rdev, address, (u8 *)smc_state, state_size, pi->sram_end);
270762306a36Sopenharmony_ci
270862306a36Sopenharmony_cidone:
270962306a36Sopenharmony_ci	kfree(smc_state);
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci	return ret;
271262306a36Sopenharmony_ci}
271362306a36Sopenharmony_ci
271462306a36Sopenharmony_cistatic int ni_set_mc_special_registers(struct radeon_device *rdev,
271562306a36Sopenharmony_ci				       struct ni_mc_reg_table *table)
271662306a36Sopenharmony_ci{
271762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
271862306a36Sopenharmony_ci	u8 i, j, k;
271962306a36Sopenharmony_ci	u32 temp_reg;
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_ci	for (i = 0, j = table->last; i < table->last; i++) {
272262306a36Sopenharmony_ci		switch (table->mc_reg_address[i].s1) {
272362306a36Sopenharmony_ci		case MC_SEQ_MISC1 >> 2:
272462306a36Sopenharmony_ci			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
272562306a36Sopenharmony_ci				return -EINVAL;
272662306a36Sopenharmony_ci			temp_reg = RREG32(MC_PMG_CMD_EMRS);
272762306a36Sopenharmony_ci			table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS >> 2;
272862306a36Sopenharmony_ci			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
272962306a36Sopenharmony_ci			for (k = 0; k < table->num_entries; k++)
273062306a36Sopenharmony_ci				table->mc_reg_table_entry[k].mc_data[j] =
273162306a36Sopenharmony_ci					((temp_reg & 0xffff0000)) |
273262306a36Sopenharmony_ci					((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16);
273362306a36Sopenharmony_ci			j++;
273462306a36Sopenharmony_ci			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
273562306a36Sopenharmony_ci				return -EINVAL;
273662306a36Sopenharmony_ci
273762306a36Sopenharmony_ci			temp_reg = RREG32(MC_PMG_CMD_MRS);
273862306a36Sopenharmony_ci			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS >> 2;
273962306a36Sopenharmony_ci			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP >> 2;
274062306a36Sopenharmony_ci			for(k = 0; k < table->num_entries; k++) {
274162306a36Sopenharmony_ci				table->mc_reg_table_entry[k].mc_data[j] =
274262306a36Sopenharmony_ci					(temp_reg & 0xffff0000) |
274362306a36Sopenharmony_ci					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
274462306a36Sopenharmony_ci				if (!pi->mem_gddr5)
274562306a36Sopenharmony_ci					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
274662306a36Sopenharmony_ci			}
274762306a36Sopenharmony_ci			j++;
274862306a36Sopenharmony_ci			break;
274962306a36Sopenharmony_ci		case MC_SEQ_RESERVE_M >> 2:
275062306a36Sopenharmony_ci			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
275162306a36Sopenharmony_ci				return -EINVAL;
275262306a36Sopenharmony_ci			temp_reg = RREG32(MC_PMG_CMD_MRS1);
275362306a36Sopenharmony_ci			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1 >> 2;
275462306a36Sopenharmony_ci			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
275562306a36Sopenharmony_ci			for (k = 0; k < table->num_entries; k++)
275662306a36Sopenharmony_ci				table->mc_reg_table_entry[k].mc_data[j] =
275762306a36Sopenharmony_ci					(temp_reg & 0xffff0000) |
275862306a36Sopenharmony_ci					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
275962306a36Sopenharmony_ci			j++;
276062306a36Sopenharmony_ci			break;
276162306a36Sopenharmony_ci		default:
276262306a36Sopenharmony_ci			break;
276362306a36Sopenharmony_ci		}
276462306a36Sopenharmony_ci	}
276562306a36Sopenharmony_ci
276662306a36Sopenharmony_ci	table->last = j;
276762306a36Sopenharmony_ci
276862306a36Sopenharmony_ci	return 0;
276962306a36Sopenharmony_ci}
277062306a36Sopenharmony_ci
277162306a36Sopenharmony_cistatic bool ni_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg)
277262306a36Sopenharmony_ci{
277362306a36Sopenharmony_ci	bool result = true;
277462306a36Sopenharmony_ci
277562306a36Sopenharmony_ci	switch (in_reg) {
277662306a36Sopenharmony_ci	case  MC_SEQ_RAS_TIMING >> 2:
277762306a36Sopenharmony_ci		*out_reg = MC_SEQ_RAS_TIMING_LP >> 2;
277862306a36Sopenharmony_ci		break;
277962306a36Sopenharmony_ci	case MC_SEQ_CAS_TIMING >> 2:
278062306a36Sopenharmony_ci		*out_reg = MC_SEQ_CAS_TIMING_LP >> 2;
278162306a36Sopenharmony_ci		break;
278262306a36Sopenharmony_ci	case MC_SEQ_MISC_TIMING >> 2:
278362306a36Sopenharmony_ci		*out_reg = MC_SEQ_MISC_TIMING_LP >> 2;
278462306a36Sopenharmony_ci		break;
278562306a36Sopenharmony_ci	case MC_SEQ_MISC_TIMING2 >> 2:
278662306a36Sopenharmony_ci		*out_reg = MC_SEQ_MISC_TIMING2_LP >> 2;
278762306a36Sopenharmony_ci		break;
278862306a36Sopenharmony_ci	case MC_SEQ_RD_CTL_D0 >> 2:
278962306a36Sopenharmony_ci		*out_reg = MC_SEQ_RD_CTL_D0_LP >> 2;
279062306a36Sopenharmony_ci		break;
279162306a36Sopenharmony_ci	case MC_SEQ_RD_CTL_D1 >> 2:
279262306a36Sopenharmony_ci		*out_reg = MC_SEQ_RD_CTL_D1_LP >> 2;
279362306a36Sopenharmony_ci		break;
279462306a36Sopenharmony_ci	case MC_SEQ_WR_CTL_D0 >> 2:
279562306a36Sopenharmony_ci		*out_reg = MC_SEQ_WR_CTL_D0_LP >> 2;
279662306a36Sopenharmony_ci		break;
279762306a36Sopenharmony_ci	case MC_SEQ_WR_CTL_D1 >> 2:
279862306a36Sopenharmony_ci		*out_reg = MC_SEQ_WR_CTL_D1_LP >> 2;
279962306a36Sopenharmony_ci		break;
280062306a36Sopenharmony_ci	case MC_PMG_CMD_EMRS >> 2:
280162306a36Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_EMRS_LP >> 2;
280262306a36Sopenharmony_ci		break;
280362306a36Sopenharmony_ci	case MC_PMG_CMD_MRS >> 2:
280462306a36Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_MRS_LP >> 2;
280562306a36Sopenharmony_ci		break;
280662306a36Sopenharmony_ci	case MC_PMG_CMD_MRS1 >> 2:
280762306a36Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
280862306a36Sopenharmony_ci		break;
280962306a36Sopenharmony_ci	case MC_SEQ_PMG_TIMING >> 2:
281062306a36Sopenharmony_ci		*out_reg = MC_SEQ_PMG_TIMING_LP >> 2;
281162306a36Sopenharmony_ci		break;
281262306a36Sopenharmony_ci	case MC_PMG_CMD_MRS2 >> 2:
281362306a36Sopenharmony_ci		*out_reg = MC_SEQ_PMG_CMD_MRS2_LP >> 2;
281462306a36Sopenharmony_ci		break;
281562306a36Sopenharmony_ci	default:
281662306a36Sopenharmony_ci		result = false;
281762306a36Sopenharmony_ci		break;
281862306a36Sopenharmony_ci	}
281962306a36Sopenharmony_ci
282062306a36Sopenharmony_ci	return result;
282162306a36Sopenharmony_ci}
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_cistatic void ni_set_valid_flag(struct ni_mc_reg_table *table)
282462306a36Sopenharmony_ci{
282562306a36Sopenharmony_ci	u8 i, j;
282662306a36Sopenharmony_ci
282762306a36Sopenharmony_ci	for (i = 0; i < table->last; i++) {
282862306a36Sopenharmony_ci		for (j = 1; j < table->num_entries; j++) {
282962306a36Sopenharmony_ci			if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) {
283062306a36Sopenharmony_ci				table->valid_flag |= 1 << i;
283162306a36Sopenharmony_ci				break;
283262306a36Sopenharmony_ci			}
283362306a36Sopenharmony_ci		}
283462306a36Sopenharmony_ci	}
283562306a36Sopenharmony_ci}
283662306a36Sopenharmony_ci
283762306a36Sopenharmony_cistatic void ni_set_s0_mc_reg_index(struct ni_mc_reg_table *table)
283862306a36Sopenharmony_ci{
283962306a36Sopenharmony_ci	u32 i;
284062306a36Sopenharmony_ci	u16 address;
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci	for (i = 0; i < table->last; i++)
284362306a36Sopenharmony_ci		table->mc_reg_address[i].s0 =
284462306a36Sopenharmony_ci			ni_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ?
284562306a36Sopenharmony_ci			address : table->mc_reg_address[i].s1;
284662306a36Sopenharmony_ci}
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_cistatic int ni_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table,
284962306a36Sopenharmony_ci				      struct ni_mc_reg_table *ni_table)
285062306a36Sopenharmony_ci{
285162306a36Sopenharmony_ci	u8 i, j;
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	if (table->last > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
285462306a36Sopenharmony_ci		return -EINVAL;
285562306a36Sopenharmony_ci	if (table->num_entries > MAX_AC_TIMING_ENTRIES)
285662306a36Sopenharmony_ci		return -EINVAL;
285762306a36Sopenharmony_ci
285862306a36Sopenharmony_ci	for (i = 0; i < table->last; i++)
285962306a36Sopenharmony_ci		ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1;
286062306a36Sopenharmony_ci	ni_table->last = table->last;
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_ci	for (i = 0; i < table->num_entries; i++) {
286362306a36Sopenharmony_ci		ni_table->mc_reg_table_entry[i].mclk_max =
286462306a36Sopenharmony_ci			table->mc_reg_table_entry[i].mclk_max;
286562306a36Sopenharmony_ci		for (j = 0; j < table->last; j++)
286662306a36Sopenharmony_ci			ni_table->mc_reg_table_entry[i].mc_data[j] =
286762306a36Sopenharmony_ci				table->mc_reg_table_entry[i].mc_data[j];
286862306a36Sopenharmony_ci	}
286962306a36Sopenharmony_ci	ni_table->num_entries = table->num_entries;
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci	return 0;
287262306a36Sopenharmony_ci}
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_cistatic int ni_initialize_mc_reg_table(struct radeon_device *rdev)
287562306a36Sopenharmony_ci{
287662306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
287762306a36Sopenharmony_ci	int ret;
287862306a36Sopenharmony_ci	struct atom_mc_reg_table *table;
287962306a36Sopenharmony_ci	struct ni_mc_reg_table *ni_table = &ni_pi->mc_reg_table;
288062306a36Sopenharmony_ci	u8 module_index = rv770_get_memory_module_index(rdev);
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_ci	table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL);
288362306a36Sopenharmony_ci	if (!table)
288462306a36Sopenharmony_ci		return -ENOMEM;
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci	WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING));
288762306a36Sopenharmony_ci	WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING));
288862306a36Sopenharmony_ci	WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING));
288962306a36Sopenharmony_ci	WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2));
289062306a36Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS));
289162306a36Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS));
289262306a36Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1));
289362306a36Sopenharmony_ci	WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0));
289462306a36Sopenharmony_ci	WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1));
289562306a36Sopenharmony_ci	WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0));
289662306a36Sopenharmony_ci	WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1));
289762306a36Sopenharmony_ci	WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING));
289862306a36Sopenharmony_ci	WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2));
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci	ret = radeon_atom_init_mc_reg_table(rdev, module_index, table);
290162306a36Sopenharmony_ci
290262306a36Sopenharmony_ci	if (ret)
290362306a36Sopenharmony_ci		goto init_mc_done;
290462306a36Sopenharmony_ci
290562306a36Sopenharmony_ci	ret = ni_copy_vbios_mc_reg_table(table, ni_table);
290662306a36Sopenharmony_ci
290762306a36Sopenharmony_ci	if (ret)
290862306a36Sopenharmony_ci		goto init_mc_done;
290962306a36Sopenharmony_ci
291062306a36Sopenharmony_ci	ni_set_s0_mc_reg_index(ni_table);
291162306a36Sopenharmony_ci
291262306a36Sopenharmony_ci	ret = ni_set_mc_special_registers(rdev, ni_table);
291362306a36Sopenharmony_ci
291462306a36Sopenharmony_ci	if (ret)
291562306a36Sopenharmony_ci		goto init_mc_done;
291662306a36Sopenharmony_ci
291762306a36Sopenharmony_ci	ni_set_valid_flag(ni_table);
291862306a36Sopenharmony_ci
291962306a36Sopenharmony_ciinit_mc_done:
292062306a36Sopenharmony_ci	kfree(table);
292162306a36Sopenharmony_ci
292262306a36Sopenharmony_ci	return ret;
292362306a36Sopenharmony_ci}
292462306a36Sopenharmony_ci
292562306a36Sopenharmony_cistatic void ni_populate_mc_reg_addresses(struct radeon_device *rdev,
292662306a36Sopenharmony_ci					 SMC_NIslands_MCRegisters *mc_reg_table)
292762306a36Sopenharmony_ci{
292862306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
292962306a36Sopenharmony_ci	u32 i, j;
293062306a36Sopenharmony_ci
293162306a36Sopenharmony_ci	for (i = 0, j = 0; j < ni_pi->mc_reg_table.last; j++) {
293262306a36Sopenharmony_ci		if (ni_pi->mc_reg_table.valid_flag & (1 << j)) {
293362306a36Sopenharmony_ci			if (i >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
293462306a36Sopenharmony_ci				break;
293562306a36Sopenharmony_ci			mc_reg_table->address[i].s0 =
293662306a36Sopenharmony_ci				cpu_to_be16(ni_pi->mc_reg_table.mc_reg_address[j].s0);
293762306a36Sopenharmony_ci			mc_reg_table->address[i].s1 =
293862306a36Sopenharmony_ci				cpu_to_be16(ni_pi->mc_reg_table.mc_reg_address[j].s1);
293962306a36Sopenharmony_ci			i++;
294062306a36Sopenharmony_ci		}
294162306a36Sopenharmony_ci	}
294262306a36Sopenharmony_ci	mc_reg_table->last = (u8)i;
294362306a36Sopenharmony_ci}
294462306a36Sopenharmony_ci
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_cistatic void ni_convert_mc_registers(struct ni_mc_reg_entry *entry,
294762306a36Sopenharmony_ci				    SMC_NIslands_MCRegisterSet *data,
294862306a36Sopenharmony_ci				    u32 num_entries, u32 valid_flag)
294962306a36Sopenharmony_ci{
295062306a36Sopenharmony_ci	u32 i, j;
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_ci	for (i = 0, j = 0; j < num_entries; j++) {
295362306a36Sopenharmony_ci		if (valid_flag & (1 << j)) {
295462306a36Sopenharmony_ci			data->value[i] = cpu_to_be32(entry->mc_data[j]);
295562306a36Sopenharmony_ci			i++;
295662306a36Sopenharmony_ci		}
295762306a36Sopenharmony_ci	}
295862306a36Sopenharmony_ci}
295962306a36Sopenharmony_ci
296062306a36Sopenharmony_cistatic void ni_convert_mc_reg_table_entry_to_smc(struct radeon_device *rdev,
296162306a36Sopenharmony_ci						 struct rv7xx_pl *pl,
296262306a36Sopenharmony_ci						 SMC_NIslands_MCRegisterSet *mc_reg_table_data)
296362306a36Sopenharmony_ci{
296462306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
296562306a36Sopenharmony_ci	u32 i = 0;
296662306a36Sopenharmony_ci
296762306a36Sopenharmony_ci	for (i = 0; i < ni_pi->mc_reg_table.num_entries; i++) {
296862306a36Sopenharmony_ci		if (pl->mclk <= ni_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max)
296962306a36Sopenharmony_ci			break;
297062306a36Sopenharmony_ci	}
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci	if ((i == ni_pi->mc_reg_table.num_entries) && (i > 0))
297362306a36Sopenharmony_ci		--i;
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci	ni_convert_mc_registers(&ni_pi->mc_reg_table.mc_reg_table_entry[i],
297662306a36Sopenharmony_ci				mc_reg_table_data,
297762306a36Sopenharmony_ci				ni_pi->mc_reg_table.last,
297862306a36Sopenharmony_ci				ni_pi->mc_reg_table.valid_flag);
297962306a36Sopenharmony_ci}
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_cistatic void ni_convert_mc_reg_table_to_smc(struct radeon_device *rdev,
298262306a36Sopenharmony_ci					   struct radeon_ps *radeon_state,
298362306a36Sopenharmony_ci					   SMC_NIslands_MCRegisters *mc_reg_table)
298462306a36Sopenharmony_ci{
298562306a36Sopenharmony_ci	struct ni_ps *state = ni_get_ps(radeon_state);
298662306a36Sopenharmony_ci	int i;
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_ci	for (i = 0; i < state->performance_level_count; i++) {
298962306a36Sopenharmony_ci		ni_convert_mc_reg_table_entry_to_smc(rdev,
299062306a36Sopenharmony_ci						     &state->performance_levels[i],
299162306a36Sopenharmony_ci						     &mc_reg_table->data[NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]);
299262306a36Sopenharmony_ci	}
299362306a36Sopenharmony_ci}
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_cistatic int ni_populate_mc_reg_table(struct radeon_device *rdev,
299662306a36Sopenharmony_ci				    struct radeon_ps *radeon_boot_state)
299762306a36Sopenharmony_ci{
299862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
299962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
300062306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
300162306a36Sopenharmony_ci	struct ni_ps *boot_state = ni_get_ps(radeon_boot_state);
300262306a36Sopenharmony_ci	SMC_NIslands_MCRegisters *mc_reg_table = &ni_pi->smc_mc_reg_table;
300362306a36Sopenharmony_ci
300462306a36Sopenharmony_ci	memset(mc_reg_table, 0, sizeof(SMC_NIslands_MCRegisters));
300562306a36Sopenharmony_ci
300662306a36Sopenharmony_ci	rv770_write_smc_soft_register(rdev, NI_SMC_SOFT_REGISTER_seq_index, 1);
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci	ni_populate_mc_reg_addresses(rdev, mc_reg_table);
300962306a36Sopenharmony_ci
301062306a36Sopenharmony_ci	ni_convert_mc_reg_table_entry_to_smc(rdev, &boot_state->performance_levels[0],
301162306a36Sopenharmony_ci					     &mc_reg_table->data[0]);
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_ci	ni_convert_mc_registers(&ni_pi->mc_reg_table.mc_reg_table_entry[0],
301462306a36Sopenharmony_ci				&mc_reg_table->data[1],
301562306a36Sopenharmony_ci				ni_pi->mc_reg_table.last,
301662306a36Sopenharmony_ci				ni_pi->mc_reg_table.valid_flag);
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci	ni_convert_mc_reg_table_to_smc(rdev, radeon_boot_state, mc_reg_table);
301962306a36Sopenharmony_ci
302062306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, eg_pi->mc_reg_table_start,
302162306a36Sopenharmony_ci				       (u8 *)mc_reg_table,
302262306a36Sopenharmony_ci				       sizeof(SMC_NIslands_MCRegisters),
302362306a36Sopenharmony_ci				       pi->sram_end);
302462306a36Sopenharmony_ci}
302562306a36Sopenharmony_ci
302662306a36Sopenharmony_cistatic int ni_upload_mc_reg_table(struct radeon_device *rdev,
302762306a36Sopenharmony_ci				  struct radeon_ps *radeon_new_state)
302862306a36Sopenharmony_ci{
302962306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
303062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
303162306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
303262306a36Sopenharmony_ci	struct ni_ps *ni_new_state = ni_get_ps(radeon_new_state);
303362306a36Sopenharmony_ci	SMC_NIslands_MCRegisters *mc_reg_table = &ni_pi->smc_mc_reg_table;
303462306a36Sopenharmony_ci	u16 address;
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	memset(mc_reg_table, 0, sizeof(SMC_NIslands_MCRegisters));
303762306a36Sopenharmony_ci
303862306a36Sopenharmony_ci	ni_convert_mc_reg_table_to_smc(rdev, radeon_new_state, mc_reg_table);
303962306a36Sopenharmony_ci
304062306a36Sopenharmony_ci	address = eg_pi->mc_reg_table_start +
304162306a36Sopenharmony_ci		(u16)offsetof(SMC_NIslands_MCRegisters, data[NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]);
304262306a36Sopenharmony_ci
304362306a36Sopenharmony_ci	return rv770_copy_bytes_to_smc(rdev, address,
304462306a36Sopenharmony_ci				       (u8 *)&mc_reg_table->data[NISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT],
304562306a36Sopenharmony_ci				       sizeof(SMC_NIslands_MCRegisterSet) * ni_new_state->performance_level_count,
304662306a36Sopenharmony_ci				       pi->sram_end);
304762306a36Sopenharmony_ci}
304862306a36Sopenharmony_ci
304962306a36Sopenharmony_cistatic int ni_init_driver_calculated_leakage_table(struct radeon_device *rdev,
305062306a36Sopenharmony_ci						   PP_NIslands_CACTABLES *cac_tables)
305162306a36Sopenharmony_ci{
305262306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
305362306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
305462306a36Sopenharmony_ci	u32 leakage = 0;
305562306a36Sopenharmony_ci	unsigned int i, j, table_size;
305662306a36Sopenharmony_ci	s32 t;
305762306a36Sopenharmony_ci	u32 smc_leakage, max_leakage = 0;
305862306a36Sopenharmony_ci	u32 scaling_factor;
305962306a36Sopenharmony_ci
306062306a36Sopenharmony_ci	table_size = eg_pi->vddc_voltage_table.count;
306162306a36Sopenharmony_ci
306262306a36Sopenharmony_ci	if (SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES < table_size)
306362306a36Sopenharmony_ci		table_size = SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES;
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_ci	scaling_factor = ni_get_smc_power_scaling_factor(rdev);
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_ci	for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++) {
306862306a36Sopenharmony_ci		for (j = 0; j < table_size; j++) {
306962306a36Sopenharmony_ci			t = (1000 * ((i + 1) * 8));
307062306a36Sopenharmony_ci
307162306a36Sopenharmony_ci			if (t < ni_pi->cac_data.leakage_minimum_temperature)
307262306a36Sopenharmony_ci				t = ni_pi->cac_data.leakage_minimum_temperature;
307362306a36Sopenharmony_ci
307462306a36Sopenharmony_ci			ni_calculate_leakage_for_v_and_t(rdev,
307562306a36Sopenharmony_ci							 &ni_pi->cac_data.leakage_coefficients,
307662306a36Sopenharmony_ci							 eg_pi->vddc_voltage_table.entries[j].value,
307762306a36Sopenharmony_ci							 t,
307862306a36Sopenharmony_ci							 ni_pi->cac_data.i_leakage,
307962306a36Sopenharmony_ci							 &leakage);
308062306a36Sopenharmony_ci
308162306a36Sopenharmony_ci			smc_leakage = ni_scale_power_for_smc(leakage, scaling_factor) / 1000;
308262306a36Sopenharmony_ci			if (smc_leakage > max_leakage)
308362306a36Sopenharmony_ci				max_leakage = smc_leakage;
308462306a36Sopenharmony_ci
308562306a36Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] = cpu_to_be32(smc_leakage);
308662306a36Sopenharmony_ci		}
308762306a36Sopenharmony_ci	}
308862306a36Sopenharmony_ci
308962306a36Sopenharmony_ci	for (j = table_size; j < SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
309062306a36Sopenharmony_ci		for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++)
309162306a36Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] = cpu_to_be32(max_leakage);
309262306a36Sopenharmony_ci	}
309362306a36Sopenharmony_ci	return 0;
309462306a36Sopenharmony_ci}
309562306a36Sopenharmony_ci
309662306a36Sopenharmony_cistatic int ni_init_simplified_leakage_table(struct radeon_device *rdev,
309762306a36Sopenharmony_ci					    PP_NIslands_CACTABLES *cac_tables)
309862306a36Sopenharmony_ci{
309962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
310062306a36Sopenharmony_ci	struct radeon_cac_leakage_table *leakage_table =
310162306a36Sopenharmony_ci		&rdev->pm.dpm.dyn_state.cac_leakage_table;
310262306a36Sopenharmony_ci	u32 i, j, table_size;
310362306a36Sopenharmony_ci	u32 smc_leakage, max_leakage = 0;
310462306a36Sopenharmony_ci	u32 scaling_factor;
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	if (!leakage_table)
310762306a36Sopenharmony_ci		return -EINVAL;
310862306a36Sopenharmony_ci
310962306a36Sopenharmony_ci	table_size = leakage_table->count;
311062306a36Sopenharmony_ci
311162306a36Sopenharmony_ci	if (eg_pi->vddc_voltage_table.count != table_size)
311262306a36Sopenharmony_ci		table_size = (eg_pi->vddc_voltage_table.count < leakage_table->count) ?
311362306a36Sopenharmony_ci			eg_pi->vddc_voltage_table.count : leakage_table->count;
311462306a36Sopenharmony_ci
311562306a36Sopenharmony_ci	if (SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES < table_size)
311662306a36Sopenharmony_ci		table_size = SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES;
311762306a36Sopenharmony_ci
311862306a36Sopenharmony_ci	if (table_size == 0)
311962306a36Sopenharmony_ci		return -EINVAL;
312062306a36Sopenharmony_ci
312162306a36Sopenharmony_ci	scaling_factor = ni_get_smc_power_scaling_factor(rdev);
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	for (j = 0; j < table_size; j++) {
312462306a36Sopenharmony_ci		smc_leakage = leakage_table->entries[j].leakage;
312562306a36Sopenharmony_ci
312662306a36Sopenharmony_ci		if (smc_leakage > max_leakage)
312762306a36Sopenharmony_ci			max_leakage = smc_leakage;
312862306a36Sopenharmony_ci
312962306a36Sopenharmony_ci		for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++)
313062306a36Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] =
313162306a36Sopenharmony_ci				cpu_to_be32(ni_scale_power_for_smc(smc_leakage, scaling_factor));
313262306a36Sopenharmony_ci	}
313362306a36Sopenharmony_ci
313462306a36Sopenharmony_ci	for (j = table_size; j < SMC_NISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) {
313562306a36Sopenharmony_ci		for (i = 0; i < SMC_NISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES; i++)
313662306a36Sopenharmony_ci			cac_tables->cac_lkge_lut[i][j] =
313762306a36Sopenharmony_ci				cpu_to_be32(ni_scale_power_for_smc(max_leakage, scaling_factor));
313862306a36Sopenharmony_ci	}
313962306a36Sopenharmony_ci	return 0;
314062306a36Sopenharmony_ci}
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_cistatic int ni_initialize_smc_cac_tables(struct radeon_device *rdev)
314362306a36Sopenharmony_ci{
314462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
314562306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
314662306a36Sopenharmony_ci	PP_NIslands_CACTABLES *cac_tables = NULL;
314762306a36Sopenharmony_ci	int i, ret;
314862306a36Sopenharmony_ci	u32 reg;
314962306a36Sopenharmony_ci
315062306a36Sopenharmony_ci	if (ni_pi->enable_cac == false)
315162306a36Sopenharmony_ci		return 0;
315262306a36Sopenharmony_ci
315362306a36Sopenharmony_ci	cac_tables = kzalloc(sizeof(PP_NIslands_CACTABLES), GFP_KERNEL);
315462306a36Sopenharmony_ci	if (!cac_tables)
315562306a36Sopenharmony_ci		return -ENOMEM;
315662306a36Sopenharmony_ci
315762306a36Sopenharmony_ci	reg = RREG32(CG_CAC_CTRL) & ~(TID_CNT_MASK | TID_UNIT_MASK);
315862306a36Sopenharmony_ci	reg |= (TID_CNT(ni_pi->cac_weights->tid_cnt) |
315962306a36Sopenharmony_ci		TID_UNIT(ni_pi->cac_weights->tid_unit));
316062306a36Sopenharmony_ci	WREG32(CG_CAC_CTRL, reg);
316162306a36Sopenharmony_ci
316262306a36Sopenharmony_ci	for (i = 0; i < NISLANDS_DCCAC_MAX_LEVELS; i++)
316362306a36Sopenharmony_ci		ni_pi->dc_cac_table[i] = ni_pi->cac_weights->dc_cac[i];
316462306a36Sopenharmony_ci
316562306a36Sopenharmony_ci	for (i = 0; i < SMC_NISLANDS_BIF_LUT_NUM_OF_ENTRIES; i++)
316662306a36Sopenharmony_ci		cac_tables->cac_bif_lut[i] = ni_pi->cac_weights->pcie_cac[i];
316762306a36Sopenharmony_ci
316862306a36Sopenharmony_ci	ni_pi->cac_data.i_leakage = rdev->pm.dpm.cac_leakage;
316962306a36Sopenharmony_ci	ni_pi->cac_data.pwr_const = 0;
317062306a36Sopenharmony_ci	ni_pi->cac_data.dc_cac_value = ni_pi->dc_cac_table[NISLANDS_DCCAC_LEVEL_0];
317162306a36Sopenharmony_ci	ni_pi->cac_data.bif_cac_value = 0;
317262306a36Sopenharmony_ci	ni_pi->cac_data.mc_wr_weight = ni_pi->cac_weights->mc_write_weight;
317362306a36Sopenharmony_ci	ni_pi->cac_data.mc_rd_weight = ni_pi->cac_weights->mc_read_weight;
317462306a36Sopenharmony_ci	ni_pi->cac_data.allow_ovrflw = 0;
317562306a36Sopenharmony_ci	ni_pi->cac_data.l2num_win_tdp = ni_pi->lta_window_size;
317662306a36Sopenharmony_ci	ni_pi->cac_data.num_win_tdp = 0;
317762306a36Sopenharmony_ci	ni_pi->cac_data.lts_truncate_n = ni_pi->lts_truncate;
317862306a36Sopenharmony_ci
317962306a36Sopenharmony_ci	if (ni_pi->driver_calculate_cac_leakage)
318062306a36Sopenharmony_ci		ret = ni_init_driver_calculated_leakage_table(rdev, cac_tables);
318162306a36Sopenharmony_ci	else
318262306a36Sopenharmony_ci		ret = ni_init_simplified_leakage_table(rdev, cac_tables);
318362306a36Sopenharmony_ci
318462306a36Sopenharmony_ci	if (ret)
318562306a36Sopenharmony_ci		goto done_free;
318662306a36Sopenharmony_ci
318762306a36Sopenharmony_ci	cac_tables->pwr_const      = cpu_to_be32(ni_pi->cac_data.pwr_const);
318862306a36Sopenharmony_ci	cac_tables->dc_cacValue    = cpu_to_be32(ni_pi->cac_data.dc_cac_value);
318962306a36Sopenharmony_ci	cac_tables->bif_cacValue   = cpu_to_be32(ni_pi->cac_data.bif_cac_value);
319062306a36Sopenharmony_ci	cac_tables->AllowOvrflw    = ni_pi->cac_data.allow_ovrflw;
319162306a36Sopenharmony_ci	cac_tables->MCWrWeight     = ni_pi->cac_data.mc_wr_weight;
319262306a36Sopenharmony_ci	cac_tables->MCRdWeight     = ni_pi->cac_data.mc_rd_weight;
319362306a36Sopenharmony_ci	cac_tables->numWin_TDP     = ni_pi->cac_data.num_win_tdp;
319462306a36Sopenharmony_ci	cac_tables->l2numWin_TDP   = ni_pi->cac_data.l2num_win_tdp;
319562306a36Sopenharmony_ci	cac_tables->lts_truncate_n = ni_pi->cac_data.lts_truncate_n;
319662306a36Sopenharmony_ci
319762306a36Sopenharmony_ci	ret = rv770_copy_bytes_to_smc(rdev, ni_pi->cac_table_start, (u8 *)cac_tables,
319862306a36Sopenharmony_ci				      sizeof(PP_NIslands_CACTABLES), pi->sram_end);
319962306a36Sopenharmony_ci
320062306a36Sopenharmony_cidone_free:
320162306a36Sopenharmony_ci	if (ret) {
320262306a36Sopenharmony_ci		ni_pi->enable_cac = false;
320362306a36Sopenharmony_ci		ni_pi->enable_power_containment = false;
320462306a36Sopenharmony_ci	}
320562306a36Sopenharmony_ci
320662306a36Sopenharmony_ci	kfree(cac_tables);
320762306a36Sopenharmony_ci
320862306a36Sopenharmony_ci	return 0;
320962306a36Sopenharmony_ci}
321062306a36Sopenharmony_ci
321162306a36Sopenharmony_cistatic int ni_initialize_hardware_cac_manager(struct radeon_device *rdev)
321262306a36Sopenharmony_ci{
321362306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
321462306a36Sopenharmony_ci	u32 reg;
321562306a36Sopenharmony_ci
321662306a36Sopenharmony_ci	if (!ni_pi->enable_cac ||
321762306a36Sopenharmony_ci	    !ni_pi->cac_configuration_required)
321862306a36Sopenharmony_ci		return 0;
321962306a36Sopenharmony_ci
322062306a36Sopenharmony_ci	if (ni_pi->cac_weights == NULL)
322162306a36Sopenharmony_ci		return -EINVAL;
322262306a36Sopenharmony_ci
322362306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_1_WEIGHT_0) & ~(WEIGHT_TCP_SIG0_MASK |
322462306a36Sopenharmony_ci						      WEIGHT_TCP_SIG1_MASK |
322562306a36Sopenharmony_ci						      WEIGHT_TA_SIG_MASK);
322662306a36Sopenharmony_ci	reg |= (WEIGHT_TCP_SIG0(ni_pi->cac_weights->weight_tcp_sig0) |
322762306a36Sopenharmony_ci		WEIGHT_TCP_SIG1(ni_pi->cac_weights->weight_tcp_sig1) |
322862306a36Sopenharmony_ci		WEIGHT_TA_SIG(ni_pi->cac_weights->weight_ta_sig));
322962306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_1_WEIGHT_0, reg);
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_1_WEIGHT_1) & ~(WEIGHT_TCC_EN0_MASK |
323262306a36Sopenharmony_ci						      WEIGHT_TCC_EN1_MASK |
323362306a36Sopenharmony_ci						      WEIGHT_TCC_EN2_MASK);
323462306a36Sopenharmony_ci	reg |= (WEIGHT_TCC_EN0(ni_pi->cac_weights->weight_tcc_en0) |
323562306a36Sopenharmony_ci		WEIGHT_TCC_EN1(ni_pi->cac_weights->weight_tcc_en1) |
323662306a36Sopenharmony_ci		WEIGHT_TCC_EN2(ni_pi->cac_weights->weight_tcc_en2));
323762306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_1_WEIGHT_1, reg);
323862306a36Sopenharmony_ci
323962306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_2_WEIGHT_0) & ~(WEIGHT_CB_EN0_MASK |
324062306a36Sopenharmony_ci						      WEIGHT_CB_EN1_MASK |
324162306a36Sopenharmony_ci						      WEIGHT_CB_EN2_MASK |
324262306a36Sopenharmony_ci						      WEIGHT_CB_EN3_MASK);
324362306a36Sopenharmony_ci	reg |= (WEIGHT_CB_EN0(ni_pi->cac_weights->weight_cb_en0) |
324462306a36Sopenharmony_ci		WEIGHT_CB_EN1(ni_pi->cac_weights->weight_cb_en1) |
324562306a36Sopenharmony_ci		WEIGHT_CB_EN2(ni_pi->cac_weights->weight_cb_en2) |
324662306a36Sopenharmony_ci		WEIGHT_CB_EN3(ni_pi->cac_weights->weight_cb_en3));
324762306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_2_WEIGHT_0, reg);
324862306a36Sopenharmony_ci
324962306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_2_WEIGHT_1) & ~(WEIGHT_DB_SIG0_MASK |
325062306a36Sopenharmony_ci						      WEIGHT_DB_SIG1_MASK |
325162306a36Sopenharmony_ci						      WEIGHT_DB_SIG2_MASK |
325262306a36Sopenharmony_ci						      WEIGHT_DB_SIG3_MASK);
325362306a36Sopenharmony_ci	reg |= (WEIGHT_DB_SIG0(ni_pi->cac_weights->weight_db_sig0) |
325462306a36Sopenharmony_ci		WEIGHT_DB_SIG1(ni_pi->cac_weights->weight_db_sig1) |
325562306a36Sopenharmony_ci		WEIGHT_DB_SIG2(ni_pi->cac_weights->weight_db_sig2) |
325662306a36Sopenharmony_ci		WEIGHT_DB_SIG3(ni_pi->cac_weights->weight_db_sig3));
325762306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_2_WEIGHT_1, reg);
325862306a36Sopenharmony_ci
325962306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_2_WEIGHT_2) & ~(WEIGHT_SXM_SIG0_MASK |
326062306a36Sopenharmony_ci						      WEIGHT_SXM_SIG1_MASK |
326162306a36Sopenharmony_ci						      WEIGHT_SXM_SIG2_MASK |
326262306a36Sopenharmony_ci						      WEIGHT_SXS_SIG0_MASK |
326362306a36Sopenharmony_ci						      WEIGHT_SXS_SIG1_MASK);
326462306a36Sopenharmony_ci	reg |= (WEIGHT_SXM_SIG0(ni_pi->cac_weights->weight_sxm_sig0) |
326562306a36Sopenharmony_ci		WEIGHT_SXM_SIG1(ni_pi->cac_weights->weight_sxm_sig1) |
326662306a36Sopenharmony_ci		WEIGHT_SXM_SIG2(ni_pi->cac_weights->weight_sxm_sig2) |
326762306a36Sopenharmony_ci		WEIGHT_SXS_SIG0(ni_pi->cac_weights->weight_sxs_sig0) |
326862306a36Sopenharmony_ci		WEIGHT_SXS_SIG1(ni_pi->cac_weights->weight_sxs_sig1));
326962306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_2_WEIGHT_2, reg);
327062306a36Sopenharmony_ci
327162306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_3_WEIGHT_0) & ~(WEIGHT_XBR_0_MASK |
327262306a36Sopenharmony_ci						      WEIGHT_XBR_1_MASK |
327362306a36Sopenharmony_ci						      WEIGHT_XBR_2_MASK |
327462306a36Sopenharmony_ci						      WEIGHT_SPI_SIG0_MASK);
327562306a36Sopenharmony_ci	reg |= (WEIGHT_XBR_0(ni_pi->cac_weights->weight_xbr_0) |
327662306a36Sopenharmony_ci		WEIGHT_XBR_1(ni_pi->cac_weights->weight_xbr_1) |
327762306a36Sopenharmony_ci		WEIGHT_XBR_2(ni_pi->cac_weights->weight_xbr_2) |
327862306a36Sopenharmony_ci		WEIGHT_SPI_SIG0(ni_pi->cac_weights->weight_spi_sig0));
327962306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_3_WEIGHT_0, reg);
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_3_WEIGHT_1) & ~(WEIGHT_SPI_SIG1_MASK |
328262306a36Sopenharmony_ci						      WEIGHT_SPI_SIG2_MASK |
328362306a36Sopenharmony_ci						      WEIGHT_SPI_SIG3_MASK |
328462306a36Sopenharmony_ci						      WEIGHT_SPI_SIG4_MASK |
328562306a36Sopenharmony_ci						      WEIGHT_SPI_SIG5_MASK);
328662306a36Sopenharmony_ci	reg |= (WEIGHT_SPI_SIG1(ni_pi->cac_weights->weight_spi_sig1) |
328762306a36Sopenharmony_ci		WEIGHT_SPI_SIG2(ni_pi->cac_weights->weight_spi_sig2) |
328862306a36Sopenharmony_ci		WEIGHT_SPI_SIG3(ni_pi->cac_weights->weight_spi_sig3) |
328962306a36Sopenharmony_ci		WEIGHT_SPI_SIG4(ni_pi->cac_weights->weight_spi_sig4) |
329062306a36Sopenharmony_ci		WEIGHT_SPI_SIG5(ni_pi->cac_weights->weight_spi_sig5));
329162306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_3_WEIGHT_1, reg);
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_0) & ~(WEIGHT_LDS_SIG0_MASK |
329462306a36Sopenharmony_ci						      WEIGHT_LDS_SIG1_MASK |
329562306a36Sopenharmony_ci						      WEIGHT_SC_MASK);
329662306a36Sopenharmony_ci	reg |= (WEIGHT_LDS_SIG0(ni_pi->cac_weights->weight_lds_sig0) |
329762306a36Sopenharmony_ci		WEIGHT_LDS_SIG1(ni_pi->cac_weights->weight_lds_sig1) |
329862306a36Sopenharmony_ci		WEIGHT_SC(ni_pi->cac_weights->weight_sc));
329962306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_0, reg);
330062306a36Sopenharmony_ci
330162306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_1) & ~(WEIGHT_BIF_MASK |
330262306a36Sopenharmony_ci						      WEIGHT_CP_MASK |
330362306a36Sopenharmony_ci						      WEIGHT_PA_SIG0_MASK |
330462306a36Sopenharmony_ci						      WEIGHT_PA_SIG1_MASK |
330562306a36Sopenharmony_ci						      WEIGHT_VGT_SIG0_MASK);
330662306a36Sopenharmony_ci	reg |= (WEIGHT_BIF(ni_pi->cac_weights->weight_bif) |
330762306a36Sopenharmony_ci		WEIGHT_CP(ni_pi->cac_weights->weight_cp) |
330862306a36Sopenharmony_ci		WEIGHT_PA_SIG0(ni_pi->cac_weights->weight_pa_sig0) |
330962306a36Sopenharmony_ci		WEIGHT_PA_SIG1(ni_pi->cac_weights->weight_pa_sig1) |
331062306a36Sopenharmony_ci		WEIGHT_VGT_SIG0(ni_pi->cac_weights->weight_vgt_sig0));
331162306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_1, reg);
331262306a36Sopenharmony_ci
331362306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_2) & ~(WEIGHT_VGT_SIG1_MASK |
331462306a36Sopenharmony_ci						      WEIGHT_VGT_SIG2_MASK |
331562306a36Sopenharmony_ci						      WEIGHT_DC_SIG0_MASK |
331662306a36Sopenharmony_ci						      WEIGHT_DC_SIG1_MASK |
331762306a36Sopenharmony_ci						      WEIGHT_DC_SIG2_MASK);
331862306a36Sopenharmony_ci	reg |= (WEIGHT_VGT_SIG1(ni_pi->cac_weights->weight_vgt_sig1) |
331962306a36Sopenharmony_ci		WEIGHT_VGT_SIG2(ni_pi->cac_weights->weight_vgt_sig2) |
332062306a36Sopenharmony_ci		WEIGHT_DC_SIG0(ni_pi->cac_weights->weight_dc_sig0) |
332162306a36Sopenharmony_ci		WEIGHT_DC_SIG1(ni_pi->cac_weights->weight_dc_sig1) |
332262306a36Sopenharmony_ci		WEIGHT_DC_SIG2(ni_pi->cac_weights->weight_dc_sig2));
332362306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_2, reg);
332462306a36Sopenharmony_ci
332562306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_WEIGHT_3) & ~(WEIGHT_DC_SIG3_MASK |
332662306a36Sopenharmony_ci						      WEIGHT_UVD_SIG0_MASK |
332762306a36Sopenharmony_ci						      WEIGHT_UVD_SIG1_MASK |
332862306a36Sopenharmony_ci						      WEIGHT_SPARE0_MASK |
332962306a36Sopenharmony_ci						      WEIGHT_SPARE1_MASK);
333062306a36Sopenharmony_ci	reg |= (WEIGHT_DC_SIG3(ni_pi->cac_weights->weight_dc_sig3) |
333162306a36Sopenharmony_ci		WEIGHT_UVD_SIG0(ni_pi->cac_weights->weight_uvd_sig0) |
333262306a36Sopenharmony_ci		WEIGHT_UVD_SIG1(ni_pi->cac_weights->weight_uvd_sig1) |
333362306a36Sopenharmony_ci		WEIGHT_SPARE0(ni_pi->cac_weights->weight_spare0) |
333462306a36Sopenharmony_ci		WEIGHT_SPARE1(ni_pi->cac_weights->weight_spare1));
333562306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_WEIGHT_3, reg);
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_5_WEIGHT_0) & ~(WEIGHT_SQ_VSP_MASK |
333862306a36Sopenharmony_ci						      WEIGHT_SQ_VSP0_MASK);
333962306a36Sopenharmony_ci	reg |= (WEIGHT_SQ_VSP(ni_pi->cac_weights->weight_sq_vsp) |
334062306a36Sopenharmony_ci		WEIGHT_SQ_VSP0(ni_pi->cac_weights->weight_sq_vsp0));
334162306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_5_WEIGHT_0, reg);
334262306a36Sopenharmony_ci
334362306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_5_WEIGHT_1) & ~(WEIGHT_SQ_GPR_MASK);
334462306a36Sopenharmony_ci	reg |= WEIGHT_SQ_GPR(ni_pi->cac_weights->weight_sq_gpr);
334562306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_5_WEIGHT_1, reg);
334662306a36Sopenharmony_ci
334762306a36Sopenharmony_ci	reg = RREG32_CG(CG_CAC_REGION_4_OVERRIDE_4) & ~(OVR_MODE_SPARE_0_MASK |
334862306a36Sopenharmony_ci							OVR_VAL_SPARE_0_MASK |
334962306a36Sopenharmony_ci							OVR_MODE_SPARE_1_MASK |
335062306a36Sopenharmony_ci							OVR_VAL_SPARE_1_MASK);
335162306a36Sopenharmony_ci	reg |= (OVR_MODE_SPARE_0(ni_pi->cac_weights->ovr_mode_spare_0) |
335262306a36Sopenharmony_ci		OVR_VAL_SPARE_0(ni_pi->cac_weights->ovr_val_spare_0) |
335362306a36Sopenharmony_ci		OVR_MODE_SPARE_1(ni_pi->cac_weights->ovr_mode_spare_1) |
335462306a36Sopenharmony_ci		OVR_VAL_SPARE_1(ni_pi->cac_weights->ovr_val_spare_1));
335562306a36Sopenharmony_ci	WREG32_CG(CG_CAC_REGION_4_OVERRIDE_4, reg);
335662306a36Sopenharmony_ci
335762306a36Sopenharmony_ci	reg = RREG32(SQ_CAC_THRESHOLD) & ~(VSP_MASK |
335862306a36Sopenharmony_ci					   VSP0_MASK |
335962306a36Sopenharmony_ci					   GPR_MASK);
336062306a36Sopenharmony_ci	reg |= (VSP(ni_pi->cac_weights->vsp) |
336162306a36Sopenharmony_ci		VSP0(ni_pi->cac_weights->vsp0) |
336262306a36Sopenharmony_ci		GPR(ni_pi->cac_weights->gpr));
336362306a36Sopenharmony_ci	WREG32(SQ_CAC_THRESHOLD, reg);
336462306a36Sopenharmony_ci
336562306a36Sopenharmony_ci	reg = (MCDW_WR_ENABLE |
336662306a36Sopenharmony_ci	       MCDX_WR_ENABLE |
336762306a36Sopenharmony_ci	       MCDY_WR_ENABLE |
336862306a36Sopenharmony_ci	       MCDZ_WR_ENABLE |
336962306a36Sopenharmony_ci	       INDEX(0x09D4));
337062306a36Sopenharmony_ci	WREG32(MC_CG_CONFIG, reg);
337162306a36Sopenharmony_ci
337262306a36Sopenharmony_ci	reg = (READ_WEIGHT(ni_pi->cac_weights->mc_read_weight) |
337362306a36Sopenharmony_ci	       WRITE_WEIGHT(ni_pi->cac_weights->mc_write_weight) |
337462306a36Sopenharmony_ci	       ALLOW_OVERFLOW);
337562306a36Sopenharmony_ci	WREG32(MC_CG_DATAPORT, reg);
337662306a36Sopenharmony_ci
337762306a36Sopenharmony_ci	return 0;
337862306a36Sopenharmony_ci}
337962306a36Sopenharmony_ci
338062306a36Sopenharmony_cistatic int ni_enable_smc_cac(struct radeon_device *rdev,
338162306a36Sopenharmony_ci			     struct radeon_ps *radeon_new_state,
338262306a36Sopenharmony_ci			     bool enable)
338362306a36Sopenharmony_ci{
338462306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
338562306a36Sopenharmony_ci	int ret = 0;
338662306a36Sopenharmony_ci	PPSMC_Result smc_result;
338762306a36Sopenharmony_ci
338862306a36Sopenharmony_ci	if (ni_pi->enable_cac) {
338962306a36Sopenharmony_ci		if (enable) {
339062306a36Sopenharmony_ci			if (!r600_is_uvd_state(radeon_new_state->class, radeon_new_state->class2)) {
339162306a36Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_CollectCAC_PowerCorreln);
339262306a36Sopenharmony_ci
339362306a36Sopenharmony_ci				if (ni_pi->support_cac_long_term_average) {
339462306a36Sopenharmony_ci					smc_result = rv770_send_msg_to_smc(rdev, PPSMC_CACLongTermAvgEnable);
339562306a36Sopenharmony_ci					if (PPSMC_Result_OK != smc_result)
339662306a36Sopenharmony_ci						ni_pi->support_cac_long_term_average = false;
339762306a36Sopenharmony_ci				}
339862306a36Sopenharmony_ci
339962306a36Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableCac);
340062306a36Sopenharmony_ci				if (PPSMC_Result_OK != smc_result)
340162306a36Sopenharmony_ci					ret = -EINVAL;
340262306a36Sopenharmony_ci
340362306a36Sopenharmony_ci				ni_pi->cac_enabled = (PPSMC_Result_OK == smc_result) ? true : false;
340462306a36Sopenharmony_ci			}
340562306a36Sopenharmony_ci		} else if (ni_pi->cac_enabled) {
340662306a36Sopenharmony_ci			smc_result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_DisableCac);
340762306a36Sopenharmony_ci
340862306a36Sopenharmony_ci			ni_pi->cac_enabled = false;
340962306a36Sopenharmony_ci
341062306a36Sopenharmony_ci			if (ni_pi->support_cac_long_term_average) {
341162306a36Sopenharmony_ci				smc_result = rv770_send_msg_to_smc(rdev, PPSMC_CACLongTermAvgDisable);
341262306a36Sopenharmony_ci				if (PPSMC_Result_OK != smc_result)
341362306a36Sopenharmony_ci					ni_pi->support_cac_long_term_average = false;
341462306a36Sopenharmony_ci			}
341562306a36Sopenharmony_ci		}
341662306a36Sopenharmony_ci	}
341762306a36Sopenharmony_ci
341862306a36Sopenharmony_ci	return ret;
341962306a36Sopenharmony_ci}
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_cistatic int ni_pcie_performance_request(struct radeon_device *rdev,
342262306a36Sopenharmony_ci				       u8 perf_req, bool advertise)
342362306a36Sopenharmony_ci{
342462306a36Sopenharmony_ci#if defined(CONFIG_ACPI)
342562306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
342662306a36Sopenharmony_ci
342762306a36Sopenharmony_ci	if ((perf_req == PCIE_PERF_REQ_PECI_GEN1) ||
342862306a36Sopenharmony_ci	    (perf_req == PCIE_PERF_REQ_PECI_GEN2)) {
342962306a36Sopenharmony_ci		if (eg_pi->pcie_performance_request_registered == false)
343062306a36Sopenharmony_ci			radeon_acpi_pcie_notify_device_ready(rdev);
343162306a36Sopenharmony_ci		eg_pi->pcie_performance_request_registered = true;
343262306a36Sopenharmony_ci		return radeon_acpi_pcie_performance_request(rdev, perf_req, advertise);
343362306a36Sopenharmony_ci	} else if ((perf_req == PCIE_PERF_REQ_REMOVE_REGISTRY) &&
343462306a36Sopenharmony_ci		    eg_pi->pcie_performance_request_registered) {
343562306a36Sopenharmony_ci		eg_pi->pcie_performance_request_registered = false;
343662306a36Sopenharmony_ci		return radeon_acpi_pcie_performance_request(rdev, perf_req, advertise);
343762306a36Sopenharmony_ci	}
343862306a36Sopenharmony_ci#endif
343962306a36Sopenharmony_ci	return 0;
344062306a36Sopenharmony_ci}
344162306a36Sopenharmony_ci
344262306a36Sopenharmony_cistatic int ni_advertise_gen2_capability(struct radeon_device *rdev)
344362306a36Sopenharmony_ci{
344462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
344562306a36Sopenharmony_ci	u32 tmp;
344662306a36Sopenharmony_ci
344762306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
344862306a36Sopenharmony_ci
344962306a36Sopenharmony_ci	if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
345062306a36Sopenharmony_ci	    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
345162306a36Sopenharmony_ci		pi->pcie_gen2 = true;
345262306a36Sopenharmony_ci	else
345362306a36Sopenharmony_ci		pi->pcie_gen2 = false;
345462306a36Sopenharmony_ci
345562306a36Sopenharmony_ci	if (!pi->pcie_gen2)
345662306a36Sopenharmony_ci		ni_pcie_performance_request(rdev, PCIE_PERF_REQ_PECI_GEN2, true);
345762306a36Sopenharmony_ci
345862306a36Sopenharmony_ci	return 0;
345962306a36Sopenharmony_ci}
346062306a36Sopenharmony_ci
346162306a36Sopenharmony_cistatic void ni_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
346262306a36Sopenharmony_ci					    bool enable)
346362306a36Sopenharmony_ci{
346462306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
346562306a36Sopenharmony_ci	u32 tmp, bif;
346662306a36Sopenharmony_ci
346762306a36Sopenharmony_ci	tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
346862306a36Sopenharmony_ci
346962306a36Sopenharmony_ci	if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
347062306a36Sopenharmony_ci	    (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
347162306a36Sopenharmony_ci		if (enable) {
347262306a36Sopenharmony_ci			if (!pi->boot_in_gen2) {
347362306a36Sopenharmony_ci				bif = RREG32(CG_BIF_REQ_AND_RSP) & ~CG_CLIENT_REQ_MASK;
347462306a36Sopenharmony_ci				bif |= CG_CLIENT_REQ(0xd);
347562306a36Sopenharmony_ci				WREG32(CG_BIF_REQ_AND_RSP, bif);
347662306a36Sopenharmony_ci			}
347762306a36Sopenharmony_ci			tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
347862306a36Sopenharmony_ci			tmp |= LC_HW_VOLTAGE_IF_CONTROL(1);
347962306a36Sopenharmony_ci			tmp |= LC_GEN2_EN_STRAP;
348062306a36Sopenharmony_ci
348162306a36Sopenharmony_ci			tmp |= LC_CLR_FAILED_SPD_CHANGE_CNT;
348262306a36Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
348362306a36Sopenharmony_ci			udelay(10);
348462306a36Sopenharmony_ci			tmp &= ~LC_CLR_FAILED_SPD_CHANGE_CNT;
348562306a36Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
348662306a36Sopenharmony_ci		} else {
348762306a36Sopenharmony_ci			if (!pi->boot_in_gen2) {
348862306a36Sopenharmony_ci				bif = RREG32(CG_BIF_REQ_AND_RSP) & ~CG_CLIENT_REQ_MASK;
348962306a36Sopenharmony_ci				bif |= CG_CLIENT_REQ(0xd);
349062306a36Sopenharmony_ci				WREG32(CG_BIF_REQ_AND_RSP, bif);
349162306a36Sopenharmony_ci
349262306a36Sopenharmony_ci				tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
349362306a36Sopenharmony_ci				tmp &= ~LC_GEN2_EN_STRAP;
349462306a36Sopenharmony_ci			}
349562306a36Sopenharmony_ci			WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
349662306a36Sopenharmony_ci		}
349762306a36Sopenharmony_ci	}
349862306a36Sopenharmony_ci}
349962306a36Sopenharmony_ci
350062306a36Sopenharmony_cistatic void ni_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
350162306a36Sopenharmony_ci					bool enable)
350262306a36Sopenharmony_ci{
350362306a36Sopenharmony_ci	ni_enable_bif_dynamic_pcie_gen2(rdev, enable);
350462306a36Sopenharmony_ci
350562306a36Sopenharmony_ci	if (enable)
350662306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE);
350762306a36Sopenharmony_ci	else
350862306a36Sopenharmony_ci		WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE);
350962306a36Sopenharmony_ci}
351062306a36Sopenharmony_ci
351162306a36Sopenharmony_civoid ni_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
351262306a36Sopenharmony_ci					   struct radeon_ps *new_ps,
351362306a36Sopenharmony_ci					   struct radeon_ps *old_ps)
351462306a36Sopenharmony_ci{
351562306a36Sopenharmony_ci	struct ni_ps *new_state = ni_get_ps(new_ps);
351662306a36Sopenharmony_ci	struct ni_ps *current_state = ni_get_ps(old_ps);
351762306a36Sopenharmony_ci
351862306a36Sopenharmony_ci	if ((new_ps->vclk == old_ps->vclk) &&
351962306a36Sopenharmony_ci	    (new_ps->dclk == old_ps->dclk))
352062306a36Sopenharmony_ci		return;
352162306a36Sopenharmony_ci
352262306a36Sopenharmony_ci	if (new_state->performance_levels[new_state->performance_level_count - 1].sclk >=
352362306a36Sopenharmony_ci	    current_state->performance_levels[current_state->performance_level_count - 1].sclk)
352462306a36Sopenharmony_ci		return;
352562306a36Sopenharmony_ci
352662306a36Sopenharmony_ci	radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
352762306a36Sopenharmony_ci}
352862306a36Sopenharmony_ci
352962306a36Sopenharmony_civoid ni_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
353062306a36Sopenharmony_ci					  struct radeon_ps *new_ps,
353162306a36Sopenharmony_ci					  struct radeon_ps *old_ps)
353262306a36Sopenharmony_ci{
353362306a36Sopenharmony_ci	struct ni_ps *new_state = ni_get_ps(new_ps);
353462306a36Sopenharmony_ci	struct ni_ps *current_state = ni_get_ps(old_ps);
353562306a36Sopenharmony_ci
353662306a36Sopenharmony_ci	if ((new_ps->vclk == old_ps->vclk) &&
353762306a36Sopenharmony_ci	    (new_ps->dclk == old_ps->dclk))
353862306a36Sopenharmony_ci		return;
353962306a36Sopenharmony_ci
354062306a36Sopenharmony_ci	if (new_state->performance_levels[new_state->performance_level_count - 1].sclk <
354162306a36Sopenharmony_ci	    current_state->performance_levels[current_state->performance_level_count - 1].sclk)
354262306a36Sopenharmony_ci		return;
354362306a36Sopenharmony_ci
354462306a36Sopenharmony_ci	radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
354562306a36Sopenharmony_ci}
354662306a36Sopenharmony_ci
354762306a36Sopenharmony_civoid ni_dpm_setup_asic(struct radeon_device *rdev)
354862306a36Sopenharmony_ci{
354962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
355062306a36Sopenharmony_ci	int r;
355162306a36Sopenharmony_ci
355262306a36Sopenharmony_ci	r = ni_mc_load_microcode(rdev);
355362306a36Sopenharmony_ci	if (r)
355462306a36Sopenharmony_ci		DRM_ERROR("Failed to load MC firmware!\n");
355562306a36Sopenharmony_ci	ni_read_clock_registers(rdev);
355662306a36Sopenharmony_ci	btc_read_arb_registers(rdev);
355762306a36Sopenharmony_ci	rv770_get_memory_type(rdev);
355862306a36Sopenharmony_ci	if (eg_pi->pcie_performance_request)
355962306a36Sopenharmony_ci		ni_advertise_gen2_capability(rdev);
356062306a36Sopenharmony_ci	rv770_get_pcie_gen2_status(rdev);
356162306a36Sopenharmony_ci	rv770_enable_acpi_pm(rdev);
356262306a36Sopenharmony_ci}
356362306a36Sopenharmony_ci
356462306a36Sopenharmony_civoid ni_update_current_ps(struct radeon_device *rdev,
356562306a36Sopenharmony_ci			  struct radeon_ps *rps)
356662306a36Sopenharmony_ci{
356762306a36Sopenharmony_ci	struct ni_ps *new_ps = ni_get_ps(rps);
356862306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
356962306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
357062306a36Sopenharmony_ci
357162306a36Sopenharmony_ci	eg_pi->current_rps = *rps;
357262306a36Sopenharmony_ci	ni_pi->current_ps = *new_ps;
357362306a36Sopenharmony_ci	eg_pi->current_rps.ps_priv = &ni_pi->current_ps;
357462306a36Sopenharmony_ci}
357562306a36Sopenharmony_ci
357662306a36Sopenharmony_civoid ni_update_requested_ps(struct radeon_device *rdev,
357762306a36Sopenharmony_ci			    struct radeon_ps *rps)
357862306a36Sopenharmony_ci{
357962306a36Sopenharmony_ci	struct ni_ps *new_ps = ni_get_ps(rps);
358062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
358162306a36Sopenharmony_ci	struct ni_power_info *ni_pi = ni_get_pi(rdev);
358262306a36Sopenharmony_ci
358362306a36Sopenharmony_ci	eg_pi->requested_rps = *rps;
358462306a36Sopenharmony_ci	ni_pi->requested_ps = *new_ps;
358562306a36Sopenharmony_ci	eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps;
358662306a36Sopenharmony_ci}
358762306a36Sopenharmony_ci
358862306a36Sopenharmony_ciint ni_dpm_enable(struct radeon_device *rdev)
358962306a36Sopenharmony_ci{
359062306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
359162306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
359262306a36Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
359362306a36Sopenharmony_ci	int ret;
359462306a36Sopenharmony_ci
359562306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
359662306a36Sopenharmony_ci		ni_cg_clockgating_default(rdev);
359762306a36Sopenharmony_ci	if (btc_dpm_enabled(rdev))
359862306a36Sopenharmony_ci		return -EINVAL;
359962306a36Sopenharmony_ci	if (pi->mg_clock_gating)
360062306a36Sopenharmony_ci		ni_mg_clockgating_default(rdev);
360162306a36Sopenharmony_ci	if (eg_pi->ls_clock_gating)
360262306a36Sopenharmony_ci		ni_ls_clockgating_default(rdev);
360362306a36Sopenharmony_ci	if (pi->voltage_control) {
360462306a36Sopenharmony_ci		rv770_enable_voltage_control(rdev, true);
360562306a36Sopenharmony_ci		ret = cypress_construct_voltage_tables(rdev);
360662306a36Sopenharmony_ci		if (ret) {
360762306a36Sopenharmony_ci			DRM_ERROR("cypress_construct_voltage_tables failed\n");
360862306a36Sopenharmony_ci			return ret;
360962306a36Sopenharmony_ci		}
361062306a36Sopenharmony_ci	}
361162306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
361262306a36Sopenharmony_ci		ret = ni_initialize_mc_reg_table(rdev);
361362306a36Sopenharmony_ci		if (ret)
361462306a36Sopenharmony_ci			eg_pi->dynamic_ac_timing = false;
361562306a36Sopenharmony_ci	}
361662306a36Sopenharmony_ci	if (pi->dynamic_ss)
361762306a36Sopenharmony_ci		cypress_enable_spread_spectrum(rdev, true);
361862306a36Sopenharmony_ci	if (pi->thermal_protection)
361962306a36Sopenharmony_ci		rv770_enable_thermal_protection(rdev, true);
362062306a36Sopenharmony_ci	rv770_setup_bsp(rdev);
362162306a36Sopenharmony_ci	rv770_program_git(rdev);
362262306a36Sopenharmony_ci	rv770_program_tp(rdev);
362362306a36Sopenharmony_ci	rv770_program_tpp(rdev);
362462306a36Sopenharmony_ci	rv770_program_sstp(rdev);
362562306a36Sopenharmony_ci	cypress_enable_display_gap(rdev);
362662306a36Sopenharmony_ci	rv770_program_vc(rdev);
362762306a36Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
362862306a36Sopenharmony_ci		ni_enable_dynamic_pcie_gen2(rdev, true);
362962306a36Sopenharmony_ci	ret = rv770_upload_firmware(rdev);
363062306a36Sopenharmony_ci	if (ret) {
363162306a36Sopenharmony_ci		DRM_ERROR("rv770_upload_firmware failed\n");
363262306a36Sopenharmony_ci		return ret;
363362306a36Sopenharmony_ci	}
363462306a36Sopenharmony_ci	ret = ni_process_firmware_header(rdev);
363562306a36Sopenharmony_ci	if (ret) {
363662306a36Sopenharmony_ci		DRM_ERROR("ni_process_firmware_header failed\n");
363762306a36Sopenharmony_ci		return ret;
363862306a36Sopenharmony_ci	}
363962306a36Sopenharmony_ci	ret = ni_initial_switch_from_arb_f0_to_f1(rdev);
364062306a36Sopenharmony_ci	if (ret) {
364162306a36Sopenharmony_ci		DRM_ERROR("ni_initial_switch_from_arb_f0_to_f1 failed\n");
364262306a36Sopenharmony_ci		return ret;
364362306a36Sopenharmony_ci	}
364462306a36Sopenharmony_ci	ret = ni_init_smc_table(rdev);
364562306a36Sopenharmony_ci	if (ret) {
364662306a36Sopenharmony_ci		DRM_ERROR("ni_init_smc_table failed\n");
364762306a36Sopenharmony_ci		return ret;
364862306a36Sopenharmony_ci	}
364962306a36Sopenharmony_ci	ret = ni_init_smc_spll_table(rdev);
365062306a36Sopenharmony_ci	if (ret) {
365162306a36Sopenharmony_ci		DRM_ERROR("ni_init_smc_spll_table failed\n");
365262306a36Sopenharmony_ci		return ret;
365362306a36Sopenharmony_ci	}
365462306a36Sopenharmony_ci	ret = ni_init_arb_table_index(rdev);
365562306a36Sopenharmony_ci	if (ret) {
365662306a36Sopenharmony_ci		DRM_ERROR("ni_init_arb_table_index failed\n");
365762306a36Sopenharmony_ci		return ret;
365862306a36Sopenharmony_ci	}
365962306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
366062306a36Sopenharmony_ci		ret = ni_populate_mc_reg_table(rdev, boot_ps);
366162306a36Sopenharmony_ci		if (ret) {
366262306a36Sopenharmony_ci			DRM_ERROR("ni_populate_mc_reg_table failed\n");
366362306a36Sopenharmony_ci			return ret;
366462306a36Sopenharmony_ci		}
366562306a36Sopenharmony_ci	}
366662306a36Sopenharmony_ci	ret = ni_initialize_smc_cac_tables(rdev);
366762306a36Sopenharmony_ci	if (ret) {
366862306a36Sopenharmony_ci		DRM_ERROR("ni_initialize_smc_cac_tables failed\n");
366962306a36Sopenharmony_ci		return ret;
367062306a36Sopenharmony_ci	}
367162306a36Sopenharmony_ci	ret = ni_initialize_hardware_cac_manager(rdev);
367262306a36Sopenharmony_ci	if (ret) {
367362306a36Sopenharmony_ci		DRM_ERROR("ni_initialize_hardware_cac_manager failed\n");
367462306a36Sopenharmony_ci		return ret;
367562306a36Sopenharmony_ci	}
367662306a36Sopenharmony_ci	ret = ni_populate_smc_tdp_limits(rdev, boot_ps);
367762306a36Sopenharmony_ci	if (ret) {
367862306a36Sopenharmony_ci		DRM_ERROR("ni_populate_smc_tdp_limits failed\n");
367962306a36Sopenharmony_ci		return ret;
368062306a36Sopenharmony_ci	}
368162306a36Sopenharmony_ci	ni_program_response_times(rdev);
368262306a36Sopenharmony_ci	r7xx_start_smc(rdev);
368362306a36Sopenharmony_ci	ret = cypress_notify_smc_display_change(rdev, false);
368462306a36Sopenharmony_ci	if (ret) {
368562306a36Sopenharmony_ci		DRM_ERROR("cypress_notify_smc_display_change failed\n");
368662306a36Sopenharmony_ci		return ret;
368762306a36Sopenharmony_ci	}
368862306a36Sopenharmony_ci	cypress_enable_sclk_control(rdev, true);
368962306a36Sopenharmony_ci	if (eg_pi->memory_transition)
369062306a36Sopenharmony_ci		cypress_enable_mclk_control(rdev, true);
369162306a36Sopenharmony_ci	cypress_start_dpm(rdev);
369262306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
369362306a36Sopenharmony_ci		ni_gfx_clockgating_enable(rdev, true);
369462306a36Sopenharmony_ci	if (pi->mg_clock_gating)
369562306a36Sopenharmony_ci		ni_mg_clockgating_enable(rdev, true);
369662306a36Sopenharmony_ci	if (eg_pi->ls_clock_gating)
369762306a36Sopenharmony_ci		ni_ls_clockgating_enable(rdev, true);
369862306a36Sopenharmony_ci
369962306a36Sopenharmony_ci	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
370062306a36Sopenharmony_ci
370162306a36Sopenharmony_ci	ni_update_current_ps(rdev, boot_ps);
370262306a36Sopenharmony_ci
370362306a36Sopenharmony_ci	return 0;
370462306a36Sopenharmony_ci}
370562306a36Sopenharmony_ci
370662306a36Sopenharmony_civoid ni_dpm_disable(struct radeon_device *rdev)
370762306a36Sopenharmony_ci{
370862306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
370962306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
371062306a36Sopenharmony_ci	struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
371162306a36Sopenharmony_ci
371262306a36Sopenharmony_ci	if (!btc_dpm_enabled(rdev))
371362306a36Sopenharmony_ci		return;
371462306a36Sopenharmony_ci	rv770_clear_vc(rdev);
371562306a36Sopenharmony_ci	if (pi->thermal_protection)
371662306a36Sopenharmony_ci		rv770_enable_thermal_protection(rdev, false);
371762306a36Sopenharmony_ci	ni_enable_power_containment(rdev, boot_ps, false);
371862306a36Sopenharmony_ci	ni_enable_smc_cac(rdev, boot_ps, false);
371962306a36Sopenharmony_ci	cypress_enable_spread_spectrum(rdev, false);
372062306a36Sopenharmony_ci	rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, false);
372162306a36Sopenharmony_ci	if (pi->dynamic_pcie_gen2)
372262306a36Sopenharmony_ci		ni_enable_dynamic_pcie_gen2(rdev, false);
372362306a36Sopenharmony_ci
372462306a36Sopenharmony_ci	if (rdev->irq.installed &&
372562306a36Sopenharmony_ci	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
372662306a36Sopenharmony_ci		rdev->irq.dpm_thermal = false;
372762306a36Sopenharmony_ci		radeon_irq_set(rdev);
372862306a36Sopenharmony_ci	}
372962306a36Sopenharmony_ci
373062306a36Sopenharmony_ci	if (pi->gfx_clock_gating)
373162306a36Sopenharmony_ci		ni_gfx_clockgating_enable(rdev, false);
373262306a36Sopenharmony_ci	if (pi->mg_clock_gating)
373362306a36Sopenharmony_ci		ni_mg_clockgating_enable(rdev, false);
373462306a36Sopenharmony_ci	if (eg_pi->ls_clock_gating)
373562306a36Sopenharmony_ci		ni_ls_clockgating_enable(rdev, false);
373662306a36Sopenharmony_ci	ni_stop_dpm(rdev);
373762306a36Sopenharmony_ci	btc_reset_to_default(rdev);
373862306a36Sopenharmony_ci	ni_stop_smc(rdev);
373962306a36Sopenharmony_ci	ni_force_switch_to_arb_f0(rdev);
374062306a36Sopenharmony_ci
374162306a36Sopenharmony_ci	ni_update_current_ps(rdev, boot_ps);
374262306a36Sopenharmony_ci}
374362306a36Sopenharmony_ci
374462306a36Sopenharmony_cistatic int ni_power_control_set_level(struct radeon_device *rdev)
374562306a36Sopenharmony_ci{
374662306a36Sopenharmony_ci	struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
374762306a36Sopenharmony_ci	int ret;
374862306a36Sopenharmony_ci
374962306a36Sopenharmony_ci	ret = ni_restrict_performance_levels_before_switch(rdev);
375062306a36Sopenharmony_ci	if (ret)
375162306a36Sopenharmony_ci		return ret;
375262306a36Sopenharmony_ci	ret = rv770_halt_smc(rdev);
375362306a36Sopenharmony_ci	if (ret)
375462306a36Sopenharmony_ci		return ret;
375562306a36Sopenharmony_ci	ret = ni_populate_smc_tdp_limits(rdev, new_ps);
375662306a36Sopenharmony_ci	if (ret)
375762306a36Sopenharmony_ci		return ret;
375862306a36Sopenharmony_ci	ret = rv770_resume_smc(rdev);
375962306a36Sopenharmony_ci	if (ret)
376062306a36Sopenharmony_ci		return ret;
376162306a36Sopenharmony_ci	ret = rv770_set_sw_state(rdev);
376262306a36Sopenharmony_ci	if (ret)
376362306a36Sopenharmony_ci		return ret;
376462306a36Sopenharmony_ci
376562306a36Sopenharmony_ci	return 0;
376662306a36Sopenharmony_ci}
376762306a36Sopenharmony_ci
376862306a36Sopenharmony_ciint ni_dpm_pre_set_power_state(struct radeon_device *rdev)
376962306a36Sopenharmony_ci{
377062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
377162306a36Sopenharmony_ci	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
377262306a36Sopenharmony_ci	struct radeon_ps *new_ps = &requested_ps;
377362306a36Sopenharmony_ci
377462306a36Sopenharmony_ci	ni_update_requested_ps(rdev, new_ps);
377562306a36Sopenharmony_ci
377662306a36Sopenharmony_ci	ni_apply_state_adjust_rules(rdev, &eg_pi->requested_rps);
377762306a36Sopenharmony_ci
377862306a36Sopenharmony_ci	return 0;
377962306a36Sopenharmony_ci}
378062306a36Sopenharmony_ci
378162306a36Sopenharmony_ciint ni_dpm_set_power_state(struct radeon_device *rdev)
378262306a36Sopenharmony_ci{
378362306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
378462306a36Sopenharmony_ci	struct radeon_ps *new_ps = &eg_pi->requested_rps;
378562306a36Sopenharmony_ci	struct radeon_ps *old_ps = &eg_pi->current_rps;
378662306a36Sopenharmony_ci	int ret;
378762306a36Sopenharmony_ci
378862306a36Sopenharmony_ci	ret = ni_restrict_performance_levels_before_switch(rdev);
378962306a36Sopenharmony_ci	if (ret) {
379062306a36Sopenharmony_ci		DRM_ERROR("ni_restrict_performance_levels_before_switch failed\n");
379162306a36Sopenharmony_ci		return ret;
379262306a36Sopenharmony_ci	}
379362306a36Sopenharmony_ci	ni_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
379462306a36Sopenharmony_ci	ret = ni_enable_power_containment(rdev, new_ps, false);
379562306a36Sopenharmony_ci	if (ret) {
379662306a36Sopenharmony_ci		DRM_ERROR("ni_enable_power_containment failed\n");
379762306a36Sopenharmony_ci		return ret;
379862306a36Sopenharmony_ci	}
379962306a36Sopenharmony_ci	ret = ni_enable_smc_cac(rdev, new_ps, false);
380062306a36Sopenharmony_ci	if (ret) {
380162306a36Sopenharmony_ci		DRM_ERROR("ni_enable_smc_cac failed\n");
380262306a36Sopenharmony_ci		return ret;
380362306a36Sopenharmony_ci	}
380462306a36Sopenharmony_ci	ret = rv770_halt_smc(rdev);
380562306a36Sopenharmony_ci	if (ret) {
380662306a36Sopenharmony_ci		DRM_ERROR("rv770_halt_smc failed\n");
380762306a36Sopenharmony_ci		return ret;
380862306a36Sopenharmony_ci	}
380962306a36Sopenharmony_ci	if (eg_pi->smu_uvd_hs)
381062306a36Sopenharmony_ci		btc_notify_uvd_to_smc(rdev, new_ps);
381162306a36Sopenharmony_ci	ret = ni_upload_sw_state(rdev, new_ps);
381262306a36Sopenharmony_ci	if (ret) {
381362306a36Sopenharmony_ci		DRM_ERROR("ni_upload_sw_state failed\n");
381462306a36Sopenharmony_ci		return ret;
381562306a36Sopenharmony_ci	}
381662306a36Sopenharmony_ci	if (eg_pi->dynamic_ac_timing) {
381762306a36Sopenharmony_ci		ret = ni_upload_mc_reg_table(rdev, new_ps);
381862306a36Sopenharmony_ci		if (ret) {
381962306a36Sopenharmony_ci			DRM_ERROR("ni_upload_mc_reg_table failed\n");
382062306a36Sopenharmony_ci			return ret;
382162306a36Sopenharmony_ci		}
382262306a36Sopenharmony_ci	}
382362306a36Sopenharmony_ci	ret = ni_program_memory_timing_parameters(rdev, new_ps);
382462306a36Sopenharmony_ci	if (ret) {
382562306a36Sopenharmony_ci		DRM_ERROR("ni_program_memory_timing_parameters failed\n");
382662306a36Sopenharmony_ci		return ret;
382762306a36Sopenharmony_ci	}
382862306a36Sopenharmony_ci	ret = rv770_resume_smc(rdev);
382962306a36Sopenharmony_ci	if (ret) {
383062306a36Sopenharmony_ci		DRM_ERROR("rv770_resume_smc failed\n");
383162306a36Sopenharmony_ci		return ret;
383262306a36Sopenharmony_ci	}
383362306a36Sopenharmony_ci	ret = rv770_set_sw_state(rdev);
383462306a36Sopenharmony_ci	if (ret) {
383562306a36Sopenharmony_ci		DRM_ERROR("rv770_set_sw_state failed\n");
383662306a36Sopenharmony_ci		return ret;
383762306a36Sopenharmony_ci	}
383862306a36Sopenharmony_ci	ni_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
383962306a36Sopenharmony_ci	ret = ni_enable_smc_cac(rdev, new_ps, true);
384062306a36Sopenharmony_ci	if (ret) {
384162306a36Sopenharmony_ci		DRM_ERROR("ni_enable_smc_cac failed\n");
384262306a36Sopenharmony_ci		return ret;
384362306a36Sopenharmony_ci	}
384462306a36Sopenharmony_ci	ret = ni_enable_power_containment(rdev, new_ps, true);
384562306a36Sopenharmony_ci	if (ret) {
384662306a36Sopenharmony_ci		DRM_ERROR("ni_enable_power_containment failed\n");
384762306a36Sopenharmony_ci		return ret;
384862306a36Sopenharmony_ci	}
384962306a36Sopenharmony_ci
385062306a36Sopenharmony_ci	/* update tdp */
385162306a36Sopenharmony_ci	ret = ni_power_control_set_level(rdev);
385262306a36Sopenharmony_ci	if (ret) {
385362306a36Sopenharmony_ci		DRM_ERROR("ni_power_control_set_level failed\n");
385462306a36Sopenharmony_ci		return ret;
385562306a36Sopenharmony_ci	}
385662306a36Sopenharmony_ci
385762306a36Sopenharmony_ci	return 0;
385862306a36Sopenharmony_ci}
385962306a36Sopenharmony_ci
386062306a36Sopenharmony_civoid ni_dpm_post_set_power_state(struct radeon_device *rdev)
386162306a36Sopenharmony_ci{
386262306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
386362306a36Sopenharmony_ci	struct radeon_ps *new_ps = &eg_pi->requested_rps;
386462306a36Sopenharmony_ci
386562306a36Sopenharmony_ci	ni_update_current_ps(rdev, new_ps);
386662306a36Sopenharmony_ci}
386762306a36Sopenharmony_ci
386862306a36Sopenharmony_ci#if 0
386962306a36Sopenharmony_civoid ni_dpm_reset_asic(struct radeon_device *rdev)
387062306a36Sopenharmony_ci{
387162306a36Sopenharmony_ci	ni_restrict_performance_levels_before_switch(rdev);
387262306a36Sopenharmony_ci	rv770_set_boot_state(rdev);
387362306a36Sopenharmony_ci}
387462306a36Sopenharmony_ci#endif
387562306a36Sopenharmony_ci
387662306a36Sopenharmony_ciunion power_info {
387762306a36Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO info;
387862306a36Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V2 info_2;
387962306a36Sopenharmony_ci	struct _ATOM_POWERPLAY_INFO_V3 info_3;
388062306a36Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
388162306a36Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
388262306a36Sopenharmony_ci	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
388362306a36Sopenharmony_ci};
388462306a36Sopenharmony_ci
388562306a36Sopenharmony_ciunion pplib_clock_info {
388662306a36Sopenharmony_ci	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
388762306a36Sopenharmony_ci	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
388862306a36Sopenharmony_ci	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
388962306a36Sopenharmony_ci	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
389062306a36Sopenharmony_ci};
389162306a36Sopenharmony_ci
389262306a36Sopenharmony_ciunion pplib_power_state {
389362306a36Sopenharmony_ci	struct _ATOM_PPLIB_STATE v1;
389462306a36Sopenharmony_ci	struct _ATOM_PPLIB_STATE_V2 v2;
389562306a36Sopenharmony_ci};
389662306a36Sopenharmony_ci
389762306a36Sopenharmony_cistatic void ni_parse_pplib_non_clock_info(struct radeon_device *rdev,
389862306a36Sopenharmony_ci					  struct radeon_ps *rps,
389962306a36Sopenharmony_ci					  struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
390062306a36Sopenharmony_ci					  u8 table_rev)
390162306a36Sopenharmony_ci{
390262306a36Sopenharmony_ci	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
390362306a36Sopenharmony_ci	rps->class = le16_to_cpu(non_clock_info->usClassification);
390462306a36Sopenharmony_ci	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
390562306a36Sopenharmony_ci
390662306a36Sopenharmony_ci	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
390762306a36Sopenharmony_ci		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
390862306a36Sopenharmony_ci		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
390962306a36Sopenharmony_ci	} else if (r600_is_uvd_state(rps->class, rps->class2)) {
391062306a36Sopenharmony_ci		rps->vclk = RV770_DEFAULT_VCLK_FREQ;
391162306a36Sopenharmony_ci		rps->dclk = RV770_DEFAULT_DCLK_FREQ;
391262306a36Sopenharmony_ci	} else {
391362306a36Sopenharmony_ci		rps->vclk = 0;
391462306a36Sopenharmony_ci		rps->dclk = 0;
391562306a36Sopenharmony_ci	}
391662306a36Sopenharmony_ci
391762306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
391862306a36Sopenharmony_ci		rdev->pm.dpm.boot_ps = rps;
391962306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
392062306a36Sopenharmony_ci		rdev->pm.dpm.uvd_ps = rps;
392162306a36Sopenharmony_ci}
392262306a36Sopenharmony_ci
392362306a36Sopenharmony_cistatic void ni_parse_pplib_clock_info(struct radeon_device *rdev,
392462306a36Sopenharmony_ci				      struct radeon_ps *rps, int index,
392562306a36Sopenharmony_ci				      union pplib_clock_info *clock_info)
392662306a36Sopenharmony_ci{
392762306a36Sopenharmony_ci	struct rv7xx_power_info *pi = rv770_get_pi(rdev);
392862306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
392962306a36Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
393062306a36Sopenharmony_ci	struct rv7xx_pl *pl = &ps->performance_levels[index];
393162306a36Sopenharmony_ci
393262306a36Sopenharmony_ci	ps->performance_level_count = index + 1;
393362306a36Sopenharmony_ci
393462306a36Sopenharmony_ci	pl->sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
393562306a36Sopenharmony_ci	pl->sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
393662306a36Sopenharmony_ci	pl->mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
393762306a36Sopenharmony_ci	pl->mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
393862306a36Sopenharmony_ci
393962306a36Sopenharmony_ci	pl->vddc = le16_to_cpu(clock_info->evergreen.usVDDC);
394062306a36Sopenharmony_ci	pl->vddci = le16_to_cpu(clock_info->evergreen.usVDDCI);
394162306a36Sopenharmony_ci	pl->flags = le32_to_cpu(clock_info->evergreen.ulFlags);
394262306a36Sopenharmony_ci
394362306a36Sopenharmony_ci	/* patch up vddc if necessary */
394462306a36Sopenharmony_ci	if (pl->vddc == 0xff01) {
394562306a36Sopenharmony_ci		if (pi->max_vddc)
394662306a36Sopenharmony_ci			pl->vddc = pi->max_vddc;
394762306a36Sopenharmony_ci	}
394862306a36Sopenharmony_ci
394962306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
395062306a36Sopenharmony_ci		pi->acpi_vddc = pl->vddc;
395162306a36Sopenharmony_ci		eg_pi->acpi_vddci = pl->vddci;
395262306a36Sopenharmony_ci		if (ps->performance_levels[0].flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
395362306a36Sopenharmony_ci			pi->acpi_pcie_gen2 = true;
395462306a36Sopenharmony_ci		else
395562306a36Sopenharmony_ci			pi->acpi_pcie_gen2 = false;
395662306a36Sopenharmony_ci	}
395762306a36Sopenharmony_ci
395862306a36Sopenharmony_ci	if (rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) {
395962306a36Sopenharmony_ci		eg_pi->ulv.supported = true;
396062306a36Sopenharmony_ci		eg_pi->ulv.pl = pl;
396162306a36Sopenharmony_ci	}
396262306a36Sopenharmony_ci
396362306a36Sopenharmony_ci	if (pi->min_vddc_in_table > pl->vddc)
396462306a36Sopenharmony_ci		pi->min_vddc_in_table = pl->vddc;
396562306a36Sopenharmony_ci
396662306a36Sopenharmony_ci	if (pi->max_vddc_in_table < pl->vddc)
396762306a36Sopenharmony_ci		pi->max_vddc_in_table = pl->vddc;
396862306a36Sopenharmony_ci
396962306a36Sopenharmony_ci	/* patch up boot state */
397062306a36Sopenharmony_ci	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
397162306a36Sopenharmony_ci		u16 vddc, vddci, mvdd;
397262306a36Sopenharmony_ci		radeon_atombios_get_default_voltages(rdev, &vddc, &vddci, &mvdd);
397362306a36Sopenharmony_ci		pl->mclk = rdev->clock.default_mclk;
397462306a36Sopenharmony_ci		pl->sclk = rdev->clock.default_sclk;
397562306a36Sopenharmony_ci		pl->vddc = vddc;
397662306a36Sopenharmony_ci		pl->vddci = vddci;
397762306a36Sopenharmony_ci	}
397862306a36Sopenharmony_ci
397962306a36Sopenharmony_ci	if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
398062306a36Sopenharmony_ci	    ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
398162306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
398262306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
398362306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
398462306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
398562306a36Sopenharmony_ci	}
398662306a36Sopenharmony_ci}
398762306a36Sopenharmony_ci
398862306a36Sopenharmony_cistatic int ni_parse_power_table(struct radeon_device *rdev)
398962306a36Sopenharmony_ci{
399062306a36Sopenharmony_ci	struct radeon_mode_info *mode_info = &rdev->mode_info;
399162306a36Sopenharmony_ci	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
399262306a36Sopenharmony_ci	union pplib_power_state *power_state;
399362306a36Sopenharmony_ci	int i, j;
399462306a36Sopenharmony_ci	union pplib_clock_info *clock_info;
399562306a36Sopenharmony_ci	union power_info *power_info;
399662306a36Sopenharmony_ci	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
399762306a36Sopenharmony_ci	u16 data_offset;
399862306a36Sopenharmony_ci	u8 frev, crev;
399962306a36Sopenharmony_ci	struct ni_ps *ps;
400062306a36Sopenharmony_ci
400162306a36Sopenharmony_ci	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
400262306a36Sopenharmony_ci				   &frev, &crev, &data_offset))
400362306a36Sopenharmony_ci		return -EINVAL;
400462306a36Sopenharmony_ci	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
400562306a36Sopenharmony_ci
400662306a36Sopenharmony_ci	rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates,
400762306a36Sopenharmony_ci				  sizeof(struct radeon_ps),
400862306a36Sopenharmony_ci				  GFP_KERNEL);
400962306a36Sopenharmony_ci	if (!rdev->pm.dpm.ps)
401062306a36Sopenharmony_ci		return -ENOMEM;
401162306a36Sopenharmony_ci
401262306a36Sopenharmony_ci	for (i = 0; i < power_info->pplib.ucNumStates; i++) {
401362306a36Sopenharmony_ci		power_state = (union pplib_power_state *)
401462306a36Sopenharmony_ci			(mode_info->atom_context->bios + data_offset +
401562306a36Sopenharmony_ci			 le16_to_cpu(power_info->pplib.usStateArrayOffset) +
401662306a36Sopenharmony_ci			 i * power_info->pplib.ucStateEntrySize);
401762306a36Sopenharmony_ci		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
401862306a36Sopenharmony_ci			(mode_info->atom_context->bios + data_offset +
401962306a36Sopenharmony_ci			 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
402062306a36Sopenharmony_ci			 (power_state->v1.ucNonClockStateIndex *
402162306a36Sopenharmony_ci			  power_info->pplib.ucNonClockSize));
402262306a36Sopenharmony_ci		if (power_info->pplib.ucStateEntrySize - 1) {
402362306a36Sopenharmony_ci			u8 *idx;
402462306a36Sopenharmony_ci			ps = kzalloc(sizeof(struct ni_ps), GFP_KERNEL);
402562306a36Sopenharmony_ci			if (ps == NULL) {
402662306a36Sopenharmony_ci				kfree(rdev->pm.dpm.ps);
402762306a36Sopenharmony_ci				return -ENOMEM;
402862306a36Sopenharmony_ci			}
402962306a36Sopenharmony_ci			rdev->pm.dpm.ps[i].ps_priv = ps;
403062306a36Sopenharmony_ci			ni_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
403162306a36Sopenharmony_ci							 non_clock_info,
403262306a36Sopenharmony_ci							 power_info->pplib.ucNonClockSize);
403362306a36Sopenharmony_ci			idx = (u8 *)&power_state->v1.ucClockStateIndices[0];
403462306a36Sopenharmony_ci			for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
403562306a36Sopenharmony_ci				clock_info = (union pplib_clock_info *)
403662306a36Sopenharmony_ci					(mode_info->atom_context->bios + data_offset +
403762306a36Sopenharmony_ci					 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
403862306a36Sopenharmony_ci					 (idx[j] * power_info->pplib.ucClockInfoSize));
403962306a36Sopenharmony_ci				ni_parse_pplib_clock_info(rdev,
404062306a36Sopenharmony_ci							  &rdev->pm.dpm.ps[i], j,
404162306a36Sopenharmony_ci							  clock_info);
404262306a36Sopenharmony_ci			}
404362306a36Sopenharmony_ci		}
404462306a36Sopenharmony_ci	}
404562306a36Sopenharmony_ci	rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates;
404662306a36Sopenharmony_ci	return 0;
404762306a36Sopenharmony_ci}
404862306a36Sopenharmony_ci
404962306a36Sopenharmony_ciint ni_dpm_init(struct radeon_device *rdev)
405062306a36Sopenharmony_ci{
405162306a36Sopenharmony_ci	struct rv7xx_power_info *pi;
405262306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi;
405362306a36Sopenharmony_ci	struct ni_power_info *ni_pi;
405462306a36Sopenharmony_ci	struct atom_clock_dividers dividers;
405562306a36Sopenharmony_ci	int ret;
405662306a36Sopenharmony_ci
405762306a36Sopenharmony_ci	ni_pi = kzalloc(sizeof(struct ni_power_info), GFP_KERNEL);
405862306a36Sopenharmony_ci	if (ni_pi == NULL)
405962306a36Sopenharmony_ci		return -ENOMEM;
406062306a36Sopenharmony_ci	rdev->pm.dpm.priv = ni_pi;
406162306a36Sopenharmony_ci	eg_pi = &ni_pi->eg;
406262306a36Sopenharmony_ci	pi = &eg_pi->rv7xx;
406362306a36Sopenharmony_ci
406462306a36Sopenharmony_ci	rv770_get_max_vddc(rdev);
406562306a36Sopenharmony_ci
406662306a36Sopenharmony_ci	eg_pi->ulv.supported = false;
406762306a36Sopenharmony_ci	pi->acpi_vddc = 0;
406862306a36Sopenharmony_ci	eg_pi->acpi_vddci = 0;
406962306a36Sopenharmony_ci	pi->min_vddc_in_table = 0;
407062306a36Sopenharmony_ci	pi->max_vddc_in_table = 0;
407162306a36Sopenharmony_ci
407262306a36Sopenharmony_ci	ret = r600_get_platform_caps(rdev);
407362306a36Sopenharmony_ci	if (ret)
407462306a36Sopenharmony_ci		return ret;
407562306a36Sopenharmony_ci
407662306a36Sopenharmony_ci	ret = ni_parse_power_table(rdev);
407762306a36Sopenharmony_ci	if (ret)
407862306a36Sopenharmony_ci		return ret;
407962306a36Sopenharmony_ci	ret = r600_parse_extended_power_table(rdev);
408062306a36Sopenharmony_ci	if (ret)
408162306a36Sopenharmony_ci		return ret;
408262306a36Sopenharmony_ci
408362306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
408462306a36Sopenharmony_ci		kcalloc(4,
408562306a36Sopenharmony_ci			sizeof(struct radeon_clock_voltage_dependency_entry),
408662306a36Sopenharmony_ci			GFP_KERNEL);
408762306a36Sopenharmony_ci	if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
408862306a36Sopenharmony_ci		r600_free_extended_power_table(rdev);
408962306a36Sopenharmony_ci		return -ENOMEM;
409062306a36Sopenharmony_ci	}
409162306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
409262306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
409362306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
409462306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000;
409562306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720;
409662306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000;
409762306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810;
409862306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000;
409962306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900;
410062306a36Sopenharmony_ci
410162306a36Sopenharmony_ci	ni_patch_dependency_tables_based_on_leakage(rdev);
410262306a36Sopenharmony_ci
410362306a36Sopenharmony_ci	if (rdev->pm.dpm.voltage_response_time == 0)
410462306a36Sopenharmony_ci		rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
410562306a36Sopenharmony_ci	if (rdev->pm.dpm.backbias_response_time == 0)
410662306a36Sopenharmony_ci		rdev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;
410762306a36Sopenharmony_ci
410862306a36Sopenharmony_ci	ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
410962306a36Sopenharmony_ci					     0, false, &dividers);
411062306a36Sopenharmony_ci	if (ret)
411162306a36Sopenharmony_ci		pi->ref_div = dividers.ref_div + 1;
411262306a36Sopenharmony_ci	else
411362306a36Sopenharmony_ci		pi->ref_div = R600_REFERENCEDIVIDER_DFLT;
411462306a36Sopenharmony_ci
411562306a36Sopenharmony_ci	pi->rlp = RV770_RLP_DFLT;
411662306a36Sopenharmony_ci	pi->rmp = RV770_RMP_DFLT;
411762306a36Sopenharmony_ci	pi->lhp = RV770_LHP_DFLT;
411862306a36Sopenharmony_ci	pi->lmp = RV770_LMP_DFLT;
411962306a36Sopenharmony_ci
412062306a36Sopenharmony_ci	eg_pi->ats[0].rlp = RV770_RLP_DFLT;
412162306a36Sopenharmony_ci	eg_pi->ats[0].rmp = RV770_RMP_DFLT;
412262306a36Sopenharmony_ci	eg_pi->ats[0].lhp = RV770_LHP_DFLT;
412362306a36Sopenharmony_ci	eg_pi->ats[0].lmp = RV770_LMP_DFLT;
412462306a36Sopenharmony_ci
412562306a36Sopenharmony_ci	eg_pi->ats[1].rlp = BTC_RLP_UVD_DFLT;
412662306a36Sopenharmony_ci	eg_pi->ats[1].rmp = BTC_RMP_UVD_DFLT;
412762306a36Sopenharmony_ci	eg_pi->ats[1].lhp = BTC_LHP_UVD_DFLT;
412862306a36Sopenharmony_ci	eg_pi->ats[1].lmp = BTC_LMP_UVD_DFLT;
412962306a36Sopenharmony_ci
413062306a36Sopenharmony_ci	eg_pi->smu_uvd_hs = true;
413162306a36Sopenharmony_ci
413262306a36Sopenharmony_ci	if (rdev->pdev->device == 0x6707) {
413362306a36Sopenharmony_ci		pi->mclk_strobe_mode_threshold = 55000;
413462306a36Sopenharmony_ci		pi->mclk_edc_enable_threshold = 55000;
413562306a36Sopenharmony_ci		eg_pi->mclk_edc_wr_enable_threshold = 55000;
413662306a36Sopenharmony_ci	} else {
413762306a36Sopenharmony_ci		pi->mclk_strobe_mode_threshold = 40000;
413862306a36Sopenharmony_ci		pi->mclk_edc_enable_threshold = 40000;
413962306a36Sopenharmony_ci		eg_pi->mclk_edc_wr_enable_threshold = 40000;
414062306a36Sopenharmony_ci	}
414162306a36Sopenharmony_ci	ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold;
414262306a36Sopenharmony_ci
414362306a36Sopenharmony_ci	pi->voltage_control =
414462306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, 0);
414562306a36Sopenharmony_ci
414662306a36Sopenharmony_ci	pi->mvdd_control =
414762306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0);
414862306a36Sopenharmony_ci
414962306a36Sopenharmony_ci	eg_pi->vddci_control =
415062306a36Sopenharmony_ci		radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDCI, 0);
415162306a36Sopenharmony_ci
415262306a36Sopenharmony_ci	rv770_get_engine_memory_ss(rdev);
415362306a36Sopenharmony_ci
415462306a36Sopenharmony_ci	pi->asi = RV770_ASI_DFLT;
415562306a36Sopenharmony_ci	pi->pasi = CYPRESS_HASI_DFLT;
415662306a36Sopenharmony_ci	pi->vrc = CYPRESS_VRC_DFLT;
415762306a36Sopenharmony_ci
415862306a36Sopenharmony_ci	pi->power_gating = false;
415962306a36Sopenharmony_ci
416062306a36Sopenharmony_ci	pi->gfx_clock_gating = true;
416162306a36Sopenharmony_ci
416262306a36Sopenharmony_ci	pi->mg_clock_gating = true;
416362306a36Sopenharmony_ci	pi->mgcgtssm = true;
416462306a36Sopenharmony_ci	eg_pi->ls_clock_gating = false;
416562306a36Sopenharmony_ci	eg_pi->sclk_deep_sleep = false;
416662306a36Sopenharmony_ci
416762306a36Sopenharmony_ci	pi->dynamic_pcie_gen2 = true;
416862306a36Sopenharmony_ci
416962306a36Sopenharmony_ci	if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
417062306a36Sopenharmony_ci		pi->thermal_protection = true;
417162306a36Sopenharmony_ci	else
417262306a36Sopenharmony_ci		pi->thermal_protection = false;
417362306a36Sopenharmony_ci
417462306a36Sopenharmony_ci	pi->display_gap = true;
417562306a36Sopenharmony_ci
417662306a36Sopenharmony_ci	pi->dcodt = true;
417762306a36Sopenharmony_ci
417862306a36Sopenharmony_ci	pi->ulps = true;
417962306a36Sopenharmony_ci
418062306a36Sopenharmony_ci	eg_pi->dynamic_ac_timing = true;
418162306a36Sopenharmony_ci	eg_pi->abm = true;
418262306a36Sopenharmony_ci	eg_pi->mcls = true;
418362306a36Sopenharmony_ci	eg_pi->light_sleep = true;
418462306a36Sopenharmony_ci	eg_pi->memory_transition = true;
418562306a36Sopenharmony_ci#if defined(CONFIG_ACPI)
418662306a36Sopenharmony_ci	eg_pi->pcie_performance_request =
418762306a36Sopenharmony_ci		radeon_acpi_is_pcie_performance_request_supported(rdev);
418862306a36Sopenharmony_ci#else
418962306a36Sopenharmony_ci	eg_pi->pcie_performance_request = false;
419062306a36Sopenharmony_ci#endif
419162306a36Sopenharmony_ci
419262306a36Sopenharmony_ci	eg_pi->dll_default_on = false;
419362306a36Sopenharmony_ci
419462306a36Sopenharmony_ci	eg_pi->sclk_deep_sleep = false;
419562306a36Sopenharmony_ci
419662306a36Sopenharmony_ci	pi->mclk_stutter_mode_threshold = 0;
419762306a36Sopenharmony_ci
419862306a36Sopenharmony_ci	pi->sram_end = SMC_RAM_END;
419962306a36Sopenharmony_ci
420062306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.mclk_sclk_ratio = 3;
420162306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.vddc_vddci_delta = 200;
420262306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.min_vddc_for_pcie_gen2 = 900;
420362306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_sclk_values.count = ARRAY_SIZE(btc_valid_sclk);
420462306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_sclk_values.values = btc_valid_sclk;
420562306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_mclk_values.count = 0;
420662306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.valid_mclk_values.values = NULL;
420762306a36Sopenharmony_ci	rdev->pm.dpm.dyn_state.sclk_mclk_delta = 12500;
420862306a36Sopenharmony_ci
420962306a36Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.at = 516;
421062306a36Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.bt = 18;
421162306a36Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.av = 51;
421262306a36Sopenharmony_ci	ni_pi->cac_data.leakage_coefficients.bv = 2957;
421362306a36Sopenharmony_ci
421462306a36Sopenharmony_ci	switch (rdev->pdev->device) {
421562306a36Sopenharmony_ci	case 0x6700:
421662306a36Sopenharmony_ci	case 0x6701:
421762306a36Sopenharmony_ci	case 0x6702:
421862306a36Sopenharmony_ci	case 0x6703:
421962306a36Sopenharmony_ci	case 0x6718:
422062306a36Sopenharmony_ci		ni_pi->cac_weights = &cac_weights_cayman_xt;
422162306a36Sopenharmony_ci		break;
422262306a36Sopenharmony_ci	case 0x6705:
422362306a36Sopenharmony_ci	case 0x6719:
422462306a36Sopenharmony_ci	case 0x671D:
422562306a36Sopenharmony_ci	case 0x671C:
422662306a36Sopenharmony_ci	default:
422762306a36Sopenharmony_ci		ni_pi->cac_weights = &cac_weights_cayman_pro;
422862306a36Sopenharmony_ci		break;
422962306a36Sopenharmony_ci	case 0x6704:
423062306a36Sopenharmony_ci	case 0x6706:
423162306a36Sopenharmony_ci	case 0x6707:
423262306a36Sopenharmony_ci	case 0x6708:
423362306a36Sopenharmony_ci	case 0x6709:
423462306a36Sopenharmony_ci		ni_pi->cac_weights = &cac_weights_cayman_le;
423562306a36Sopenharmony_ci		break;
423662306a36Sopenharmony_ci	}
423762306a36Sopenharmony_ci
423862306a36Sopenharmony_ci	if (ni_pi->cac_weights->enable_power_containment_by_default) {
423962306a36Sopenharmony_ci		ni_pi->enable_power_containment = true;
424062306a36Sopenharmony_ci		ni_pi->enable_cac = true;
424162306a36Sopenharmony_ci		ni_pi->enable_sq_ramping = true;
424262306a36Sopenharmony_ci	} else {
424362306a36Sopenharmony_ci		ni_pi->enable_power_containment = false;
424462306a36Sopenharmony_ci		ni_pi->enable_cac = false;
424562306a36Sopenharmony_ci		ni_pi->enable_sq_ramping = false;
424662306a36Sopenharmony_ci	}
424762306a36Sopenharmony_ci
424862306a36Sopenharmony_ci	ni_pi->driver_calculate_cac_leakage = false;
424962306a36Sopenharmony_ci	ni_pi->cac_configuration_required = true;
425062306a36Sopenharmony_ci
425162306a36Sopenharmony_ci	if (ni_pi->cac_configuration_required) {
425262306a36Sopenharmony_ci		ni_pi->support_cac_long_term_average = true;
425362306a36Sopenharmony_ci		ni_pi->lta_window_size = ni_pi->cac_weights->l2_lta_window_size;
425462306a36Sopenharmony_ci		ni_pi->lts_truncate = ni_pi->cac_weights->lts_truncate;
425562306a36Sopenharmony_ci	} else {
425662306a36Sopenharmony_ci		ni_pi->support_cac_long_term_average = false;
425762306a36Sopenharmony_ci		ni_pi->lta_window_size = 0;
425862306a36Sopenharmony_ci		ni_pi->lts_truncate = 0;
425962306a36Sopenharmony_ci	}
426062306a36Sopenharmony_ci
426162306a36Sopenharmony_ci	ni_pi->use_power_boost_limit = true;
426262306a36Sopenharmony_ci
426362306a36Sopenharmony_ci	/* make sure dc limits are valid */
426462306a36Sopenharmony_ci	if ((rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) ||
426562306a36Sopenharmony_ci	    (rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0))
426662306a36Sopenharmony_ci		rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc =
426762306a36Sopenharmony_ci			rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac;
426862306a36Sopenharmony_ci
426962306a36Sopenharmony_ci	return 0;
427062306a36Sopenharmony_ci}
427162306a36Sopenharmony_ci
427262306a36Sopenharmony_civoid ni_dpm_fini(struct radeon_device *rdev)
427362306a36Sopenharmony_ci{
427462306a36Sopenharmony_ci	int i;
427562306a36Sopenharmony_ci
427662306a36Sopenharmony_ci	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
427762306a36Sopenharmony_ci		kfree(rdev->pm.dpm.ps[i].ps_priv);
427862306a36Sopenharmony_ci	}
427962306a36Sopenharmony_ci	kfree(rdev->pm.dpm.ps);
428062306a36Sopenharmony_ci	kfree(rdev->pm.dpm.priv);
428162306a36Sopenharmony_ci	kfree(rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries);
428262306a36Sopenharmony_ci	r600_free_extended_power_table(rdev);
428362306a36Sopenharmony_ci}
428462306a36Sopenharmony_ci
428562306a36Sopenharmony_civoid ni_dpm_print_power_state(struct radeon_device *rdev,
428662306a36Sopenharmony_ci			      struct radeon_ps *rps)
428762306a36Sopenharmony_ci{
428862306a36Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
428962306a36Sopenharmony_ci	struct rv7xx_pl *pl;
429062306a36Sopenharmony_ci	int i;
429162306a36Sopenharmony_ci
429262306a36Sopenharmony_ci	r600_dpm_print_class_info(rps->class, rps->class2);
429362306a36Sopenharmony_ci	r600_dpm_print_cap_info(rps->caps);
429462306a36Sopenharmony_ci	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
429562306a36Sopenharmony_ci	for (i = 0; i < ps->performance_level_count; i++) {
429662306a36Sopenharmony_ci		pl = &ps->performance_levels[i];
429762306a36Sopenharmony_ci		if (rdev->family >= CHIP_TAHITI)
429862306a36Sopenharmony_ci			printk("\t\tpower level %d    sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n",
429962306a36Sopenharmony_ci			       i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1);
430062306a36Sopenharmony_ci		else
430162306a36Sopenharmony_ci			printk("\t\tpower level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
430262306a36Sopenharmony_ci			       i, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
430362306a36Sopenharmony_ci	}
430462306a36Sopenharmony_ci	r600_dpm_print_ps_status(rdev, rps);
430562306a36Sopenharmony_ci}
430662306a36Sopenharmony_ci
430762306a36Sopenharmony_civoid ni_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
430862306a36Sopenharmony_ci						    struct seq_file *m)
430962306a36Sopenharmony_ci{
431062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
431162306a36Sopenharmony_ci	struct radeon_ps *rps = &eg_pi->current_rps;
431262306a36Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
431362306a36Sopenharmony_ci	struct rv7xx_pl *pl;
431462306a36Sopenharmony_ci	u32 current_index =
431562306a36Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
431662306a36Sopenharmony_ci		CURRENT_STATE_INDEX_SHIFT;
431762306a36Sopenharmony_ci
431862306a36Sopenharmony_ci	if (current_index >= ps->performance_level_count) {
431962306a36Sopenharmony_ci		seq_printf(m, "invalid dpm profile %d\n", current_index);
432062306a36Sopenharmony_ci	} else {
432162306a36Sopenharmony_ci		pl = &ps->performance_levels[current_index];
432262306a36Sopenharmony_ci		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
432362306a36Sopenharmony_ci		seq_printf(m, "power level %d    sclk: %u mclk: %u vddc: %u vddci: %u\n",
432462306a36Sopenharmony_ci			   current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
432562306a36Sopenharmony_ci	}
432662306a36Sopenharmony_ci}
432762306a36Sopenharmony_ci
432862306a36Sopenharmony_ciu32 ni_dpm_get_current_sclk(struct radeon_device *rdev)
432962306a36Sopenharmony_ci{
433062306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
433162306a36Sopenharmony_ci	struct radeon_ps *rps = &eg_pi->current_rps;
433262306a36Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
433362306a36Sopenharmony_ci	struct rv7xx_pl *pl;
433462306a36Sopenharmony_ci	u32 current_index =
433562306a36Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
433662306a36Sopenharmony_ci		CURRENT_STATE_INDEX_SHIFT;
433762306a36Sopenharmony_ci
433862306a36Sopenharmony_ci	if (current_index >= ps->performance_level_count) {
433962306a36Sopenharmony_ci		return 0;
434062306a36Sopenharmony_ci	} else {
434162306a36Sopenharmony_ci		pl = &ps->performance_levels[current_index];
434262306a36Sopenharmony_ci		return pl->sclk;
434362306a36Sopenharmony_ci	}
434462306a36Sopenharmony_ci}
434562306a36Sopenharmony_ci
434662306a36Sopenharmony_ciu32 ni_dpm_get_current_mclk(struct radeon_device *rdev)
434762306a36Sopenharmony_ci{
434862306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
434962306a36Sopenharmony_ci	struct radeon_ps *rps = &eg_pi->current_rps;
435062306a36Sopenharmony_ci	struct ni_ps *ps = ni_get_ps(rps);
435162306a36Sopenharmony_ci	struct rv7xx_pl *pl;
435262306a36Sopenharmony_ci	u32 current_index =
435362306a36Sopenharmony_ci		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >>
435462306a36Sopenharmony_ci		CURRENT_STATE_INDEX_SHIFT;
435562306a36Sopenharmony_ci
435662306a36Sopenharmony_ci	if (current_index >= ps->performance_level_count) {
435762306a36Sopenharmony_ci		return 0;
435862306a36Sopenharmony_ci	} else {
435962306a36Sopenharmony_ci		pl = &ps->performance_levels[current_index];
436062306a36Sopenharmony_ci		return pl->mclk;
436162306a36Sopenharmony_ci	}
436262306a36Sopenharmony_ci}
436362306a36Sopenharmony_ci
436462306a36Sopenharmony_ciu32 ni_dpm_get_sclk(struct radeon_device *rdev, bool low)
436562306a36Sopenharmony_ci{
436662306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
436762306a36Sopenharmony_ci	struct ni_ps *requested_state = ni_get_ps(&eg_pi->requested_rps);
436862306a36Sopenharmony_ci
436962306a36Sopenharmony_ci	if (low)
437062306a36Sopenharmony_ci		return requested_state->performance_levels[0].sclk;
437162306a36Sopenharmony_ci	else
437262306a36Sopenharmony_ci		return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk;
437362306a36Sopenharmony_ci}
437462306a36Sopenharmony_ci
437562306a36Sopenharmony_ciu32 ni_dpm_get_mclk(struct radeon_device *rdev, bool low)
437662306a36Sopenharmony_ci{
437762306a36Sopenharmony_ci	struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
437862306a36Sopenharmony_ci	struct ni_ps *requested_state = ni_get_ps(&eg_pi->requested_rps);
437962306a36Sopenharmony_ci
438062306a36Sopenharmony_ci	if (low)
438162306a36Sopenharmony_ci		return requested_state->performance_levels[0].mclk;
438262306a36Sopenharmony_ci	else
438362306a36Sopenharmony_ci		return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk;
438462306a36Sopenharmony_ci}
438562306a36Sopenharmony_ci
4386