Linux Audio

Check our new training course

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