Home | History | Annotate | Line # | Download | only in radeon
radeon_trinity_dpm.c revision 1.1.6.3
      1 /*	$NetBSD: radeon_trinity_dpm.c,v 1.1.6.3 2020/04/08 14:08:26 martin Exp $	*/
      2 
      3 /*
      4  * Copyright 2012 Advanced Micro Devices, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  */
     25 
     26 #include <sys/cdefs.h>
     27 __KERNEL_RCSID(0, "$NetBSD: radeon_trinity_dpm.c,v 1.1.6.3 2020/04/08 14:08:26 martin Exp $");
     28 
     29 #include "drmP.h"
     30 #include "radeon.h"
     31 #include "radeon_asic.h"
     32 #include "trinityd.h"
     33 #include "r600_dpm.h"
     34 #include "trinity_dpm.h"
     35 #include <linux/seq_file.h>
     36 
     37 #define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5
     38 #define TRINITY_MINIMUM_ENGINE_CLOCK 800
     39 #define SCLK_MIN_DIV_INTV_SHIFT     12
     40 #define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000
     41 
     42 #ifndef TRINITY_MGCG_SEQUENCE
     43 #define TRINITY_MGCG_SEQUENCE  100
     44 
     45 static const u32 trinity_mgcg_shls_default[] =
     46 {
     47 	/* Register, Value, Mask */
     48 	0x0000802c, 0xc0000000, 0xffffffff,
     49 	0x00003fc4, 0xc0000000, 0xffffffff,
     50 	0x00005448, 0x00000100, 0xffffffff,
     51 	0x000055e4, 0x00000100, 0xffffffff,
     52 	0x0000160c, 0x00000100, 0xffffffff,
     53 	0x00008984, 0x06000100, 0xffffffff,
     54 	0x0000c164, 0x00000100, 0xffffffff,
     55 	0x00008a18, 0x00000100, 0xffffffff,
     56 	0x0000897c, 0x06000100, 0xffffffff,
     57 	0x00008b28, 0x00000100, 0xffffffff,
     58 	0x00009144, 0x00800200, 0xffffffff,
     59 	0x00009a60, 0x00000100, 0xffffffff,
     60 	0x00009868, 0x00000100, 0xffffffff,
     61 	0x00008d58, 0x00000100, 0xffffffff,
     62 	0x00009510, 0x00000100, 0xffffffff,
     63 	0x0000949c, 0x00000100, 0xffffffff,
     64 	0x00009654, 0x00000100, 0xffffffff,
     65 	0x00009030, 0x00000100, 0xffffffff,
     66 	0x00009034, 0x00000100, 0xffffffff,
     67 	0x00009038, 0x00000100, 0xffffffff,
     68 	0x0000903c, 0x00000100, 0xffffffff,
     69 	0x00009040, 0x00000100, 0xffffffff,
     70 	0x0000a200, 0x00000100, 0xffffffff,
     71 	0x0000a204, 0x00000100, 0xffffffff,
     72 	0x0000a208, 0x00000100, 0xffffffff,
     73 	0x0000a20c, 0x00000100, 0xffffffff,
     74 	0x00009744, 0x00000100, 0xffffffff,
     75 	0x00003f80, 0x00000100, 0xffffffff,
     76 	0x0000a210, 0x00000100, 0xffffffff,
     77 	0x0000a214, 0x00000100, 0xffffffff,
     78 	0x000004d8, 0x00000100, 0xffffffff,
     79 	0x00009664, 0x00000100, 0xffffffff,
     80 	0x00009698, 0x00000100, 0xffffffff,
     81 	0x000004d4, 0x00000200, 0xffffffff,
     82 	0x000004d0, 0x00000000, 0xffffffff,
     83 	0x000030cc, 0x00000104, 0xffffffff,
     84 	0x0000d0c0, 0x00000100, 0xffffffff,
     85 	0x0000d8c0, 0x00000100, 0xffffffff,
     86 	0x0000951c, 0x00010000, 0xffffffff,
     87 	0x00009160, 0x00030002, 0xffffffff,
     88 	0x00009164, 0x00050004, 0xffffffff,
     89 	0x00009168, 0x00070006, 0xffffffff,
     90 	0x00009178, 0x00070000, 0xffffffff,
     91 	0x0000917c, 0x00030002, 0xffffffff,
     92 	0x00009180, 0x00050004, 0xffffffff,
     93 	0x0000918c, 0x00010006, 0xffffffff,
     94 	0x00009190, 0x00090008, 0xffffffff,
     95 	0x00009194, 0x00070000, 0xffffffff,
     96 	0x00009198, 0x00030002, 0xffffffff,
     97 	0x0000919c, 0x00050004, 0xffffffff,
     98 	0x000091a8, 0x00010006, 0xffffffff,
     99 	0x000091ac, 0x00090008, 0xffffffff,
    100 	0x000091b0, 0x00070000, 0xffffffff,
    101 	0x000091b4, 0x00030002, 0xffffffff,
    102 	0x000091b8, 0x00050004, 0xffffffff,
    103 	0x000091c4, 0x00010006, 0xffffffff,
    104 	0x000091c8, 0x00090008, 0xffffffff,
    105 	0x000091cc, 0x00070000, 0xffffffff,
    106 	0x000091d0, 0x00030002, 0xffffffff,
    107 	0x000091d4, 0x00050004, 0xffffffff,
    108 	0x000091e0, 0x00010006, 0xffffffff,
    109 	0x000091e4, 0x00090008, 0xffffffff,
    110 	0x000091e8, 0x00000000, 0xffffffff,
    111 	0x000091ec, 0x00070000, 0xffffffff,
    112 	0x000091f0, 0x00030002, 0xffffffff,
    113 	0x000091f4, 0x00050004, 0xffffffff,
    114 	0x00009200, 0x00010006, 0xffffffff,
    115 	0x00009204, 0x00090008, 0xffffffff,
    116 	0x00009208, 0x00070000, 0xffffffff,
    117 	0x0000920c, 0x00030002, 0xffffffff,
    118 	0x00009210, 0x00050004, 0xffffffff,
    119 	0x0000921c, 0x00010006, 0xffffffff,
    120 	0x00009220, 0x00090008, 0xffffffff,
    121 	0x00009294, 0x00000000, 0xffffffff
    122 };
    123 
    124 static const u32 trinity_mgcg_shls_enable[] =
    125 {
    126 	/* Register, Value, Mask */
    127 	0x0000802c, 0xc0000000, 0xffffffff,
    128 	0x000008f8, 0x00000000, 0xffffffff,
    129 	0x000008fc, 0x00000000, 0x000133FF,
    130 	0x000008f8, 0x00000001, 0xffffffff,
    131 	0x000008fc, 0x00000000, 0xE00B03FC,
    132 	0x00009150, 0x96944200, 0xffffffff
    133 };
    134 
    135 static const u32 trinity_mgcg_shls_disable[] =
    136 {
    137 	/* Register, Value, Mask */
    138 	0x0000802c, 0xc0000000, 0xffffffff,
    139 	0x00009150, 0x00600000, 0xffffffff,
    140 	0x000008f8, 0x00000000, 0xffffffff,
    141 	0x000008fc, 0xffffffff, 0x000133FF,
    142 	0x000008f8, 0x00000001, 0xffffffff,
    143 	0x000008fc, 0xffffffff, 0xE00B03FC
    144 };
    145 #endif
    146 
    147 #ifndef TRINITY_SYSLS_SEQUENCE
    148 #define TRINITY_SYSLS_SEQUENCE  100
    149 
    150 static const u32 trinity_sysls_default[] =
    151 {
    152 	/* Register, Value, Mask */
    153 	0x000055e8, 0x00000000, 0xffffffff,
    154 	0x0000d0bc, 0x00000000, 0xffffffff,
    155 	0x0000d8bc, 0x00000000, 0xffffffff,
    156 	0x000015c0, 0x000c1401, 0xffffffff,
    157 	0x0000264c, 0x000c0400, 0xffffffff,
    158 	0x00002648, 0x000c0400, 0xffffffff,
    159 	0x00002650, 0x000c0400, 0xffffffff,
    160 	0x000020b8, 0x000c0400, 0xffffffff,
    161 	0x000020bc, 0x000c0400, 0xffffffff,
    162 	0x000020c0, 0x000c0c80, 0xffffffff,
    163 	0x0000f4a0, 0x000000c0, 0xffffffff,
    164 	0x0000f4a4, 0x00680fff, 0xffffffff,
    165 	0x00002f50, 0x00000404, 0xffffffff,
    166 	0x000004c8, 0x00000001, 0xffffffff,
    167 	0x0000641c, 0x00000000, 0xffffffff,
    168 	0x00000c7c, 0x00000000, 0xffffffff,
    169 	0x00006dfc, 0x00000000, 0xffffffff
    170 };
    171 
    172 static const u32 trinity_sysls_disable[] =
    173 {
    174 	/* Register, Value, Mask */
    175 	0x0000d0c0, 0x00000000, 0xffffffff,
    176 	0x0000d8c0, 0x00000000, 0xffffffff,
    177 	0x000055e8, 0x00000000, 0xffffffff,
    178 	0x0000d0bc, 0x00000000, 0xffffffff,
    179 	0x0000d8bc, 0x00000000, 0xffffffff,
    180 	0x000015c0, 0x00041401, 0xffffffff,
    181 	0x0000264c, 0x00040400, 0xffffffff,
    182 	0x00002648, 0x00040400, 0xffffffff,
    183 	0x00002650, 0x00040400, 0xffffffff,
    184 	0x000020b8, 0x00040400, 0xffffffff,
    185 	0x000020bc, 0x00040400, 0xffffffff,
    186 	0x000020c0, 0x00040c80, 0xffffffff,
    187 	0x0000f4a0, 0x000000c0, 0xffffffff,
    188 	0x0000f4a4, 0x00680000, 0xffffffff,
    189 	0x00002f50, 0x00000404, 0xffffffff,
    190 	0x000004c8, 0x00000001, 0xffffffff,
    191 	0x0000641c, 0x00007ffd, 0xffffffff,
    192 	0x00000c7c, 0x0000ff00, 0xffffffff,
    193 	0x00006dfc, 0x0000007f, 0xffffffff
    194 };
    195 
    196 static const u32 trinity_sysls_enable[] =
    197 {
    198 	/* Register, Value, Mask */
    199 	0x000055e8, 0x00000001, 0xffffffff,
    200 	0x0000d0bc, 0x00000100, 0xffffffff,
    201 	0x0000d8bc, 0x00000100, 0xffffffff,
    202 	0x000015c0, 0x000c1401, 0xffffffff,
    203 	0x0000264c, 0x000c0400, 0xffffffff,
    204 	0x00002648, 0x000c0400, 0xffffffff,
    205 	0x00002650, 0x000c0400, 0xffffffff,
    206 	0x000020b8, 0x000c0400, 0xffffffff,
    207 	0x000020bc, 0x000c0400, 0xffffffff,
    208 	0x000020c0, 0x000c0c80, 0xffffffff,
    209 	0x0000f4a0, 0x000000c0, 0xffffffff,
    210 	0x0000f4a4, 0x00680fff, 0xffffffff,
    211 	0x00002f50, 0x00000903, 0xffffffff,
    212 	0x000004c8, 0x00000000, 0xffffffff,
    213 	0x0000641c, 0x00000000, 0xffffffff,
    214 	0x00000c7c, 0x00000000, 0xffffffff,
    215 	0x00006dfc, 0x00000000, 0xffffffff
    216 };
    217 #endif
    218 
    219 static const u32 trinity_override_mgpg_sequences[] =
    220 {
    221 	/* Register, Value */
    222 	0x00000200, 0xE030032C,
    223 	0x00000204, 0x00000FFF,
    224 	0x00000200, 0xE0300058,
    225 	0x00000204, 0x00030301,
    226 	0x00000200, 0xE0300054,
    227 	0x00000204, 0x500010FF,
    228 	0x00000200, 0xE0300074,
    229 	0x00000204, 0x00030301,
    230 	0x00000200, 0xE0300070,
    231 	0x00000204, 0x500010FF,
    232 	0x00000200, 0xE0300090,
    233 	0x00000204, 0x00030301,
    234 	0x00000200, 0xE030008C,
    235 	0x00000204, 0x500010FF,
    236 	0x00000200, 0xE03000AC,
    237 	0x00000204, 0x00030301,
    238 	0x00000200, 0xE03000A8,
    239 	0x00000204, 0x500010FF,
    240 	0x00000200, 0xE03000C8,
    241 	0x00000204, 0x00030301,
    242 	0x00000200, 0xE03000C4,
    243 	0x00000204, 0x500010FF,
    244 	0x00000200, 0xE03000E4,
    245 	0x00000204, 0x00030301,
    246 	0x00000200, 0xE03000E0,
    247 	0x00000204, 0x500010FF,
    248 	0x00000200, 0xE0300100,
    249 	0x00000204, 0x00030301,
    250 	0x00000200, 0xE03000FC,
    251 	0x00000204, 0x500010FF,
    252 	0x00000200, 0xE0300058,
    253 	0x00000204, 0x00030303,
    254 	0x00000200, 0xE0300054,
    255 	0x00000204, 0x600010FF,
    256 	0x00000200, 0xE0300074,
    257 	0x00000204, 0x00030303,
    258 	0x00000200, 0xE0300070,
    259 	0x00000204, 0x600010FF,
    260 	0x00000200, 0xE0300090,
    261 	0x00000204, 0x00030303,
    262 	0x00000200, 0xE030008C,
    263 	0x00000204, 0x600010FF,
    264 	0x00000200, 0xE03000AC,
    265 	0x00000204, 0x00030303,
    266 	0x00000200, 0xE03000A8,
    267 	0x00000204, 0x600010FF,
    268 	0x00000200, 0xE03000C8,
    269 	0x00000204, 0x00030303,
    270 	0x00000200, 0xE03000C4,
    271 	0x00000204, 0x600010FF,
    272 	0x00000200, 0xE03000E4,
    273 	0x00000204, 0x00030303,
    274 	0x00000200, 0xE03000E0,
    275 	0x00000204, 0x600010FF,
    276 	0x00000200, 0xE0300100,
    277 	0x00000204, 0x00030303,
    278 	0x00000200, 0xE03000FC,
    279 	0x00000204, 0x600010FF,
    280 	0x00000200, 0xE0300058,
    281 	0x00000204, 0x00030303,
    282 	0x00000200, 0xE0300054,
    283 	0x00000204, 0x700010FF,
    284 	0x00000200, 0xE0300074,
    285 	0x00000204, 0x00030303,
    286 	0x00000200, 0xE0300070,
    287 	0x00000204, 0x700010FF,
    288 	0x00000200, 0xE0300090,
    289 	0x00000204, 0x00030303,
    290 	0x00000200, 0xE030008C,
    291 	0x00000204, 0x700010FF,
    292 	0x00000200, 0xE03000AC,
    293 	0x00000204, 0x00030303,
    294 	0x00000200, 0xE03000A8,
    295 	0x00000204, 0x700010FF,
    296 	0x00000200, 0xE03000C8,
    297 	0x00000204, 0x00030303,
    298 	0x00000200, 0xE03000C4,
    299 	0x00000204, 0x700010FF,
    300 	0x00000200, 0xE03000E4,
    301 	0x00000204, 0x00030303,
    302 	0x00000200, 0xE03000E0,
    303 	0x00000204, 0x700010FF,
    304 	0x00000200, 0xE0300100,
    305 	0x00000204, 0x00030303,
    306 	0x00000200, 0xE03000FC,
    307 	0x00000204, 0x700010FF,
    308 	0x00000200, 0xE0300058,
    309 	0x00000204, 0x00010303,
    310 	0x00000200, 0xE0300054,
    311 	0x00000204, 0x800010FF,
    312 	0x00000200, 0xE0300074,
    313 	0x00000204, 0x00010303,
    314 	0x00000200, 0xE0300070,
    315 	0x00000204, 0x800010FF,
    316 	0x00000200, 0xE0300090,
    317 	0x00000204, 0x00010303,
    318 	0x00000200, 0xE030008C,
    319 	0x00000204, 0x800010FF,
    320 	0x00000200, 0xE03000AC,
    321 	0x00000204, 0x00010303,
    322 	0x00000200, 0xE03000A8,
    323 	0x00000204, 0x800010FF,
    324 	0x00000200, 0xE03000C4,
    325 	0x00000204, 0x800010FF,
    326 	0x00000200, 0xE03000C8,
    327 	0x00000204, 0x00010303,
    328 	0x00000200, 0xE03000E4,
    329 	0x00000204, 0x00010303,
    330 	0x00000200, 0xE03000E0,
    331 	0x00000204, 0x800010FF,
    332 	0x00000200, 0xE0300100,
    333 	0x00000204, 0x00010303,
    334 	0x00000200, 0xE03000FC,
    335 	0x00000204, 0x800010FF,
    336 	0x00000200, 0x0001f198,
    337 	0x00000204, 0x0003ffff,
    338 	0x00000200, 0x0001f19C,
    339 	0x00000204, 0x3fffffff,
    340 	0x00000200, 0xE030032C,
    341 	0x00000204, 0x00000000,
    342 };
    343 
    344 extern void vce_v1_0_enable_mgcg(struct radeon_device *rdev, bool enable);
    345 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
    346 						   const u32 *seq, u32 count);
    347 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
    348 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
    349 					     struct radeon_ps *new_rps,
    350 					     struct radeon_ps *old_rps);
    351 
    352 static struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
    353 {
    354 	struct trinity_ps *ps = rps->ps_priv;
    355 
    356 	return ps;
    357 }
    358 
    359 static struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
    360 {
    361 	struct trinity_power_info *pi = rdev->pm.dpm.priv;
    362 
    363 	return pi;
    364 }
    365 
    366 static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
    367 {
    368 	struct trinity_power_info *pi = trinity_get_pi(rdev);
    369 	u32 p, u;
    370 	u32 value;
    371 	struct atom_clock_dividers dividers;
    372 	u32 xclk = radeon_get_xclk(rdev);
    373 	u32 sssd = 1;
    374 	int ret;
    375 	u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
    376 
    377         ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
    378                                              25000, false, &dividers);
    379 	if (ret)
    380 		return;
    381 
    382 	value = RREG32_SMC(GFX_POWER_GATING_CNTL);
    383 	value &= ~(SSSD_MASK | PDS_DIV_MASK);
    384 	if (sssd)
    385 		value |= SSSD(1);
    386 	value |= PDS_DIV(dividers.post_div);
    387 	WREG32_SMC(GFX_POWER_GATING_CNTL, value);
    388 
    389 	r600_calculate_u_and_p(500, xclk, 16, &p, &u);
    390 
    391 	WREG32(CG_PG_CTRL, SP(p) | SU(u));
    392 
    393 	WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK);
    394 
    395 	/* XXX double check hw_rev */
    396 	if (pi->override_dynamic_mgpg && (hw_rev == 0))
    397 		trinity_override_dynamic_mg_powergating(rdev);
    398 
    399 }
    400 
    401 #define CGCG_CGTT_LOCAL0_MASK       0xFFFF33FF
    402 #define CGCG_CGTT_LOCAL1_MASK       0xFFFB0FFE
    403 #define CGTS_SM_CTRL_REG_DISABLE    0x00600000
    404 #define CGTS_SM_CTRL_REG_ENABLE     0x96944200
    405 
    406 static void trinity_mg_clockgating_enable(struct radeon_device *rdev,
    407 					  bool enable)
    408 {
    409 	u32 local0;
    410 	u32 local1;
    411 
    412 	if (enable) {
    413 		local0 = RREG32_CG(CG_CGTT_LOCAL_0);
    414 		local1 = RREG32_CG(CG_CGTT_LOCAL_1);
    415 
    416 		WREG32_CG(CG_CGTT_LOCAL_0,
    417 			  (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
    418 		WREG32_CG(CG_CGTT_LOCAL_1,
    419 			  (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
    420 
    421 		WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE);
    422 	} else {
    423 		WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE);
    424 
    425 		local0 = RREG32_CG(CG_CGTT_LOCAL_0);
    426 		local1 = RREG32_CG(CG_CGTT_LOCAL_1);
    427 
    428 		WREG32_CG(CG_CGTT_LOCAL_0,
    429 			  CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
    430 		WREG32_CG(CG_CGTT_LOCAL_1,
    431 			  CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
    432 	}
    433 }
    434 
    435 static void trinity_mg_clockgating_initialize(struct radeon_device *rdev)
    436 {
    437 	u32 count;
    438 	const u32 *seq = NULL;
    439 
    440 	seq = &trinity_mgcg_shls_default[0];
    441 	count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32));
    442 
    443 	trinity_program_clk_gating_hw_sequence(rdev, seq, count);
    444 }
    445 
    446 static void trinity_gfx_clockgating_enable(struct radeon_device *rdev,
    447 					   bool enable)
    448 {
    449 	if (enable) {
    450 		WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
    451 	} else {
    452 		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
    453 		WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
    454 		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
    455 		RREG32(GB_ADDR_CONFIG);
    456 	}
    457 }
    458 
    459 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
    460 						   const u32 *seq, u32 count)
    461 {
    462 	u32 i, length = count * 3;
    463 
    464 	for (i = 0; i < length; i += 3)
    465 		WREG32_P(seq[i], seq[i+1], ~seq[i+2]);
    466 }
    467 
    468 static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev,
    469 						    const u32 *seq, u32 count)
    470 {
    471 	u32  i, length = count * 2;
    472 
    473 	for (i = 0; i < length; i += 2)
    474 		WREG32(seq[i], seq[i+1]);
    475 
    476 }
    477 
    478 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev)
    479 {
    480 	u32 count;
    481 	const u32 *seq = NULL;
    482 
    483 	seq = &trinity_override_mgpg_sequences[0];
    484 	count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32));
    485 
    486 	trinity_program_override_mgpg_sequences(rdev, seq, count);
    487 }
    488 
    489 static void trinity_ls_clockgating_enable(struct radeon_device *rdev,
    490 					  bool enable)
    491 {
    492 	u32 count;
    493 	const u32 *seq = NULL;
    494 
    495 	if (enable) {
    496 		seq = &trinity_sysls_enable[0];
    497 		count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32));
    498 	} else {
    499 		seq = &trinity_sysls_disable[0];
    500 		count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32));
    501 	}
    502 
    503 	trinity_program_clk_gating_hw_sequence(rdev, seq, count);
    504 }
    505 
    506 static void trinity_gfx_powergating_enable(struct radeon_device *rdev,
    507 					   bool enable)
    508 {
    509 	if (enable) {
    510 		if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK)
    511 			WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01));
    512 
    513 		WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
    514 	} else {
    515 		WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN);
    516 		RREG32(GB_ADDR_CONFIG);
    517 	}
    518 }
    519 
    520 static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev,
    521 					    bool enable)
    522 {
    523 	u32 value;
    524 
    525 	if (enable) {
    526 		value = RREG32_SMC(PM_I_CNTL_1);
    527 		value &= ~DS_PG_CNTL_MASK;
    528 		value |= DS_PG_CNTL(1);
    529 		WREG32_SMC(PM_I_CNTL_1, value);
    530 
    531 		value = RREG32_SMC(SMU_S_PG_CNTL);
    532 		value &= ~DS_PG_EN_MASK;
    533 		value |= DS_PG_EN(1);
    534 		WREG32_SMC(SMU_S_PG_CNTL, value);
    535 	} else {
    536 		value = RREG32_SMC(SMU_S_PG_CNTL);
    537 		value &= ~DS_PG_EN_MASK;
    538 		WREG32_SMC(SMU_S_PG_CNTL, value);
    539 
    540 		value = RREG32_SMC(PM_I_CNTL_1);
    541 		value &= ~DS_PG_CNTL_MASK;
    542 		WREG32_SMC(PM_I_CNTL_1, value);
    543 	}
    544 
    545 	trinity_gfx_dynamic_mgpg_config(rdev);
    546 
    547 }
    548 
    549 static void trinity_enable_clock_power_gating(struct radeon_device *rdev)
    550 {
    551 	struct trinity_power_info *pi = trinity_get_pi(rdev);
    552 
    553 	if (pi->enable_gfx_clock_gating)
    554 		sumo_gfx_clockgating_initialize(rdev);
    555 	if (pi->enable_mg_clock_gating)
    556 		trinity_mg_clockgating_initialize(rdev);
    557 	if (pi->enable_gfx_power_gating)
    558 		trinity_gfx_powergating_initialize(rdev);
    559 	if (pi->enable_mg_clock_gating) {
    560 		trinity_ls_clockgating_enable(rdev, true);
    561 		trinity_mg_clockgating_enable(rdev, true);
    562 	}
    563 	if (pi->enable_gfx_clock_gating)
    564 		trinity_gfx_clockgating_enable(rdev, true);
    565 	if (pi->enable_gfx_dynamic_mgpg)
    566 		trinity_gfx_dynamic_mgpg_enable(rdev, true);
    567 	if (pi->enable_gfx_power_gating)
    568 		trinity_gfx_powergating_enable(rdev, true);
    569 }
    570 
    571 static void trinity_disable_clock_power_gating(struct radeon_device *rdev)
    572 {
    573 	struct trinity_power_info *pi = trinity_get_pi(rdev);
    574 
    575 	if (pi->enable_gfx_power_gating)
    576 		trinity_gfx_powergating_enable(rdev, false);
    577 	if (pi->enable_gfx_dynamic_mgpg)
    578 		trinity_gfx_dynamic_mgpg_enable(rdev, false);
    579 	if (pi->enable_gfx_clock_gating)
    580 		trinity_gfx_clockgating_enable(rdev, false);
    581 	if (pi->enable_mg_clock_gating) {
    582 		trinity_mg_clockgating_enable(rdev, false);
    583 		trinity_ls_clockgating_enable(rdev, false);
    584 	}
    585 }
    586 
    587 static void trinity_set_divider_value(struct radeon_device *rdev,
    588 				      u32 index, u32 sclk)
    589 {
    590 	struct atom_clock_dividers  dividers;
    591 	int ret;
    592 	u32 value;
    593 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    594 
    595         ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
    596                                              sclk, false, &dividers);
    597 	if (ret)
    598 		return;
    599 
    600 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
    601 	value &= ~CLK_DIVIDER_MASK;
    602 	value |= CLK_DIVIDER(dividers.post_div);
    603 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
    604 
    605         ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
    606                                              sclk/2, false, &dividers);
    607 	if (ret)
    608 		return;
    609 
    610 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix);
    611 	value &= ~PD_SCLK_DIVIDER_MASK;
    612 	value |= PD_SCLK_DIVIDER(dividers.post_div);
    613 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value);
    614 }
    615 
    616 static void trinity_set_ds_dividers(struct radeon_device *rdev,
    617 				    u32 index, u32 divider)
    618 {
    619 	u32 value;
    620 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    621 
    622 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
    623 	value &= ~DS_DIV_MASK;
    624 	value |= DS_DIV(divider);
    625 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
    626 }
    627 
    628 static void trinity_set_ss_dividers(struct radeon_device *rdev,
    629 				    u32 index, u32 divider)
    630 {
    631 	u32 value;
    632 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    633 
    634 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
    635 	value &= ~DS_SH_DIV_MASK;
    636 	value |= DS_SH_DIV(divider);
    637 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
    638 }
    639 
    640 static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
    641 {
    642 	struct trinity_power_info *pi = trinity_get_pi(rdev);
    643 	u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid);
    644 	u32 value;
    645 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    646 
    647 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
    648 	value &= ~VID_MASK;
    649 	value |= VID(vid_7bit);
    650 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
    651 
    652 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
    653 	value &= ~LVRT_MASK;
    654 	value |= LVRT(0);
    655 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
    656 }
    657 
    658 static void trinity_set_allos_gnb_slow(struct radeon_device *rdev,
    659 				       u32 index, u32 gnb_slow)
    660 {
    661 	u32 value;
    662 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    663 
    664 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
    665 	value &= ~GNB_SLOW_MASK;
    666 	value |= GNB_SLOW(gnb_slow);
    667 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
    668 }
    669 
    670 static void trinity_set_force_nbp_state(struct radeon_device *rdev,
    671 					u32 index, u32 force_nbp_state)
    672 {
    673 	u32 value;
    674 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    675 
    676 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
    677 	value &= ~FORCE_NBPS1_MASK;
    678 	value |= FORCE_NBPS1(force_nbp_state);
    679 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
    680 }
    681 
    682 static void trinity_set_display_wm(struct radeon_device *rdev,
    683 				   u32 index, u32 wm)
    684 {
    685 	u32 value;
    686 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    687 
    688 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
    689 	value &= ~DISPLAY_WM_MASK;
    690 	value |= DISPLAY_WM(wm);
    691 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
    692 }
    693 
    694 static void trinity_set_vce_wm(struct radeon_device *rdev,
    695 			       u32 index, u32 wm)
    696 {
    697 	u32 value;
    698 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    699 
    700 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
    701 	value &= ~VCE_WM_MASK;
    702 	value |= VCE_WM(wm);
    703 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
    704 }
    705 
    706 static void trinity_set_at(struct radeon_device *rdev,
    707 			   u32 index, u32 at)
    708 {
    709 	u32 value;
    710 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    711 
    712 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix);
    713 	value &= ~AT_MASK;
    714 	value |= AT(at);
    715 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value);
    716 }
    717 
    718 static void trinity_program_power_level(struct radeon_device *rdev,
    719 					struct trinity_pl *pl, u32 index)
    720 {
    721 	struct trinity_power_info *pi = trinity_get_pi(rdev);
    722 
    723 	if (index >= SUMO_MAX_HARDWARE_POWERLEVELS)
    724 		return;
    725 
    726 	trinity_set_divider_value(rdev, index, pl->sclk);
    727 	trinity_set_vid(rdev, index, pl->vddc_index);
    728 	trinity_set_ss_dividers(rdev, index, pl->ss_divider_index);
    729 	trinity_set_ds_dividers(rdev, index, pl->ds_divider_index);
    730 	trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
    731 	trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state);
    732 	trinity_set_display_wm(rdev, index, pl->display_wm);
    733 	trinity_set_vce_wm(rdev, index, pl->vce_wm);
    734 	trinity_set_at(rdev, index, pi->at[index]);
    735 }
    736 
    737 static void trinity_power_level_enable_disable(struct radeon_device *rdev,
    738 					       u32 index, bool enable)
    739 {
    740 	u32 value;
    741 	u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
    742 
    743 	value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
    744 	value &= ~STATE_VALID_MASK;
    745 	if (enable)
    746 		value |= STATE_VALID(1);
    747 	WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
    748 }
    749 
    750 static bool trinity_dpm_enabled(struct radeon_device *rdev)
    751 {
    752 	if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1))
    753 		return true;
    754 	else
    755 		return false;
    756 }
    757 
    758 static void trinity_start_dpm(struct radeon_device *rdev)
    759 {
    760 	u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL);
    761 
    762 	value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK);
    763 	value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1);
    764 	WREG32_SMC(SMU_SCLK_DPM_CNTL, value);
    765 
    766 	WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
    767 	WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN);
    768 
    769 	trinity_dpm_config(rdev, true);
    770 }
    771 
    772 static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev)
    773 {
    774 	int i;
    775 
    776 	for (i = 0; i < rdev->usec_timeout; i++) {
    777 		if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN)
    778 			break;
    779 		udelay(1);
    780 	}
    781 	for (i = 0; i < rdev->usec_timeout; i++) {
    782 		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0)
    783 			break;
    784 		udelay(1);
    785 	}
    786 	for (i = 0; i < rdev->usec_timeout; i++) {
    787 		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
    788 			break;
    789 		udelay(1);
    790 	}
    791 }
    792 
    793 static void trinity_stop_dpm(struct radeon_device *rdev)
    794 {
    795 	u32 sclk_dpm_cntl;
    796 
    797 	WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN);
    798 
    799 	sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL);
    800 	sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK);
    801 	WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl);
    802 
    803 	trinity_dpm_config(rdev, false);
    804 }
    805 
    806 static void trinity_start_am(struct radeon_device *rdev)
    807 {
    808 	WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
    809 }
    810 
    811 static void trinity_reset_am(struct radeon_device *rdev)
    812 {
    813 	WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT,
    814 		 ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
    815 }
    816 
    817 static void trinity_wait_for_level_0(struct radeon_device *rdev)
    818 {
    819 	int i;
    820 
    821 	for (i = 0; i < rdev->usec_timeout; i++) {
    822 		if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
    823 			break;
    824 		udelay(1);
    825 	}
    826 }
    827 
    828 static void trinity_enable_power_level_0(struct radeon_device *rdev)
    829 {
    830 	trinity_power_level_enable_disable(rdev, 0, true);
    831 }
    832 
    833 static void trinity_force_level_0(struct radeon_device *rdev)
    834 {
    835 	trinity_dpm_force_state(rdev, 0);
    836 }
    837 
    838 static void trinity_unforce_levels(struct radeon_device *rdev)
    839 {
    840 	trinity_dpm_no_forced_level(rdev);
    841 }
    842 
    843 static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev,
    844 						struct radeon_ps *new_rps,
    845 						struct radeon_ps *old_rps)
    846 {
    847 	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
    848 	struct trinity_ps *old_ps = trinity_get_ps(old_rps);
    849 	u32 i;
    850 	u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
    851 
    852 	for (i = 0; i < new_ps->num_levels; i++) {
    853 		trinity_program_power_level(rdev, &new_ps->levels[i], i);
    854 		trinity_power_level_enable_disable(rdev, i, true);
    855 	}
    856 
    857 	for (i = new_ps->num_levels; i < n_current_state_levels; i++)
    858 		trinity_power_level_enable_disable(rdev, i, false);
    859 }
    860 
    861 static void trinity_program_bootup_state(struct radeon_device *rdev)
    862 {
    863 	struct trinity_power_info *pi = trinity_get_pi(rdev);
    864 	u32 i;
    865 
    866 	trinity_program_power_level(rdev, &pi->boot_pl, 0);
    867 	trinity_power_level_enable_disable(rdev, 0, true);
    868 
    869 	for (i = 1; i < 8; i++)
    870 		trinity_power_level_enable_disable(rdev, i, false);
    871 }
    872 
    873 static void trinity_setup_uvd_clock_table(struct radeon_device *rdev,
    874 					  struct radeon_ps *rps)
    875 {
    876 	struct trinity_ps *ps = trinity_get_ps(rps);
    877 	u32 uvdstates = (ps->vclk_low_divider |
    878 			 ps->vclk_high_divider << 8 |
    879 			 ps->dclk_low_divider << 16 |
    880 			 ps->dclk_high_divider << 24);
    881 
    882 	WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates);
    883 }
    884 
    885 static void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev,
    886 					   u32 interval)
    887 {
    888 	u32 p, u;
    889 	u32 tp = RREG32_SMC(PM_TP);
    890 	u32 val;
    891 	u32 xclk = radeon_get_xclk(rdev);
    892 
    893 	r600_calculate_u_and_p(interval, xclk, 16, &p, &u);
    894 
    895 	val = (p + tp - 1) / tp;
    896 
    897 	WREG32_SMC(SMU_UVD_DPM_CNTL, val);
    898 }
    899 
    900 static bool trinity_uvd_clocks_zero(struct radeon_ps *rps)
    901 {
    902 	if ((rps->vclk == 0) && (rps->dclk == 0))
    903 		return true;
    904 	else
    905 		return false;
    906 }
    907 
    908 static bool trinity_uvd_clocks_equal(struct radeon_ps *rps1,
    909 				     struct radeon_ps *rps2)
    910 {
    911 	struct trinity_ps *ps1 = trinity_get_ps(rps1);
    912 	struct trinity_ps *ps2 = trinity_get_ps(rps2);
    913 
    914 	if ((rps1->vclk == rps2->vclk) &&
    915 	    (rps1->dclk == rps2->dclk) &&
    916 	    (ps1->vclk_low_divider == ps2->vclk_low_divider) &&
    917 	    (ps1->vclk_high_divider == ps2->vclk_high_divider) &&
    918 	    (ps1->dclk_low_divider == ps2->dclk_low_divider) &&
    919 	    (ps1->dclk_high_divider == ps2->dclk_high_divider))
    920 		return true;
    921 	else
    922 		return false;
    923 }
    924 
    925 static void trinity_setup_uvd_clocks(struct radeon_device *rdev,
    926 				     struct radeon_ps *new_rps,
    927 				     struct radeon_ps *old_rps)
    928 {
    929 	struct trinity_power_info *pi = trinity_get_pi(rdev);
    930 
    931 	if (pi->enable_gfx_power_gating) {
    932 		trinity_gfx_powergating_enable(rdev, false);
    933 	}
    934 
    935 	if (pi->uvd_dpm) {
    936 		if (trinity_uvd_clocks_zero(new_rps) &&
    937 		    !trinity_uvd_clocks_zero(old_rps)) {
    938 			trinity_setup_uvd_dpm_interval(rdev, 0);
    939 		} else if (!trinity_uvd_clocks_zero(new_rps)) {
    940 			trinity_setup_uvd_clock_table(rdev, new_rps);
    941 
    942 			if (trinity_uvd_clocks_zero(old_rps)) {
    943 				u32 tmp = RREG32(CG_MISC_REG);
    944 				tmp &= 0xfffffffd;
    945 				WREG32(CG_MISC_REG, tmp);
    946 
    947 				radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
    948 
    949 				trinity_setup_uvd_dpm_interval(rdev, 3000);
    950 			}
    951 		}
    952 		trinity_uvd_dpm_config(rdev);
    953 	} else {
    954 		if (trinity_uvd_clocks_zero(new_rps) ||
    955 		    trinity_uvd_clocks_equal(new_rps, old_rps))
    956 			return;
    957 
    958 		radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
    959 	}
    960 
    961 	if (pi->enable_gfx_power_gating) {
    962 		trinity_gfx_powergating_enable(rdev, true);
    963 	}
    964 }
    965 
    966 static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
    967 						       struct radeon_ps *new_rps,
    968 						       struct radeon_ps *old_rps)
    969 {
    970 	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
    971 	struct trinity_ps *current_ps = trinity_get_ps(new_rps);
    972 
    973 	if (new_ps->levels[new_ps->num_levels - 1].sclk >=
    974 	    current_ps->levels[current_ps->num_levels - 1].sclk)
    975 		return;
    976 
    977 	trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
    978 }
    979 
    980 static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
    981 						      struct radeon_ps *new_rps,
    982 						      struct radeon_ps *old_rps)
    983 {
    984 	struct trinity_ps *new_ps = trinity_get_ps(new_rps);
    985 	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
    986 
    987 	if (new_ps->levels[new_ps->num_levels - 1].sclk <
    988 	    current_ps->levels[current_ps->num_levels - 1].sclk)
    989 		return;
    990 
    991 	trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
    992 }
    993 
    994 static void trinity_set_vce_clock(struct radeon_device *rdev,
    995 				  struct radeon_ps *new_rps,
    996 				  struct radeon_ps *old_rps)
    997 {
    998 	if ((old_rps->evclk != new_rps->evclk) ||
    999 	    (old_rps->ecclk != new_rps->ecclk)) {
   1000 		/* turn the clocks on when encoding, off otherwise */
   1001 		if (new_rps->evclk || new_rps->ecclk)
   1002 			vce_v1_0_enable_mgcg(rdev, false);
   1003 		else
   1004 			vce_v1_0_enable_mgcg(rdev, true);
   1005 		radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
   1006 	}
   1007 }
   1008 
   1009 static void trinity_program_ttt(struct radeon_device *rdev)
   1010 {
   1011 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1012 	u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
   1013 
   1014 	value &= ~(HT_MASK | LT_MASK);
   1015 	value |= HT((pi->thermal_auto_throttling + 49) * 8);
   1016 	value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
   1017 	WREG32_SMC(SMU_SCLK_DPM_TTT, value);
   1018 }
   1019 
   1020 static void trinity_enable_att(struct radeon_device *rdev)
   1021 {
   1022 	u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
   1023 
   1024 	value &= ~SCLK_TT_EN_MASK;
   1025 	value |= SCLK_TT_EN(1);
   1026 	WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
   1027 }
   1028 
   1029 static void trinity_program_sclk_dpm(struct radeon_device *rdev)
   1030 {
   1031 	u32 p, u;
   1032 	u32 tp = RREG32_SMC(PM_TP);
   1033 	u32 ni;
   1034 	u32 xclk = radeon_get_xclk(rdev);
   1035 	u32 value;
   1036 
   1037 	r600_calculate_u_and_p(400, xclk, 16, &p, &u);
   1038 
   1039 	ni = (p + tp - 1) / tp;
   1040 
   1041 	value = RREG32_SMC(PM_I_CNTL_1);
   1042 	value &= ~SCLK_DPM_MASK;
   1043 	value |= SCLK_DPM(ni);
   1044 	WREG32_SMC(PM_I_CNTL_1, value);
   1045 }
   1046 
   1047 static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
   1048 						 int min_temp, int max_temp)
   1049 {
   1050 	int low_temp = 0 * 1000;
   1051 	int high_temp = 255 * 1000;
   1052 
   1053         if (low_temp < min_temp)
   1054 		low_temp = min_temp;
   1055         if (high_temp > max_temp)
   1056 		high_temp = max_temp;
   1057         if (high_temp < low_temp) {
   1058 		DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
   1059                 return -EINVAL;
   1060         }
   1061 
   1062 	WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
   1063 	WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
   1064 
   1065 	rdev->pm.dpm.thermal.min_temp = low_temp;
   1066 	rdev->pm.dpm.thermal.max_temp = high_temp;
   1067 
   1068 	return 0;
   1069 }
   1070 
   1071 static void trinity_update_current_ps(struct radeon_device *rdev,
   1072 				      struct radeon_ps *rps)
   1073 {
   1074 	struct trinity_ps *new_ps = trinity_get_ps(rps);
   1075 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1076 
   1077 	pi->current_rps = *rps;
   1078 	pi->current_ps = *new_ps;
   1079 	pi->current_rps.ps_priv = &pi->current_ps;
   1080 }
   1081 
   1082 static void trinity_update_requested_ps(struct radeon_device *rdev,
   1083 					struct radeon_ps *rps)
   1084 {
   1085 	struct trinity_ps *new_ps = trinity_get_ps(rps);
   1086 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1087 
   1088 	pi->requested_rps = *rps;
   1089 	pi->requested_ps = *new_ps;
   1090 	pi->requested_rps.ps_priv = &pi->requested_ps;
   1091 }
   1092 
   1093 void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
   1094 {
   1095 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1096 
   1097 	if (pi->enable_bapm) {
   1098 		trinity_acquire_mutex(rdev);
   1099 		trinity_dpm_bapm_enable(rdev, enable);
   1100 		trinity_release_mutex(rdev);
   1101 	}
   1102 }
   1103 
   1104 int trinity_dpm_enable(struct radeon_device *rdev)
   1105 {
   1106 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1107 
   1108 	trinity_acquire_mutex(rdev);
   1109 
   1110 	if (trinity_dpm_enabled(rdev)) {
   1111 		trinity_release_mutex(rdev);
   1112 		return -EINVAL;
   1113 	}
   1114 
   1115 	trinity_program_bootup_state(rdev);
   1116 	sumo_program_vc(rdev, 0x00C00033);
   1117 	trinity_start_am(rdev);
   1118 	if (pi->enable_auto_thermal_throttling) {
   1119 		trinity_program_ttt(rdev);
   1120 		trinity_enable_att(rdev);
   1121 	}
   1122 	trinity_program_sclk_dpm(rdev);
   1123 	trinity_start_dpm(rdev);
   1124 	trinity_wait_for_dpm_enabled(rdev);
   1125 	trinity_dpm_bapm_enable(rdev, false);
   1126 	trinity_release_mutex(rdev);
   1127 
   1128 	trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
   1129 
   1130 	return 0;
   1131 }
   1132 
   1133 int trinity_dpm_late_enable(struct radeon_device *rdev)
   1134 {
   1135 	int ret;
   1136 
   1137 	trinity_acquire_mutex(rdev);
   1138 	trinity_enable_clock_power_gating(rdev);
   1139 
   1140 	if (rdev->irq.installed &&
   1141 	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
   1142 		ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
   1143 		if (ret) {
   1144 			trinity_release_mutex(rdev);
   1145 			return ret;
   1146 		}
   1147 		rdev->irq.dpm_thermal = true;
   1148 		radeon_irq_set(rdev);
   1149 	}
   1150 	trinity_release_mutex(rdev);
   1151 
   1152 	return 0;
   1153 }
   1154 
   1155 void trinity_dpm_disable(struct radeon_device *rdev)
   1156 {
   1157 	trinity_acquire_mutex(rdev);
   1158 	if (!trinity_dpm_enabled(rdev)) {
   1159 		trinity_release_mutex(rdev);
   1160 		return;
   1161 	}
   1162 	trinity_dpm_bapm_enable(rdev, false);
   1163 	trinity_disable_clock_power_gating(rdev);
   1164 	sumo_clear_vc(rdev);
   1165 	trinity_wait_for_level_0(rdev);
   1166 	trinity_stop_dpm(rdev);
   1167 	trinity_reset_am(rdev);
   1168 	trinity_release_mutex(rdev);
   1169 
   1170 	if (rdev->irq.installed &&
   1171 	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
   1172 		rdev->irq.dpm_thermal = false;
   1173 		radeon_irq_set(rdev);
   1174 	}
   1175 
   1176 	trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
   1177 }
   1178 
   1179 static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
   1180 {
   1181 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1182 
   1183 	pi->min_sclk_did =
   1184 		(RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
   1185 }
   1186 
   1187 static void trinity_setup_nbp_sim(struct radeon_device *rdev,
   1188 				  struct radeon_ps *rps)
   1189 {
   1190 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1191 	struct trinity_ps *new_ps = trinity_get_ps(rps);
   1192 	u32 nbpsconfig;
   1193 
   1194 	if (pi->sys_info.nb_dpm_enable) {
   1195 		nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
   1196 		nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
   1197 		nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
   1198 			       Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
   1199 			       DpmXNbPsLo(new_ps->DpmXNbPsLo) |
   1200 			       DpmXNbPsHi(new_ps->DpmXNbPsHi));
   1201 		WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
   1202 	}
   1203 }
   1204 
   1205 int trinity_dpm_force_performance_level(struct radeon_device *rdev,
   1206 					enum radeon_dpm_forced_level level)
   1207 {
   1208 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1209 	struct radeon_ps *rps = &pi->current_rps;
   1210 	struct trinity_ps *ps = trinity_get_ps(rps);
   1211 	int i, ret;
   1212 
   1213 	if (ps->num_levels <= 1)
   1214 		return 0;
   1215 
   1216 	if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
   1217 		/* not supported by the hw */
   1218 		return -EINVAL;
   1219 	} else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
   1220 		ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1);
   1221 		if (ret)
   1222 			return ret;
   1223 	} else {
   1224 		for (i = 0; i < ps->num_levels; i++) {
   1225 			ret = trinity_dpm_n_levels_disabled(rdev, 0);
   1226 			if (ret)
   1227 				return ret;
   1228 		}
   1229 	}
   1230 
   1231 	rdev->pm.dpm.forced_level = level;
   1232 
   1233 	return 0;
   1234 }
   1235 
   1236 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev)
   1237 {
   1238 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1239 	struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
   1240 	struct radeon_ps *new_ps = &requested_ps;
   1241 
   1242 	trinity_update_requested_ps(rdev, new_ps);
   1243 
   1244 	trinity_apply_state_adjust_rules(rdev,
   1245 					 &pi->requested_rps,
   1246 					 &pi->current_rps);
   1247 
   1248 	return 0;
   1249 }
   1250 
   1251 int trinity_dpm_set_power_state(struct radeon_device *rdev)
   1252 {
   1253 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1254 	struct radeon_ps *new_ps = &pi->requested_rps;
   1255 	struct radeon_ps *old_ps = &pi->current_rps;
   1256 
   1257 	trinity_acquire_mutex(rdev);
   1258 	if (pi->enable_dpm) {
   1259 		if (pi->enable_bapm)
   1260 			trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power);
   1261 		trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
   1262 		trinity_enable_power_level_0(rdev);
   1263 		trinity_force_level_0(rdev);
   1264 		trinity_wait_for_level_0(rdev);
   1265 		trinity_setup_nbp_sim(rdev, new_ps);
   1266 		trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps);
   1267 		trinity_force_level_0(rdev);
   1268 		trinity_unforce_levels(rdev);
   1269 		trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
   1270 		trinity_set_vce_clock(rdev, new_ps, old_ps);
   1271 	}
   1272 	trinity_release_mutex(rdev);
   1273 
   1274 	return 0;
   1275 }
   1276 
   1277 void trinity_dpm_post_set_power_state(struct radeon_device *rdev)
   1278 {
   1279 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1280 	struct radeon_ps *new_ps = &pi->requested_rps;
   1281 
   1282 	trinity_update_current_ps(rdev, new_ps);
   1283 }
   1284 
   1285 void trinity_dpm_setup_asic(struct radeon_device *rdev)
   1286 {
   1287 	trinity_acquire_mutex(rdev);
   1288 	sumo_program_sstp(rdev);
   1289 	sumo_take_smu_control(rdev, true);
   1290 	trinity_get_min_sclk_divider(rdev);
   1291 	trinity_release_mutex(rdev);
   1292 }
   1293 
   1294 #if 0
   1295 void trinity_dpm_reset_asic(struct radeon_device *rdev)
   1296 {
   1297 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1298 
   1299 	trinity_acquire_mutex(rdev);
   1300 	if (pi->enable_dpm) {
   1301 		trinity_enable_power_level_0(rdev);
   1302 		trinity_force_level_0(rdev);
   1303 		trinity_wait_for_level_0(rdev);
   1304 		trinity_program_bootup_state(rdev);
   1305 		trinity_force_level_0(rdev);
   1306 		trinity_unforce_levels(rdev);
   1307 	}
   1308 	trinity_release_mutex(rdev);
   1309 }
   1310 #endif
   1311 
   1312 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
   1313 						  u32 vid_2bit)
   1314 {
   1315 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1316 	u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
   1317 	u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
   1318 	u32 step = (svi_mode == 0) ? 1250 : 625;
   1319 	u32 delta = vid_7bit * step + 50;
   1320 
   1321 	if (delta > 155000)
   1322 		return 0;
   1323 
   1324 	return (155000 - delta) / 100;
   1325 }
   1326 
   1327 static void trinity_patch_boot_state(struct radeon_device *rdev,
   1328 				     struct trinity_ps *ps)
   1329 {
   1330 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1331 
   1332 	ps->num_levels = 1;
   1333 	ps->nbps_flags = 0;
   1334 	ps->bapm_flags = 0;
   1335 	ps->levels[0] = pi->boot_pl;
   1336 }
   1337 
   1338 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
   1339 {
   1340 	if (sclk < 20000)
   1341 		return 1;
   1342 	return 0;
   1343 }
   1344 
   1345 static void trinity_construct_boot_state(struct radeon_device *rdev)
   1346 {
   1347 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1348 
   1349 	pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
   1350 	pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
   1351 	pi->boot_pl.ds_divider_index = 0;
   1352 	pi->boot_pl.ss_divider_index = 0;
   1353 	pi->boot_pl.allow_gnb_slow = 1;
   1354 	pi->boot_pl.force_nbp_state = 0;
   1355 	pi->boot_pl.display_wm = 0;
   1356 	pi->boot_pl.vce_wm = 0;
   1357 	pi->current_ps.num_levels = 1;
   1358 	pi->current_ps.levels[0] = pi->boot_pl;
   1359 }
   1360 
   1361 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
   1362 						  u32 sclk, u32 min_sclk_in_sr)
   1363 {
   1364 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1365 	u32 i;
   1366 	u32 temp;
   1367 	u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
   1368 		min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
   1369 
   1370 	if (sclk < min)
   1371 		return 0;
   1372 
   1373 	if (!pi->enable_sclk_ds)
   1374 		return 0;
   1375 
   1376 	for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
   1377 		temp = sclk / sumo_get_sleep_divider_from_id(i);
   1378 		if (temp >= min || i == 0)
   1379 			break;
   1380 	}
   1381 
   1382 	return (u8)i;
   1383 }
   1384 
   1385 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
   1386 					  u32 lower_limit)
   1387 {
   1388 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1389 	u32 i;
   1390 
   1391 	for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
   1392 		if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
   1393 			return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
   1394 	}
   1395 
   1396 	if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
   1397 		DRM_ERROR("engine clock out of range!");
   1398 
   1399 	return 0;
   1400 }
   1401 
   1402 static void trinity_patch_thermal_state(struct radeon_device *rdev,
   1403 					struct trinity_ps *ps,
   1404 					struct trinity_ps *current_ps)
   1405 {
   1406 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1407 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
   1408 	u32 current_vddc;
   1409 	u32 current_sclk;
   1410 	u32 current_index = 0;
   1411 
   1412 	if (current_ps) {
   1413 		current_vddc = current_ps->levels[current_index].vddc_index;
   1414 		current_sclk = current_ps->levels[current_index].sclk;
   1415 	} else {
   1416 		current_vddc = pi->boot_pl.vddc_index;
   1417 		current_sclk = pi->boot_pl.sclk;
   1418 	}
   1419 
   1420 	ps->levels[0].vddc_index = current_vddc;
   1421 
   1422 	if (ps->levels[0].sclk > current_sclk)
   1423 		ps->levels[0].sclk = current_sclk;
   1424 
   1425 	ps->levels[0].ds_divider_index =
   1426 		trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
   1427 	ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
   1428 	ps->levels[0].allow_gnb_slow = 1;
   1429 	ps->levels[0].force_nbp_state = 0;
   1430 	ps->levels[0].display_wm = 0;
   1431 	ps->levels[0].vce_wm =
   1432 		trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
   1433 }
   1434 
   1435 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
   1436 				       struct trinity_ps *ps, u32 index)
   1437 {
   1438 	if (ps == NULL || ps->num_levels <= 1)
   1439 		return 0;
   1440 	else if (ps->num_levels == 2) {
   1441 		if (index == 0)
   1442 			return 0;
   1443 		else
   1444 			return 1;
   1445 	} else {
   1446 		if (index == 0)
   1447 			return 0;
   1448 		else if (ps->levels[index].sclk < 30000)
   1449 			return 0;
   1450 		else
   1451 			return 1;
   1452 	}
   1453 }
   1454 
   1455 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
   1456 				       struct radeon_ps *rps)
   1457 {
   1458 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1459 	u32 i = 0;
   1460 
   1461 	for (i = 0; i < 4; i++) {
   1462 		if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
   1463 		    (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
   1464 		    break;
   1465 	}
   1466 
   1467 	if (i >= 4) {
   1468 		DRM_ERROR("UVD clock index not found!\n");
   1469 		i = 3;
   1470 	}
   1471 	return i;
   1472 }
   1473 
   1474 static void trinity_adjust_uvd_state(struct radeon_device *rdev,
   1475 				     struct radeon_ps *rps)
   1476 {
   1477 	struct trinity_ps *ps = trinity_get_ps(rps);
   1478 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1479 	u32 high_index = 0;
   1480 	u32 low_index = 0;
   1481 
   1482 	if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
   1483 		high_index = trinity_get_uvd_clock_index(rdev, rps);
   1484 
   1485 		switch(high_index) {
   1486 		case 3:
   1487 		case 2:
   1488 			low_index = 1;
   1489 			break;
   1490 		case 1:
   1491 		case 0:
   1492 		default:
   1493 			low_index = 0;
   1494 			break;
   1495 		}
   1496 
   1497 		ps->vclk_low_divider =
   1498 			pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
   1499 		ps->dclk_low_divider =
   1500 			pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
   1501 		ps->vclk_high_divider =
   1502 			pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
   1503 		ps->dclk_high_divider =
   1504 			pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
   1505 	}
   1506 }
   1507 
   1508 static int trinity_get_vce_clock_voltage(struct radeon_device *rdev,
   1509 					 u32 evclk, u32 ecclk, u16 *voltage)
   1510 {
   1511 	u32 i;
   1512 	int ret = -EINVAL;
   1513 	struct radeon_vce_clock_voltage_dependency_table *table =
   1514 		&rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
   1515 
   1516 	if (((evclk == 0) && (ecclk == 0)) ||
   1517 	    (table && (table->count == 0))) {
   1518 		*voltage = 0;
   1519 		return 0;
   1520 	}
   1521 
   1522 	for (i = 0; i < table->count; i++) {
   1523 		if ((evclk <= table->entries[i].evclk) &&
   1524 		    (ecclk <= table->entries[i].ecclk)) {
   1525 			*voltage = table->entries[i].v;
   1526 			ret = 0;
   1527 			break;
   1528 		}
   1529 	}
   1530 
   1531 	/* if no match return the highest voltage */
   1532 	if (ret)
   1533 		*voltage = table->entries[table->count - 1].v;
   1534 
   1535 	return ret;
   1536 }
   1537 
   1538 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
   1539 					     struct radeon_ps *new_rps,
   1540 					     struct radeon_ps *old_rps)
   1541 {
   1542 	struct trinity_ps *ps = trinity_get_ps(new_rps);
   1543 	struct trinity_ps *current_ps = trinity_get_ps(old_rps);
   1544 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1545 	u32 min_voltage = 0; /* ??? */
   1546 	u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
   1547 	u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
   1548 	u32 i;
   1549 	u16 min_vce_voltage;
   1550 	bool force_high;
   1551 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
   1552 
   1553 	if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
   1554 		return trinity_patch_thermal_state(rdev, ps, current_ps);
   1555 
   1556 	trinity_adjust_uvd_state(rdev, new_rps);
   1557 
   1558 	if (new_rps->vce_active) {
   1559 		new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
   1560 		new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
   1561 	} else {
   1562 		new_rps->evclk = 0;
   1563 		new_rps->ecclk = 0;
   1564 	}
   1565 
   1566 	for (i = 0; i < ps->num_levels; i++) {
   1567 		if (ps->levels[i].vddc_index < min_voltage)
   1568 			ps->levels[i].vddc_index = min_voltage;
   1569 
   1570 		if (ps->levels[i].sclk < min_sclk)
   1571 			ps->levels[i].sclk =
   1572 				trinity_get_valid_engine_clock(rdev, min_sclk);
   1573 
   1574 		/* patch in vce limits */
   1575 		if (new_rps->vce_active) {
   1576 			/* sclk */
   1577 			if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
   1578 				ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
   1579 			/* vddc */
   1580 			trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
   1581 			if (ps->levels[i].vddc_index < min_vce_voltage)
   1582 				ps->levels[i].vddc_index = min_vce_voltage;
   1583 		}
   1584 
   1585 		ps->levels[i].ds_divider_index =
   1586 			sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
   1587 
   1588 		ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
   1589 
   1590 		ps->levels[i].allow_gnb_slow = 1;
   1591 		ps->levels[i].force_nbp_state = 0;
   1592 		ps->levels[i].display_wm =
   1593 			trinity_calculate_display_wm(rdev, ps, i);
   1594 		ps->levels[i].vce_wm =
   1595 			trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
   1596 	}
   1597 
   1598 	if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
   1599 	    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
   1600 		ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
   1601 
   1602 	if (pi->sys_info.nb_dpm_enable) {
   1603 		ps->Dpm0PgNbPsLo = 0x1;
   1604 		ps->Dpm0PgNbPsHi = 0x0;
   1605 		ps->DpmXNbPsLo = 0x2;
   1606 		ps->DpmXNbPsHi = 0x1;
   1607 
   1608 		if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
   1609 		    ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
   1610 			force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
   1611 				      ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
   1612 				       (pi->sys_info.uma_channel_number == 1)));
   1613 			force_high = (num_active_displays >= 3) || force_high;
   1614 			ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
   1615 			ps->Dpm0PgNbPsHi = 0x1;
   1616 			ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
   1617 			ps->DpmXNbPsHi = 0x2;
   1618 			ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
   1619 		}
   1620 	}
   1621 }
   1622 
   1623 static void trinity_cleanup_asic(struct radeon_device *rdev)
   1624 {
   1625 	sumo_take_smu_control(rdev, false);
   1626 }
   1627 
   1628 #if 0
   1629 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
   1630 {
   1631 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1632 
   1633 	if (pi->voltage_drop_in_dce)
   1634 		trinity_dce_enable_voltage_adjustment(rdev, false);
   1635 }
   1636 #endif
   1637 
   1638 static void trinity_add_dccac_value(struct radeon_device *rdev)
   1639 {
   1640 	u32 gpu_cac_avrg_cntl_window_size;
   1641 	u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
   1642 	u64 disp_clk = rdev->clock.default_dispclk / 100;
   1643 	u32 dc_cac_value;
   1644 
   1645 	gpu_cac_avrg_cntl_window_size =
   1646 		(RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
   1647 
   1648 	dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
   1649 			     (32 - gpu_cac_avrg_cntl_window_size));
   1650 
   1651 	WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
   1652 }
   1653 
   1654 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
   1655 {
   1656 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1657 
   1658 	if (pi->voltage_drop_in_dce)
   1659 		trinity_dce_enable_voltage_adjustment(rdev, true);
   1660 	trinity_add_dccac_value(rdev);
   1661 }
   1662 
   1663 union power_info {
   1664 	struct _ATOM_POWERPLAY_INFO info;
   1665 	struct _ATOM_POWERPLAY_INFO_V2 info_2;
   1666 	struct _ATOM_POWERPLAY_INFO_V3 info_3;
   1667 	struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
   1668 	struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
   1669 	struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
   1670 };
   1671 
   1672 union pplib_clock_info {
   1673 	struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
   1674 	struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
   1675 	struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
   1676 	struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
   1677 };
   1678 
   1679 union pplib_power_state {
   1680 	struct _ATOM_PPLIB_STATE v1;
   1681 	struct _ATOM_PPLIB_STATE_V2 v2;
   1682 };
   1683 
   1684 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
   1685 					       struct radeon_ps *rps,
   1686 					       struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
   1687 					       u8 table_rev)
   1688 {
   1689 	struct trinity_ps *ps = trinity_get_ps(rps);
   1690 
   1691 	rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
   1692 	rps->class = le16_to_cpu(non_clock_info->usClassification);
   1693 	rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
   1694 
   1695 	if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
   1696 		rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
   1697 		rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
   1698 	} else {
   1699 		rps->vclk = 0;
   1700 		rps->dclk = 0;
   1701 	}
   1702 
   1703 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
   1704 		rdev->pm.dpm.boot_ps = rps;
   1705 		trinity_patch_boot_state(rdev, ps);
   1706 	}
   1707 	if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
   1708 		rdev->pm.dpm.uvd_ps = rps;
   1709 }
   1710 
   1711 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
   1712 					   struct radeon_ps *rps, int index,
   1713 					   union pplib_clock_info *clock_info)
   1714 {
   1715 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1716 	struct trinity_ps *ps = trinity_get_ps(rps);
   1717 	struct trinity_pl *pl = &ps->levels[index];
   1718 	u32 sclk;
   1719 
   1720 	sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
   1721 	sclk |= clock_info->sumo.ucEngineClockHigh << 16;
   1722 	pl->sclk = sclk;
   1723 	pl->vddc_index = clock_info->sumo.vddcIndex;
   1724 
   1725 	ps->num_levels = index + 1;
   1726 
   1727 	if (pi->enable_sclk_ds) {
   1728 		pl->ds_divider_index = 5;
   1729 		pl->ss_divider_index = 5;
   1730 	}
   1731 }
   1732 
   1733 static int trinity_parse_power_table(struct radeon_device *rdev)
   1734 {
   1735 	struct radeon_mode_info *mode_info = &rdev->mode_info;
   1736 	struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
   1737 	union pplib_power_state *power_state;
   1738 	int i, j, k, non_clock_array_index, clock_array_index;
   1739 	union pplib_clock_info *clock_info;
   1740 	struct _StateArray *state_array;
   1741 	struct _ClockInfoArray *clock_info_array;
   1742 	struct _NonClockInfoArray *non_clock_info_array;
   1743 	union power_info *power_info;
   1744 	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
   1745         u16 data_offset;
   1746 	u8 frev, crev;
   1747 	u8 *power_state_offset;
   1748 	struct sumo_ps *ps;
   1749 
   1750 	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
   1751 				   &frev, &crev, &data_offset))
   1752 		return -EINVAL;
   1753 	power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
   1754 
   1755 	state_array = (struct _StateArray *)
   1756 		(mode_info->atom_context->bios + data_offset +
   1757 		 le16_to_cpu(power_info->pplib.usStateArrayOffset));
   1758 	clock_info_array = (struct _ClockInfoArray *)
   1759 		(mode_info->atom_context->bios + data_offset +
   1760 		 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
   1761 	non_clock_info_array = (struct _NonClockInfoArray *)
   1762 		(mode_info->atom_context->bios + data_offset +
   1763 		 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
   1764 
   1765 	rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
   1766 				  state_array->ucNumEntries, GFP_KERNEL);
   1767 	if (!rdev->pm.dpm.ps)
   1768 		return -ENOMEM;
   1769 	power_state_offset = (u8 *)state_array->states;
   1770 	for (i = 0; i < state_array->ucNumEntries; i++) {
   1771 		u8 *idx;
   1772 		power_state = (union pplib_power_state *)power_state_offset;
   1773 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
   1774 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
   1775 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
   1776 		if (!rdev->pm.power_state[i].clock_info)
   1777 			return -EINVAL;
   1778 		ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
   1779 		if (ps == NULL) {
   1780 			kfree(rdev->pm.dpm.ps);
   1781 			return -ENOMEM;
   1782 		}
   1783 		rdev->pm.dpm.ps[i].ps_priv = ps;
   1784 		k = 0;
   1785 		idx = (u8 *)&power_state->v2.clockInfoIndex[0];
   1786 		for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
   1787 			clock_array_index = idx[j];
   1788 			if (clock_array_index >= clock_info_array->ucNumEntries)
   1789 				continue;
   1790 			if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
   1791 				break;
   1792 			clock_info = (union pplib_clock_info *)
   1793 				((u8 *)&clock_info_array->clockInfo[0] +
   1794 				 (clock_array_index * clock_info_array->ucEntrySize));
   1795 			trinity_parse_pplib_clock_info(rdev,
   1796 						       &rdev->pm.dpm.ps[i], k,
   1797 						       clock_info);
   1798 			k++;
   1799 		}
   1800 		trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
   1801 						   non_clock_info,
   1802 						   non_clock_info_array->ucEntrySize);
   1803 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
   1804 	}
   1805 	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
   1806 
   1807 	/* fill in the vce power states */
   1808 	for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
   1809 		u32 sclk;
   1810 		clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
   1811 		clock_info = (union pplib_clock_info *)
   1812 			&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
   1813 		sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
   1814 		sclk |= clock_info->sumo.ucEngineClockHigh << 16;
   1815 		rdev->pm.dpm.vce_states[i].sclk = sclk;
   1816 		rdev->pm.dpm.vce_states[i].mclk = 0;
   1817 	}
   1818 
   1819 	return 0;
   1820 }
   1821 
   1822 union igp_info {
   1823 	struct _ATOM_INTEGRATED_SYSTEM_INFO info;
   1824 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
   1825 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
   1826 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
   1827 	struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
   1828 };
   1829 
   1830 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
   1831 {
   1832 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1833 	u32 divider;
   1834 
   1835 	if (did >= 8 && did <= 0x3f)
   1836 		divider = did * 25;
   1837 	else if (did > 0x3f && did <= 0x5f)
   1838 		divider = (did - 64) * 50 + 1600;
   1839 	else if (did > 0x5f && did <= 0x7e)
   1840 		divider = (did - 96) * 100 + 3200;
   1841 	else if (did == 0x7f)
   1842 		divider = 128 * 100;
   1843 	else
   1844 		return 10000;
   1845 
   1846 	return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
   1847 }
   1848 
   1849 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
   1850 {
   1851 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   1852 	struct radeon_mode_info *mode_info = &rdev->mode_info;
   1853 	int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
   1854 	union igp_info *igp_info;
   1855 	u8 frev, crev;
   1856 	u16 data_offset;
   1857 	int i;
   1858 
   1859 	if (atom_parse_data_header(mode_info->atom_context, index, NULL,
   1860 				   &frev, &crev, &data_offset)) {
   1861 		igp_info = (union igp_info *)(mode_info->atom_context->bios +
   1862 					      data_offset);
   1863 
   1864 		if (crev != 7) {
   1865 			DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
   1866 			return -EINVAL;
   1867 		}
   1868 		pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
   1869 		pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
   1870 		pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
   1871 		pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
   1872 		pi->sys_info.bootup_nb_voltage_index =
   1873 			le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
   1874 		if (igp_info->info_7.ucHtcTmpLmt == 0)
   1875 			pi->sys_info.htc_tmp_lmt = 203;
   1876 		else
   1877 			pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
   1878 		if (igp_info->info_7.ucHtcHystLmt == 0)
   1879 			pi->sys_info.htc_hyst_lmt = 5;
   1880 		else
   1881 			pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
   1882 		if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
   1883 			DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
   1884 		}
   1885 
   1886 		if (pi->enable_nbps_policy)
   1887 			pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
   1888 		else
   1889 			pi->sys_info.nb_dpm_enable = 0;
   1890 
   1891 		for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
   1892 			pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
   1893 			pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
   1894 		}
   1895 
   1896 		pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
   1897 		pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
   1898 		pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
   1899 		pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
   1900 
   1901 		if (!pi->sys_info.nb_dpm_enable) {
   1902 			for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
   1903 				pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
   1904 				pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
   1905 				pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
   1906 			}
   1907 		}
   1908 
   1909 		pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
   1910 
   1911 		sumo_construct_sclk_voltage_mapping_table(rdev,
   1912 							  &pi->sys_info.sclk_voltage_mapping_table,
   1913 							  igp_info->info_7.sAvail_SCLK);
   1914 		sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
   1915 						 igp_info->info_7.sAvail_SCLK);
   1916 
   1917 		pi->sys_info.uvd_clock_table_entries[0].vclk_did =
   1918 			igp_info->info_7.ucDPMState0VclkFid;
   1919 		pi->sys_info.uvd_clock_table_entries[1].vclk_did =
   1920 			igp_info->info_7.ucDPMState1VclkFid;
   1921 		pi->sys_info.uvd_clock_table_entries[2].vclk_did =
   1922 			igp_info->info_7.ucDPMState2VclkFid;
   1923 		pi->sys_info.uvd_clock_table_entries[3].vclk_did =
   1924 			igp_info->info_7.ucDPMState3VclkFid;
   1925 
   1926 		pi->sys_info.uvd_clock_table_entries[0].dclk_did =
   1927 			igp_info->info_7.ucDPMState0DclkFid;
   1928 		pi->sys_info.uvd_clock_table_entries[1].dclk_did =
   1929 			igp_info->info_7.ucDPMState1DclkFid;
   1930 		pi->sys_info.uvd_clock_table_entries[2].dclk_did =
   1931 			igp_info->info_7.ucDPMState2DclkFid;
   1932 		pi->sys_info.uvd_clock_table_entries[3].dclk_did =
   1933 			igp_info->info_7.ucDPMState3DclkFid;
   1934 
   1935 		for (i = 0; i < 4; i++) {
   1936 			pi->sys_info.uvd_clock_table_entries[i].vclk =
   1937 				trinity_convert_did_to_freq(rdev,
   1938 							    pi->sys_info.uvd_clock_table_entries[i].vclk_did);
   1939 			pi->sys_info.uvd_clock_table_entries[i].dclk =
   1940 				trinity_convert_did_to_freq(rdev,
   1941 							    pi->sys_info.uvd_clock_table_entries[i].dclk_did);
   1942 		}
   1943 
   1944 
   1945 
   1946 	}
   1947 	return 0;
   1948 }
   1949 
   1950 int trinity_dpm_init(struct radeon_device *rdev)
   1951 {
   1952 	struct trinity_power_info *pi;
   1953 	int ret, i;
   1954 
   1955 	pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
   1956 	if (pi == NULL)
   1957 		return -ENOMEM;
   1958 	rdev->pm.dpm.priv = pi;
   1959 
   1960 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
   1961 		pi->at[i] = TRINITY_AT_DFLT;
   1962 
   1963 	if (radeon_bapm == -1) {
   1964 		/* There are stability issues reported on with
   1965 		 * bapm enabled when switching between AC and battery
   1966 		 * power.  At the same time, some MSI boards hang
   1967 		 * if it's not enabled and dpm is enabled.  Just enable
   1968 		 * it for MSI boards right now.
   1969 		 */
   1970 		if (rdev->pdev->subsystem_vendor == 0x1462)
   1971 			pi->enable_bapm = true;
   1972 		else
   1973 			pi->enable_bapm = false;
   1974 	} else if (radeon_bapm == 0) {
   1975 		pi->enable_bapm = false;
   1976 	} else {
   1977 		pi->enable_bapm = true;
   1978 	}
   1979 	pi->enable_nbps_policy = true;
   1980 	pi->enable_sclk_ds = true;
   1981 	pi->enable_gfx_power_gating = true;
   1982 	pi->enable_gfx_clock_gating = true;
   1983 	pi->enable_mg_clock_gating = false;
   1984 	pi->enable_gfx_dynamic_mgpg = false;
   1985 	pi->override_dynamic_mgpg = false;
   1986 	pi->enable_auto_thermal_throttling = true;
   1987 	pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */
   1988 	pi->uvd_dpm = true; /* ??? */
   1989 
   1990 	ret = trinity_parse_sys_info_table(rdev);
   1991 	if (ret)
   1992 		return ret;
   1993 
   1994 	trinity_construct_boot_state(rdev);
   1995 
   1996 	ret = r600_get_platform_caps(rdev);
   1997 	if (ret)
   1998 		return ret;
   1999 
   2000 	ret = r600_parse_extended_power_table(rdev);
   2001 	if (ret)
   2002 		return ret;
   2003 
   2004 	ret = trinity_parse_power_table(rdev);
   2005 	if (ret)
   2006 		return ret;
   2007 
   2008 	pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
   2009 	pi->enable_dpm = true;
   2010 
   2011 	return 0;
   2012 }
   2013 
   2014 void trinity_dpm_print_power_state(struct radeon_device *rdev,
   2015 				   struct radeon_ps *rps)
   2016 {
   2017 	int i;
   2018 	struct trinity_ps *ps = trinity_get_ps(rps);
   2019 
   2020 	r600_dpm_print_class_info(rps->class, rps->class2);
   2021 	r600_dpm_print_cap_info(rps->caps);
   2022 	printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
   2023 	for (i = 0; i < ps->num_levels; i++) {
   2024 		struct trinity_pl *pl = &ps->levels[i];
   2025 		printk("\t\tpower level %d    sclk: %u vddc: %u\n",
   2026 		       i, pl->sclk,
   2027 		       trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
   2028 	}
   2029 	r600_dpm_print_ps_status(rdev, rps);
   2030 }
   2031 
   2032 #ifdef CONFIG_DEBUG_FS
   2033 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
   2034 							 struct seq_file *m)
   2035 {
   2036 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   2037 	struct radeon_ps *rps = &pi->current_rps;
   2038 	struct trinity_ps *ps = trinity_get_ps(rps);
   2039 	struct trinity_pl *pl;
   2040 	u32 current_index =
   2041 		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
   2042 		CURRENT_STATE_SHIFT;
   2043 
   2044 	if (current_index >= ps->num_levels) {
   2045 		seq_printf(m, "invalid dpm profile %d\n", current_index);
   2046 	} else {
   2047 		pl = &ps->levels[current_index];
   2048 		seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
   2049 		seq_printf(m, "power level %d    sclk: %u vddc: %u\n",
   2050 			   current_index, pl->sclk,
   2051 			   trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
   2052 	}
   2053 }
   2054 #endif
   2055 
   2056 u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev)
   2057 {
   2058 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   2059 	struct radeon_ps *rps = &pi->current_rps;
   2060 	struct trinity_ps *ps = trinity_get_ps(rps);
   2061 	struct trinity_pl *pl;
   2062 	u32 current_index =
   2063 		(RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
   2064 		CURRENT_STATE_SHIFT;
   2065 
   2066 	if (current_index >= ps->num_levels) {
   2067 		return 0;
   2068 	} else {
   2069 		pl = &ps->levels[current_index];
   2070 		return pl->sclk;
   2071 	}
   2072 }
   2073 
   2074 u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev)
   2075 {
   2076 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   2077 
   2078 	return pi->sys_info.bootup_uma_clk;
   2079 }
   2080 
   2081 void trinity_dpm_fini(struct radeon_device *rdev)
   2082 {
   2083 	int i;
   2084 
   2085 	trinity_cleanup_asic(rdev); /* ??? */
   2086 
   2087 	for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
   2088 		kfree(rdev->pm.dpm.ps[i].ps_priv);
   2089 	}
   2090 	kfree(rdev->pm.dpm.ps);
   2091 	kfree(rdev->pm.dpm.priv);
   2092 	r600_free_extended_power_table(rdev);
   2093 }
   2094 
   2095 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
   2096 {
   2097 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   2098 	struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
   2099 
   2100 	if (low)
   2101 		return requested_state->levels[0].sclk;
   2102 	else
   2103 		return requested_state->levels[requested_state->num_levels - 1].sclk;
   2104 }
   2105 
   2106 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
   2107 {
   2108 	struct trinity_power_info *pi = trinity_get_pi(rdev);
   2109 
   2110 	return pi->sys_info.bootup_uma_clk;
   2111 }
   2112