Linux Audio

Check our new training course

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