Linux Audio

Check our new training course

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