0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/pci.h>
0025 #include <linux/seq_file.h>
0026
0027 #include "r600_dpm.h"
0028 #include "radeon.h"
0029 #include "radeon_asic.h"
0030 #include "trinity_dpm.h"
0031 #include "trinityd.h"
0032 #include "vce.h"
0033
0034 #define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5
0035 #define TRINITY_MINIMUM_ENGINE_CLOCK 800
0036 #define SCLK_MIN_DIV_INTV_SHIFT 12
0037 #define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000
0038
0039 #ifndef TRINITY_MGCG_SEQUENCE
0040 #define TRINITY_MGCG_SEQUENCE 100
0041
0042 static const u32 trinity_mgcg_shls_default[] =
0043 {
0044
0045 0x0000802c, 0xc0000000, 0xffffffff,
0046 0x00003fc4, 0xc0000000, 0xffffffff,
0047 0x00005448, 0x00000100, 0xffffffff,
0048 0x000055e4, 0x00000100, 0xffffffff,
0049 0x0000160c, 0x00000100, 0xffffffff,
0050 0x00008984, 0x06000100, 0xffffffff,
0051 0x0000c164, 0x00000100, 0xffffffff,
0052 0x00008a18, 0x00000100, 0xffffffff,
0053 0x0000897c, 0x06000100, 0xffffffff,
0054 0x00008b28, 0x00000100, 0xffffffff,
0055 0x00009144, 0x00800200, 0xffffffff,
0056 0x00009a60, 0x00000100, 0xffffffff,
0057 0x00009868, 0x00000100, 0xffffffff,
0058 0x00008d58, 0x00000100, 0xffffffff,
0059 0x00009510, 0x00000100, 0xffffffff,
0060 0x0000949c, 0x00000100, 0xffffffff,
0061 0x00009654, 0x00000100, 0xffffffff,
0062 0x00009030, 0x00000100, 0xffffffff,
0063 0x00009034, 0x00000100, 0xffffffff,
0064 0x00009038, 0x00000100, 0xffffffff,
0065 0x0000903c, 0x00000100, 0xffffffff,
0066 0x00009040, 0x00000100, 0xffffffff,
0067 0x0000a200, 0x00000100, 0xffffffff,
0068 0x0000a204, 0x00000100, 0xffffffff,
0069 0x0000a208, 0x00000100, 0xffffffff,
0070 0x0000a20c, 0x00000100, 0xffffffff,
0071 0x00009744, 0x00000100, 0xffffffff,
0072 0x00003f80, 0x00000100, 0xffffffff,
0073 0x0000a210, 0x00000100, 0xffffffff,
0074 0x0000a214, 0x00000100, 0xffffffff,
0075 0x000004d8, 0x00000100, 0xffffffff,
0076 0x00009664, 0x00000100, 0xffffffff,
0077 0x00009698, 0x00000100, 0xffffffff,
0078 0x000004d4, 0x00000200, 0xffffffff,
0079 0x000004d0, 0x00000000, 0xffffffff,
0080 0x000030cc, 0x00000104, 0xffffffff,
0081 0x0000d0c0, 0x00000100, 0xffffffff,
0082 0x0000d8c0, 0x00000100, 0xffffffff,
0083 0x0000951c, 0x00010000, 0xffffffff,
0084 0x00009160, 0x00030002, 0xffffffff,
0085 0x00009164, 0x00050004, 0xffffffff,
0086 0x00009168, 0x00070006, 0xffffffff,
0087 0x00009178, 0x00070000, 0xffffffff,
0088 0x0000917c, 0x00030002, 0xffffffff,
0089 0x00009180, 0x00050004, 0xffffffff,
0090 0x0000918c, 0x00010006, 0xffffffff,
0091 0x00009190, 0x00090008, 0xffffffff,
0092 0x00009194, 0x00070000, 0xffffffff,
0093 0x00009198, 0x00030002, 0xffffffff,
0094 0x0000919c, 0x00050004, 0xffffffff,
0095 0x000091a8, 0x00010006, 0xffffffff,
0096 0x000091ac, 0x00090008, 0xffffffff,
0097 0x000091b0, 0x00070000, 0xffffffff,
0098 0x000091b4, 0x00030002, 0xffffffff,
0099 0x000091b8, 0x00050004, 0xffffffff,
0100 0x000091c4, 0x00010006, 0xffffffff,
0101 0x000091c8, 0x00090008, 0xffffffff,
0102 0x000091cc, 0x00070000, 0xffffffff,
0103 0x000091d0, 0x00030002, 0xffffffff,
0104 0x000091d4, 0x00050004, 0xffffffff,
0105 0x000091e0, 0x00010006, 0xffffffff,
0106 0x000091e4, 0x00090008, 0xffffffff,
0107 0x000091e8, 0x00000000, 0xffffffff,
0108 0x000091ec, 0x00070000, 0xffffffff,
0109 0x000091f0, 0x00030002, 0xffffffff,
0110 0x000091f4, 0x00050004, 0xffffffff,
0111 0x00009200, 0x00010006, 0xffffffff,
0112 0x00009204, 0x00090008, 0xffffffff,
0113 0x00009208, 0x00070000, 0xffffffff,
0114 0x0000920c, 0x00030002, 0xffffffff,
0115 0x00009210, 0x00050004, 0xffffffff,
0116 0x0000921c, 0x00010006, 0xffffffff,
0117 0x00009220, 0x00090008, 0xffffffff,
0118 0x00009294, 0x00000000, 0xffffffff
0119 };
0120 #endif
0121
0122 #ifndef TRINITY_SYSLS_SEQUENCE
0123 #define TRINITY_SYSLS_SEQUENCE 100
0124
0125 static const u32 trinity_sysls_disable[] =
0126 {
0127
0128 0x0000d0c0, 0x00000000, 0xffffffff,
0129 0x0000d8c0, 0x00000000, 0xffffffff,
0130 0x000055e8, 0x00000000, 0xffffffff,
0131 0x0000d0bc, 0x00000000, 0xffffffff,
0132 0x0000d8bc, 0x00000000, 0xffffffff,
0133 0x000015c0, 0x00041401, 0xffffffff,
0134 0x0000264c, 0x00040400, 0xffffffff,
0135 0x00002648, 0x00040400, 0xffffffff,
0136 0x00002650, 0x00040400, 0xffffffff,
0137 0x000020b8, 0x00040400, 0xffffffff,
0138 0x000020bc, 0x00040400, 0xffffffff,
0139 0x000020c0, 0x00040c80, 0xffffffff,
0140 0x0000f4a0, 0x000000c0, 0xffffffff,
0141 0x0000f4a4, 0x00680000, 0xffffffff,
0142 0x00002f50, 0x00000404, 0xffffffff,
0143 0x000004c8, 0x00000001, 0xffffffff,
0144 0x0000641c, 0x00007ffd, 0xffffffff,
0145 0x00000c7c, 0x0000ff00, 0xffffffff,
0146 0x00006dfc, 0x0000007f, 0xffffffff
0147 };
0148
0149 static const u32 trinity_sysls_enable[] =
0150 {
0151
0152 0x000055e8, 0x00000001, 0xffffffff,
0153 0x0000d0bc, 0x00000100, 0xffffffff,
0154 0x0000d8bc, 0x00000100, 0xffffffff,
0155 0x000015c0, 0x000c1401, 0xffffffff,
0156 0x0000264c, 0x000c0400, 0xffffffff,
0157 0x00002648, 0x000c0400, 0xffffffff,
0158 0x00002650, 0x000c0400, 0xffffffff,
0159 0x000020b8, 0x000c0400, 0xffffffff,
0160 0x000020bc, 0x000c0400, 0xffffffff,
0161 0x000020c0, 0x000c0c80, 0xffffffff,
0162 0x0000f4a0, 0x000000c0, 0xffffffff,
0163 0x0000f4a4, 0x00680fff, 0xffffffff,
0164 0x00002f50, 0x00000903, 0xffffffff,
0165 0x000004c8, 0x00000000, 0xffffffff,
0166 0x0000641c, 0x00000000, 0xffffffff,
0167 0x00000c7c, 0x00000000, 0xffffffff,
0168 0x00006dfc, 0x00000000, 0xffffffff
0169 };
0170 #endif
0171
0172 static const u32 trinity_override_mgpg_sequences[] =
0173 {
0174
0175 0x00000200, 0xE030032C,
0176 0x00000204, 0x00000FFF,
0177 0x00000200, 0xE0300058,
0178 0x00000204, 0x00030301,
0179 0x00000200, 0xE0300054,
0180 0x00000204, 0x500010FF,
0181 0x00000200, 0xE0300074,
0182 0x00000204, 0x00030301,
0183 0x00000200, 0xE0300070,
0184 0x00000204, 0x500010FF,
0185 0x00000200, 0xE0300090,
0186 0x00000204, 0x00030301,
0187 0x00000200, 0xE030008C,
0188 0x00000204, 0x500010FF,
0189 0x00000200, 0xE03000AC,
0190 0x00000204, 0x00030301,
0191 0x00000200, 0xE03000A8,
0192 0x00000204, 0x500010FF,
0193 0x00000200, 0xE03000C8,
0194 0x00000204, 0x00030301,
0195 0x00000200, 0xE03000C4,
0196 0x00000204, 0x500010FF,
0197 0x00000200, 0xE03000E4,
0198 0x00000204, 0x00030301,
0199 0x00000200, 0xE03000E0,
0200 0x00000204, 0x500010FF,
0201 0x00000200, 0xE0300100,
0202 0x00000204, 0x00030301,
0203 0x00000200, 0xE03000FC,
0204 0x00000204, 0x500010FF,
0205 0x00000200, 0xE0300058,
0206 0x00000204, 0x00030303,
0207 0x00000200, 0xE0300054,
0208 0x00000204, 0x600010FF,
0209 0x00000200, 0xE0300074,
0210 0x00000204, 0x00030303,
0211 0x00000200, 0xE0300070,
0212 0x00000204, 0x600010FF,
0213 0x00000200, 0xE0300090,
0214 0x00000204, 0x00030303,
0215 0x00000200, 0xE030008C,
0216 0x00000204, 0x600010FF,
0217 0x00000200, 0xE03000AC,
0218 0x00000204, 0x00030303,
0219 0x00000200, 0xE03000A8,
0220 0x00000204, 0x600010FF,
0221 0x00000200, 0xE03000C8,
0222 0x00000204, 0x00030303,
0223 0x00000200, 0xE03000C4,
0224 0x00000204, 0x600010FF,
0225 0x00000200, 0xE03000E4,
0226 0x00000204, 0x00030303,
0227 0x00000200, 0xE03000E0,
0228 0x00000204, 0x600010FF,
0229 0x00000200, 0xE0300100,
0230 0x00000204, 0x00030303,
0231 0x00000200, 0xE03000FC,
0232 0x00000204, 0x600010FF,
0233 0x00000200, 0xE0300058,
0234 0x00000204, 0x00030303,
0235 0x00000200, 0xE0300054,
0236 0x00000204, 0x700010FF,
0237 0x00000200, 0xE0300074,
0238 0x00000204, 0x00030303,
0239 0x00000200, 0xE0300070,
0240 0x00000204, 0x700010FF,
0241 0x00000200, 0xE0300090,
0242 0x00000204, 0x00030303,
0243 0x00000200, 0xE030008C,
0244 0x00000204, 0x700010FF,
0245 0x00000200, 0xE03000AC,
0246 0x00000204, 0x00030303,
0247 0x00000200, 0xE03000A8,
0248 0x00000204, 0x700010FF,
0249 0x00000200, 0xE03000C8,
0250 0x00000204, 0x00030303,
0251 0x00000200, 0xE03000C4,
0252 0x00000204, 0x700010FF,
0253 0x00000200, 0xE03000E4,
0254 0x00000204, 0x00030303,
0255 0x00000200, 0xE03000E0,
0256 0x00000204, 0x700010FF,
0257 0x00000200, 0xE0300100,
0258 0x00000204, 0x00030303,
0259 0x00000200, 0xE03000FC,
0260 0x00000204, 0x700010FF,
0261 0x00000200, 0xE0300058,
0262 0x00000204, 0x00010303,
0263 0x00000200, 0xE0300054,
0264 0x00000204, 0x800010FF,
0265 0x00000200, 0xE0300074,
0266 0x00000204, 0x00010303,
0267 0x00000200, 0xE0300070,
0268 0x00000204, 0x800010FF,
0269 0x00000200, 0xE0300090,
0270 0x00000204, 0x00010303,
0271 0x00000200, 0xE030008C,
0272 0x00000204, 0x800010FF,
0273 0x00000200, 0xE03000AC,
0274 0x00000204, 0x00010303,
0275 0x00000200, 0xE03000A8,
0276 0x00000204, 0x800010FF,
0277 0x00000200, 0xE03000C4,
0278 0x00000204, 0x800010FF,
0279 0x00000200, 0xE03000C8,
0280 0x00000204, 0x00010303,
0281 0x00000200, 0xE03000E4,
0282 0x00000204, 0x00010303,
0283 0x00000200, 0xE03000E0,
0284 0x00000204, 0x800010FF,
0285 0x00000200, 0xE0300100,
0286 0x00000204, 0x00010303,
0287 0x00000200, 0xE03000FC,
0288 0x00000204, 0x800010FF,
0289 0x00000200, 0x0001f198,
0290 0x00000204, 0x0003ffff,
0291 0x00000200, 0x0001f19C,
0292 0x00000204, 0x3fffffff,
0293 0x00000200, 0xE030032C,
0294 0x00000204, 0x00000000,
0295 };
0296
0297 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
0298 const u32 *seq, u32 count);
0299 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev);
0300 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
0301 struct radeon_ps *new_rps,
0302 struct radeon_ps *old_rps);
0303
0304 static struct trinity_ps *trinity_get_ps(struct radeon_ps *rps)
0305 {
0306 struct trinity_ps *ps = rps->ps_priv;
0307
0308 return ps;
0309 }
0310
0311 static struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev)
0312 {
0313 struct trinity_power_info *pi = rdev->pm.dpm.priv;
0314
0315 return pi;
0316 }
0317
0318 static void trinity_gfx_powergating_initialize(struct radeon_device *rdev)
0319 {
0320 struct trinity_power_info *pi = trinity_get_pi(rdev);
0321 u32 p, u;
0322 u32 value;
0323 struct atom_clock_dividers dividers;
0324 u32 xclk = radeon_get_xclk(rdev);
0325 u32 sssd = 1;
0326 int ret;
0327 u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
0328
0329 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
0330 25000, false, ÷rs);
0331 if (ret)
0332 return;
0333
0334 value = RREG32_SMC(GFX_POWER_GATING_CNTL);
0335 value &= ~(SSSD_MASK | PDS_DIV_MASK);
0336 if (sssd)
0337 value |= SSSD(1);
0338 value |= PDS_DIV(dividers.post_div);
0339 WREG32_SMC(GFX_POWER_GATING_CNTL, value);
0340
0341 r600_calculate_u_and_p(500, xclk, 16, &p, &u);
0342
0343 WREG32(CG_PG_CTRL, SP(p) | SU(u));
0344
0345 WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK);
0346
0347
0348 if (pi->override_dynamic_mgpg && (hw_rev == 0))
0349 trinity_override_dynamic_mg_powergating(rdev);
0350
0351 }
0352
0353 #define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF
0354 #define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE
0355 #define CGTS_SM_CTRL_REG_DISABLE 0x00600000
0356 #define CGTS_SM_CTRL_REG_ENABLE 0x96944200
0357
0358 static void trinity_mg_clockgating_enable(struct radeon_device *rdev,
0359 bool enable)
0360 {
0361 u32 local0;
0362 u32 local1;
0363
0364 if (enable) {
0365 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
0366 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
0367
0368 WREG32_CG(CG_CGTT_LOCAL_0,
0369 (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
0370 WREG32_CG(CG_CGTT_LOCAL_1,
0371 (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
0372
0373 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE);
0374 } else {
0375 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE);
0376
0377 local0 = RREG32_CG(CG_CGTT_LOCAL_0);
0378 local1 = RREG32_CG(CG_CGTT_LOCAL_1);
0379
0380 WREG32_CG(CG_CGTT_LOCAL_0,
0381 CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
0382 WREG32_CG(CG_CGTT_LOCAL_1,
0383 CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
0384 }
0385 }
0386
0387 static void trinity_mg_clockgating_initialize(struct radeon_device *rdev)
0388 {
0389 u32 count;
0390 const u32 *seq = NULL;
0391
0392 seq = &trinity_mgcg_shls_default[0];
0393 count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32));
0394
0395 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
0396 }
0397
0398 static void trinity_gfx_clockgating_enable(struct radeon_device *rdev,
0399 bool enable)
0400 {
0401 if (enable) {
0402 WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
0403 } else {
0404 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
0405 WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
0406 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
0407 RREG32(GB_ADDR_CONFIG);
0408 }
0409 }
0410
0411 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev,
0412 const u32 *seq, u32 count)
0413 {
0414 u32 i, length = count * 3;
0415
0416 for (i = 0; i < length; i += 3)
0417 WREG32_P(seq[i], seq[i+1], ~seq[i+2]);
0418 }
0419
0420 static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev,
0421 const u32 *seq, u32 count)
0422 {
0423 u32 i, length = count * 2;
0424
0425 for (i = 0; i < length; i += 2)
0426 WREG32(seq[i], seq[i+1]);
0427
0428 }
0429
0430 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev)
0431 {
0432 u32 count;
0433 const u32 *seq = NULL;
0434
0435 seq = &trinity_override_mgpg_sequences[0];
0436 count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32));
0437
0438 trinity_program_override_mgpg_sequences(rdev, seq, count);
0439 }
0440
0441 static void trinity_ls_clockgating_enable(struct radeon_device *rdev,
0442 bool enable)
0443 {
0444 u32 count;
0445 const u32 *seq = NULL;
0446
0447 if (enable) {
0448 seq = &trinity_sysls_enable[0];
0449 count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32));
0450 } else {
0451 seq = &trinity_sysls_disable[0];
0452 count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32));
0453 }
0454
0455 trinity_program_clk_gating_hw_sequence(rdev, seq, count);
0456 }
0457
0458 static void trinity_gfx_powergating_enable(struct radeon_device *rdev,
0459 bool enable)
0460 {
0461 if (enable) {
0462 if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK)
0463 WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01));
0464
0465 WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
0466 } else {
0467 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN);
0468 RREG32(GB_ADDR_CONFIG);
0469 }
0470 }
0471
0472 static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev,
0473 bool enable)
0474 {
0475 u32 value;
0476
0477 if (enable) {
0478 value = RREG32_SMC(PM_I_CNTL_1);
0479 value &= ~DS_PG_CNTL_MASK;
0480 value |= DS_PG_CNTL(1);
0481 WREG32_SMC(PM_I_CNTL_1, value);
0482
0483 value = RREG32_SMC(SMU_S_PG_CNTL);
0484 value &= ~DS_PG_EN_MASK;
0485 value |= DS_PG_EN(1);
0486 WREG32_SMC(SMU_S_PG_CNTL, value);
0487 } else {
0488 value = RREG32_SMC(SMU_S_PG_CNTL);
0489 value &= ~DS_PG_EN_MASK;
0490 WREG32_SMC(SMU_S_PG_CNTL, value);
0491
0492 value = RREG32_SMC(PM_I_CNTL_1);
0493 value &= ~DS_PG_CNTL_MASK;
0494 WREG32_SMC(PM_I_CNTL_1, value);
0495 }
0496
0497 trinity_gfx_dynamic_mgpg_config(rdev);
0498
0499 }
0500
0501 static void trinity_enable_clock_power_gating(struct radeon_device *rdev)
0502 {
0503 struct trinity_power_info *pi = trinity_get_pi(rdev);
0504
0505 if (pi->enable_gfx_clock_gating)
0506 sumo_gfx_clockgating_initialize(rdev);
0507 if (pi->enable_mg_clock_gating)
0508 trinity_mg_clockgating_initialize(rdev);
0509 if (pi->enable_gfx_power_gating)
0510 trinity_gfx_powergating_initialize(rdev);
0511 if (pi->enable_mg_clock_gating) {
0512 trinity_ls_clockgating_enable(rdev, true);
0513 trinity_mg_clockgating_enable(rdev, true);
0514 }
0515 if (pi->enable_gfx_clock_gating)
0516 trinity_gfx_clockgating_enable(rdev, true);
0517 if (pi->enable_gfx_dynamic_mgpg)
0518 trinity_gfx_dynamic_mgpg_enable(rdev, true);
0519 if (pi->enable_gfx_power_gating)
0520 trinity_gfx_powergating_enable(rdev, true);
0521 }
0522
0523 static void trinity_disable_clock_power_gating(struct radeon_device *rdev)
0524 {
0525 struct trinity_power_info *pi = trinity_get_pi(rdev);
0526
0527 if (pi->enable_gfx_power_gating)
0528 trinity_gfx_powergating_enable(rdev, false);
0529 if (pi->enable_gfx_dynamic_mgpg)
0530 trinity_gfx_dynamic_mgpg_enable(rdev, false);
0531 if (pi->enable_gfx_clock_gating)
0532 trinity_gfx_clockgating_enable(rdev, false);
0533 if (pi->enable_mg_clock_gating) {
0534 trinity_mg_clockgating_enable(rdev, false);
0535 trinity_ls_clockgating_enable(rdev, false);
0536 }
0537 }
0538
0539 static void trinity_set_divider_value(struct radeon_device *rdev,
0540 u32 index, u32 sclk)
0541 {
0542 struct atom_clock_dividers dividers;
0543 int ret;
0544 u32 value;
0545 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0546
0547 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
0548 sclk, false, ÷rs);
0549 if (ret)
0550 return;
0551
0552 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
0553 value &= ~CLK_DIVIDER_MASK;
0554 value |= CLK_DIVIDER(dividers.post_div);
0555 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
0556
0557 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
0558 sclk/2, false, ÷rs);
0559 if (ret)
0560 return;
0561
0562 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix);
0563 value &= ~PD_SCLK_DIVIDER_MASK;
0564 value |= PD_SCLK_DIVIDER(dividers.post_div);
0565 WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value);
0566 }
0567
0568 static void trinity_set_ds_dividers(struct radeon_device *rdev,
0569 u32 index, u32 divider)
0570 {
0571 u32 value;
0572 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0573
0574 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
0575 value &= ~DS_DIV_MASK;
0576 value |= DS_DIV(divider);
0577 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
0578 }
0579
0580 static void trinity_set_ss_dividers(struct radeon_device *rdev,
0581 u32 index, u32 divider)
0582 {
0583 u32 value;
0584 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0585
0586 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
0587 value &= ~DS_SH_DIV_MASK;
0588 value |= DS_SH_DIV(divider);
0589 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
0590 }
0591
0592 static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
0593 {
0594 struct trinity_power_info *pi = trinity_get_pi(rdev);
0595 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid);
0596 u32 value;
0597 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0598
0599 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
0600 value &= ~VID_MASK;
0601 value |= VID(vid_7bit);
0602 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
0603
0604 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
0605 value &= ~LVRT_MASK;
0606 value |= LVRT(0);
0607 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
0608 }
0609
0610 static void trinity_set_allos_gnb_slow(struct radeon_device *rdev,
0611 u32 index, u32 gnb_slow)
0612 {
0613 u32 value;
0614 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0615
0616 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
0617 value &= ~GNB_SLOW_MASK;
0618 value |= GNB_SLOW(gnb_slow);
0619 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
0620 }
0621
0622 static void trinity_set_force_nbp_state(struct radeon_device *rdev,
0623 u32 index, u32 force_nbp_state)
0624 {
0625 u32 value;
0626 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0627
0628 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix);
0629 value &= ~FORCE_NBPS1_MASK;
0630 value |= FORCE_NBPS1(force_nbp_state);
0631 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value);
0632 }
0633
0634 static void trinity_set_display_wm(struct radeon_device *rdev,
0635 u32 index, u32 wm)
0636 {
0637 u32 value;
0638 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0639
0640 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
0641 value &= ~DISPLAY_WM_MASK;
0642 value |= DISPLAY_WM(wm);
0643 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
0644 }
0645
0646 static void trinity_set_vce_wm(struct radeon_device *rdev,
0647 u32 index, u32 wm)
0648 {
0649 u32 value;
0650 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0651
0652 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix);
0653 value &= ~VCE_WM_MASK;
0654 value |= VCE_WM(wm);
0655 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value);
0656 }
0657
0658 static void trinity_set_at(struct radeon_device *rdev,
0659 u32 index, u32 at)
0660 {
0661 u32 value;
0662 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0663
0664 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix);
0665 value &= ~AT_MASK;
0666 value |= AT(at);
0667 WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value);
0668 }
0669
0670 static void trinity_program_power_level(struct radeon_device *rdev,
0671 struct trinity_pl *pl, u32 index)
0672 {
0673 struct trinity_power_info *pi = trinity_get_pi(rdev);
0674
0675 if (index >= SUMO_MAX_HARDWARE_POWERLEVELS)
0676 return;
0677
0678 trinity_set_divider_value(rdev, index, pl->sclk);
0679 trinity_set_vid(rdev, index, pl->vddc_index);
0680 trinity_set_ss_dividers(rdev, index, pl->ss_divider_index);
0681 trinity_set_ds_dividers(rdev, index, pl->ds_divider_index);
0682 trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
0683 trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state);
0684 trinity_set_display_wm(rdev, index, pl->display_wm);
0685 trinity_set_vce_wm(rdev, index, pl->vce_wm);
0686 trinity_set_at(rdev, index, pi->at[index]);
0687 }
0688
0689 static void trinity_power_level_enable_disable(struct radeon_device *rdev,
0690 u32 index, bool enable)
0691 {
0692 u32 value;
0693 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE;
0694
0695 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix);
0696 value &= ~STATE_VALID_MASK;
0697 if (enable)
0698 value |= STATE_VALID(1);
0699 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value);
0700 }
0701
0702 static bool trinity_dpm_enabled(struct radeon_device *rdev)
0703 {
0704 if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1))
0705 return true;
0706 else
0707 return false;
0708 }
0709
0710 static void trinity_start_dpm(struct radeon_device *rdev)
0711 {
0712 u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL);
0713
0714 value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK);
0715 value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1);
0716 WREG32_SMC(SMU_SCLK_DPM_CNTL, value);
0717
0718 WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
0719 WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN);
0720
0721 trinity_dpm_config(rdev, true);
0722 }
0723
0724 static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev)
0725 {
0726 int i;
0727
0728 for (i = 0; i < rdev->usec_timeout; i++) {
0729 if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN)
0730 break;
0731 udelay(1);
0732 }
0733 for (i = 0; i < rdev->usec_timeout; i++) {
0734 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0)
0735 break;
0736 udelay(1);
0737 }
0738 for (i = 0; i < rdev->usec_timeout; i++) {
0739 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
0740 break;
0741 udelay(1);
0742 }
0743 }
0744
0745 static void trinity_stop_dpm(struct radeon_device *rdev)
0746 {
0747 u32 sclk_dpm_cntl;
0748
0749 WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN);
0750
0751 sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL);
0752 sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK);
0753 WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl);
0754
0755 trinity_dpm_config(rdev, false);
0756 }
0757
0758 static void trinity_start_am(struct radeon_device *rdev)
0759 {
0760 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
0761 }
0762
0763 static void trinity_reset_am(struct radeon_device *rdev)
0764 {
0765 WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT,
0766 ~(RESET_SCLK_CNT | RESET_BUSY_CNT));
0767 }
0768
0769 static void trinity_wait_for_level_0(struct radeon_device *rdev)
0770 {
0771 int i;
0772
0773 for (i = 0; i < rdev->usec_timeout; i++) {
0774 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0)
0775 break;
0776 udelay(1);
0777 }
0778 }
0779
0780 static void trinity_enable_power_level_0(struct radeon_device *rdev)
0781 {
0782 trinity_power_level_enable_disable(rdev, 0, true);
0783 }
0784
0785 static void trinity_force_level_0(struct radeon_device *rdev)
0786 {
0787 trinity_dpm_force_state(rdev, 0);
0788 }
0789
0790 static void trinity_unforce_levels(struct radeon_device *rdev)
0791 {
0792 trinity_dpm_no_forced_level(rdev);
0793 }
0794
0795 static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev,
0796 struct radeon_ps *new_rps,
0797 struct radeon_ps *old_rps)
0798 {
0799 struct trinity_ps *new_ps = trinity_get_ps(new_rps);
0800 struct trinity_ps *old_ps = trinity_get_ps(old_rps);
0801 u32 i;
0802 u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
0803
0804 for (i = 0; i < new_ps->num_levels; i++) {
0805 trinity_program_power_level(rdev, &new_ps->levels[i], i);
0806 trinity_power_level_enable_disable(rdev, i, true);
0807 }
0808
0809 for (i = new_ps->num_levels; i < n_current_state_levels; i++)
0810 trinity_power_level_enable_disable(rdev, i, false);
0811 }
0812
0813 static void trinity_program_bootup_state(struct radeon_device *rdev)
0814 {
0815 struct trinity_power_info *pi = trinity_get_pi(rdev);
0816 u32 i;
0817
0818 trinity_program_power_level(rdev, &pi->boot_pl, 0);
0819 trinity_power_level_enable_disable(rdev, 0, true);
0820
0821 for (i = 1; i < 8; i++)
0822 trinity_power_level_enable_disable(rdev, i, false);
0823 }
0824
0825 static void trinity_setup_uvd_clock_table(struct radeon_device *rdev,
0826 struct radeon_ps *rps)
0827 {
0828 struct trinity_ps *ps = trinity_get_ps(rps);
0829 u32 uvdstates = (ps->vclk_low_divider |
0830 ps->vclk_high_divider << 8 |
0831 ps->dclk_low_divider << 16 |
0832 ps->dclk_high_divider << 24);
0833
0834 WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates);
0835 }
0836
0837 static void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev,
0838 u32 interval)
0839 {
0840 u32 p, u;
0841 u32 tp = RREG32_SMC(PM_TP);
0842 u32 val;
0843 u32 xclk = radeon_get_xclk(rdev);
0844
0845 r600_calculate_u_and_p(interval, xclk, 16, &p, &u);
0846
0847 val = (p + tp - 1) / tp;
0848
0849 WREG32_SMC(SMU_UVD_DPM_CNTL, val);
0850 }
0851
0852 static bool trinity_uvd_clocks_zero(struct radeon_ps *rps)
0853 {
0854 if ((rps->vclk == 0) && (rps->dclk == 0))
0855 return true;
0856 else
0857 return false;
0858 }
0859
0860 static bool trinity_uvd_clocks_equal(struct radeon_ps *rps1,
0861 struct radeon_ps *rps2)
0862 {
0863 struct trinity_ps *ps1 = trinity_get_ps(rps1);
0864 struct trinity_ps *ps2 = trinity_get_ps(rps2);
0865
0866 if ((rps1->vclk == rps2->vclk) &&
0867 (rps1->dclk == rps2->dclk) &&
0868 (ps1->vclk_low_divider == ps2->vclk_low_divider) &&
0869 (ps1->vclk_high_divider == ps2->vclk_high_divider) &&
0870 (ps1->dclk_low_divider == ps2->dclk_low_divider) &&
0871 (ps1->dclk_high_divider == ps2->dclk_high_divider))
0872 return true;
0873 else
0874 return false;
0875 }
0876
0877 static void trinity_setup_uvd_clocks(struct radeon_device *rdev,
0878 struct radeon_ps *new_rps,
0879 struct radeon_ps *old_rps)
0880 {
0881 struct trinity_power_info *pi = trinity_get_pi(rdev);
0882
0883 if (pi->enable_gfx_power_gating) {
0884 trinity_gfx_powergating_enable(rdev, false);
0885 }
0886
0887 if (pi->uvd_dpm) {
0888 if (trinity_uvd_clocks_zero(new_rps) &&
0889 !trinity_uvd_clocks_zero(old_rps)) {
0890 trinity_setup_uvd_dpm_interval(rdev, 0);
0891 } else if (!trinity_uvd_clocks_zero(new_rps)) {
0892 trinity_setup_uvd_clock_table(rdev, new_rps);
0893
0894 if (trinity_uvd_clocks_zero(old_rps)) {
0895 u32 tmp = RREG32(CG_MISC_REG);
0896 tmp &= 0xfffffffd;
0897 WREG32(CG_MISC_REG, tmp);
0898
0899 radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
0900
0901 trinity_setup_uvd_dpm_interval(rdev, 3000);
0902 }
0903 }
0904 trinity_uvd_dpm_config(rdev);
0905 } else {
0906 if (trinity_uvd_clocks_zero(new_rps) ||
0907 trinity_uvd_clocks_equal(new_rps, old_rps))
0908 return;
0909
0910 radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
0911 }
0912
0913 if (pi->enable_gfx_power_gating) {
0914 trinity_gfx_powergating_enable(rdev, true);
0915 }
0916 }
0917
0918 static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
0919 struct radeon_ps *new_rps,
0920 struct radeon_ps *old_rps)
0921 {
0922 struct trinity_ps *new_ps = trinity_get_ps(new_rps);
0923 struct trinity_ps *current_ps = trinity_get_ps(new_rps);
0924
0925 if (new_ps->levels[new_ps->num_levels - 1].sclk >=
0926 current_ps->levels[current_ps->num_levels - 1].sclk)
0927 return;
0928
0929 trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
0930 }
0931
0932 static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
0933 struct radeon_ps *new_rps,
0934 struct radeon_ps *old_rps)
0935 {
0936 struct trinity_ps *new_ps = trinity_get_ps(new_rps);
0937 struct trinity_ps *current_ps = trinity_get_ps(old_rps);
0938
0939 if (new_ps->levels[new_ps->num_levels - 1].sclk <
0940 current_ps->levels[current_ps->num_levels - 1].sclk)
0941 return;
0942
0943 trinity_setup_uvd_clocks(rdev, new_rps, old_rps);
0944 }
0945
0946 static void trinity_set_vce_clock(struct radeon_device *rdev,
0947 struct radeon_ps *new_rps,
0948 struct radeon_ps *old_rps)
0949 {
0950 if ((old_rps->evclk != new_rps->evclk) ||
0951 (old_rps->ecclk != new_rps->ecclk)) {
0952
0953 if (new_rps->evclk || new_rps->ecclk)
0954 vce_v1_0_enable_mgcg(rdev, false);
0955 else
0956 vce_v1_0_enable_mgcg(rdev, true);
0957 radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk);
0958 }
0959 }
0960
0961 static void trinity_program_ttt(struct radeon_device *rdev)
0962 {
0963 struct trinity_power_info *pi = trinity_get_pi(rdev);
0964 u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT);
0965
0966 value &= ~(HT_MASK | LT_MASK);
0967 value |= HT((pi->thermal_auto_throttling + 49) * 8);
0968 value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8);
0969 WREG32_SMC(SMU_SCLK_DPM_TTT, value);
0970 }
0971
0972 static void trinity_enable_att(struct radeon_device *rdev)
0973 {
0974 u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL);
0975
0976 value &= ~SCLK_TT_EN_MASK;
0977 value |= SCLK_TT_EN(1);
0978 WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value);
0979 }
0980
0981 static void trinity_program_sclk_dpm(struct radeon_device *rdev)
0982 {
0983 u32 p, u;
0984 u32 tp = RREG32_SMC(PM_TP);
0985 u32 ni;
0986 u32 xclk = radeon_get_xclk(rdev);
0987 u32 value;
0988
0989 r600_calculate_u_and_p(400, xclk, 16, &p, &u);
0990
0991 ni = (p + tp - 1) / tp;
0992
0993 value = RREG32_SMC(PM_I_CNTL_1);
0994 value &= ~SCLK_DPM_MASK;
0995 value |= SCLK_DPM(ni);
0996 WREG32_SMC(PM_I_CNTL_1, value);
0997 }
0998
0999 static int trinity_set_thermal_temperature_range(struct radeon_device *rdev,
1000 int min_temp, int max_temp)
1001 {
1002 int low_temp = 0 * 1000;
1003 int high_temp = 255 * 1000;
1004
1005 if (low_temp < min_temp)
1006 low_temp = min_temp;
1007 if (high_temp > max_temp)
1008 high_temp = max_temp;
1009 if (high_temp < low_temp) {
1010 DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
1011 return -EINVAL;
1012 }
1013
1014 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
1015 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
1016
1017 rdev->pm.dpm.thermal.min_temp = low_temp;
1018 rdev->pm.dpm.thermal.max_temp = high_temp;
1019
1020 return 0;
1021 }
1022
1023 static void trinity_update_current_ps(struct radeon_device *rdev,
1024 struct radeon_ps *rps)
1025 {
1026 struct trinity_ps *new_ps = trinity_get_ps(rps);
1027 struct trinity_power_info *pi = trinity_get_pi(rdev);
1028
1029 pi->current_rps = *rps;
1030 pi->current_ps = *new_ps;
1031 pi->current_rps.ps_priv = &pi->current_ps;
1032 }
1033
1034 static void trinity_update_requested_ps(struct radeon_device *rdev,
1035 struct radeon_ps *rps)
1036 {
1037 struct trinity_ps *new_ps = trinity_get_ps(rps);
1038 struct trinity_power_info *pi = trinity_get_pi(rdev);
1039
1040 pi->requested_rps = *rps;
1041 pi->requested_ps = *new_ps;
1042 pi->requested_rps.ps_priv = &pi->requested_ps;
1043 }
1044
1045 void trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
1046 {
1047 struct trinity_power_info *pi = trinity_get_pi(rdev);
1048
1049 if (pi->enable_bapm) {
1050 trinity_acquire_mutex(rdev);
1051 trinity_dpm_bapm_enable(rdev, enable);
1052 trinity_release_mutex(rdev);
1053 }
1054 }
1055
1056 int trinity_dpm_enable(struct radeon_device *rdev)
1057 {
1058 struct trinity_power_info *pi = trinity_get_pi(rdev);
1059
1060 trinity_acquire_mutex(rdev);
1061
1062 if (trinity_dpm_enabled(rdev)) {
1063 trinity_release_mutex(rdev);
1064 return -EINVAL;
1065 }
1066
1067 trinity_program_bootup_state(rdev);
1068 sumo_program_vc(rdev, 0x00C00033);
1069 trinity_start_am(rdev);
1070 if (pi->enable_auto_thermal_throttling) {
1071 trinity_program_ttt(rdev);
1072 trinity_enable_att(rdev);
1073 }
1074 trinity_program_sclk_dpm(rdev);
1075 trinity_start_dpm(rdev);
1076 trinity_wait_for_dpm_enabled(rdev);
1077 trinity_dpm_bapm_enable(rdev, false);
1078 trinity_release_mutex(rdev);
1079
1080 trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1081
1082 return 0;
1083 }
1084
1085 int trinity_dpm_late_enable(struct radeon_device *rdev)
1086 {
1087 int ret;
1088
1089 trinity_acquire_mutex(rdev);
1090 trinity_enable_clock_power_gating(rdev);
1091
1092 if (rdev->irq.installed &&
1093 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1094 ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
1095 if (ret) {
1096 trinity_release_mutex(rdev);
1097 return ret;
1098 }
1099 rdev->irq.dpm_thermal = true;
1100 radeon_irq_set(rdev);
1101 }
1102 trinity_release_mutex(rdev);
1103
1104 return 0;
1105 }
1106
1107 void trinity_dpm_disable(struct radeon_device *rdev)
1108 {
1109 trinity_acquire_mutex(rdev);
1110 if (!trinity_dpm_enabled(rdev)) {
1111 trinity_release_mutex(rdev);
1112 return;
1113 }
1114 trinity_dpm_bapm_enable(rdev, false);
1115 trinity_disable_clock_power_gating(rdev);
1116 sumo_clear_vc(rdev);
1117 trinity_wait_for_level_0(rdev);
1118 trinity_stop_dpm(rdev);
1119 trinity_reset_am(rdev);
1120 trinity_release_mutex(rdev);
1121
1122 if (rdev->irq.installed &&
1123 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1124 rdev->irq.dpm_thermal = false;
1125 radeon_irq_set(rdev);
1126 }
1127
1128 trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
1129 }
1130
1131 static void trinity_get_min_sclk_divider(struct radeon_device *rdev)
1132 {
1133 struct trinity_power_info *pi = trinity_get_pi(rdev);
1134
1135 pi->min_sclk_did =
1136 (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT;
1137 }
1138
1139 static void trinity_setup_nbp_sim(struct radeon_device *rdev,
1140 struct radeon_ps *rps)
1141 {
1142 struct trinity_power_info *pi = trinity_get_pi(rdev);
1143 struct trinity_ps *new_ps = trinity_get_ps(rps);
1144 u32 nbpsconfig;
1145
1146 if (pi->sys_info.nb_dpm_enable) {
1147 nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG);
1148 nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK);
1149 nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) |
1150 Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) |
1151 DpmXNbPsLo(new_ps->DpmXNbPsLo) |
1152 DpmXNbPsHi(new_ps->DpmXNbPsHi));
1153 WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig);
1154 }
1155 }
1156
1157 int trinity_dpm_force_performance_level(struct radeon_device *rdev,
1158 enum radeon_dpm_forced_level level)
1159 {
1160 struct trinity_power_info *pi = trinity_get_pi(rdev);
1161 struct radeon_ps *rps = &pi->current_rps;
1162 struct trinity_ps *ps = trinity_get_ps(rps);
1163 int i, ret;
1164
1165 if (ps->num_levels <= 1)
1166 return 0;
1167
1168 if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
1169
1170 return -EINVAL;
1171 } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
1172 ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1);
1173 if (ret)
1174 return ret;
1175 } else {
1176 for (i = 0; i < ps->num_levels; i++) {
1177 ret = trinity_dpm_n_levels_disabled(rdev, 0);
1178 if (ret)
1179 return ret;
1180 }
1181 }
1182
1183 rdev->pm.dpm.forced_level = level;
1184
1185 return 0;
1186 }
1187
1188 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev)
1189 {
1190 struct trinity_power_info *pi = trinity_get_pi(rdev);
1191 struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
1192 struct radeon_ps *new_ps = &requested_ps;
1193
1194 trinity_update_requested_ps(rdev, new_ps);
1195
1196 trinity_apply_state_adjust_rules(rdev,
1197 &pi->requested_rps,
1198 &pi->current_rps);
1199
1200 return 0;
1201 }
1202
1203 int trinity_dpm_set_power_state(struct radeon_device *rdev)
1204 {
1205 struct trinity_power_info *pi = trinity_get_pi(rdev);
1206 struct radeon_ps *new_ps = &pi->requested_rps;
1207 struct radeon_ps *old_ps = &pi->current_rps;
1208
1209 trinity_acquire_mutex(rdev);
1210 if (pi->enable_dpm) {
1211 if (pi->enable_bapm)
1212 trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power);
1213 trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
1214 trinity_enable_power_level_0(rdev);
1215 trinity_force_level_0(rdev);
1216 trinity_wait_for_level_0(rdev);
1217 trinity_setup_nbp_sim(rdev, new_ps);
1218 trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps);
1219 trinity_force_level_0(rdev);
1220 trinity_unforce_levels(rdev);
1221 trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
1222 trinity_set_vce_clock(rdev, new_ps, old_ps);
1223 }
1224 trinity_release_mutex(rdev);
1225
1226 return 0;
1227 }
1228
1229 void trinity_dpm_post_set_power_state(struct radeon_device *rdev)
1230 {
1231 struct trinity_power_info *pi = trinity_get_pi(rdev);
1232 struct radeon_ps *new_ps = &pi->requested_rps;
1233
1234 trinity_update_current_ps(rdev, new_ps);
1235 }
1236
1237 void trinity_dpm_setup_asic(struct radeon_device *rdev)
1238 {
1239 trinity_acquire_mutex(rdev);
1240 sumo_program_sstp(rdev);
1241 sumo_take_smu_control(rdev, true);
1242 trinity_get_min_sclk_divider(rdev);
1243 trinity_release_mutex(rdev);
1244 }
1245
1246 #if 0
1247 void trinity_dpm_reset_asic(struct radeon_device *rdev)
1248 {
1249 struct trinity_power_info *pi = trinity_get_pi(rdev);
1250
1251 trinity_acquire_mutex(rdev);
1252 if (pi->enable_dpm) {
1253 trinity_enable_power_level_0(rdev);
1254 trinity_force_level_0(rdev);
1255 trinity_wait_for_level_0(rdev);
1256 trinity_program_bootup_state(rdev);
1257 trinity_force_level_0(rdev);
1258 trinity_unforce_levels(rdev);
1259 }
1260 trinity_release_mutex(rdev);
1261 }
1262 #endif
1263
1264 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev,
1265 u32 vid_2bit)
1266 {
1267 struct trinity_power_info *pi = trinity_get_pi(rdev);
1268 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
1269 u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0;
1270 u32 step = (svi_mode == 0) ? 1250 : 625;
1271 u32 delta = vid_7bit * step + 50;
1272
1273 if (delta > 155000)
1274 return 0;
1275
1276 return (155000 - delta) / 100;
1277 }
1278
1279 static void trinity_patch_boot_state(struct radeon_device *rdev,
1280 struct trinity_ps *ps)
1281 {
1282 struct trinity_power_info *pi = trinity_get_pi(rdev);
1283
1284 ps->num_levels = 1;
1285 ps->nbps_flags = 0;
1286 ps->bapm_flags = 0;
1287 ps->levels[0] = pi->boot_pl;
1288 }
1289
1290 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk)
1291 {
1292 if (sclk < 20000)
1293 return 1;
1294 return 0;
1295 }
1296
1297 static void trinity_construct_boot_state(struct radeon_device *rdev)
1298 {
1299 struct trinity_power_info *pi = trinity_get_pi(rdev);
1300
1301 pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
1302 pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
1303 pi->boot_pl.ds_divider_index = 0;
1304 pi->boot_pl.ss_divider_index = 0;
1305 pi->boot_pl.allow_gnb_slow = 1;
1306 pi->boot_pl.force_nbp_state = 0;
1307 pi->boot_pl.display_wm = 0;
1308 pi->boot_pl.vce_wm = 0;
1309 pi->current_ps.num_levels = 1;
1310 pi->current_ps.levels[0] = pi->boot_pl;
1311 }
1312
1313 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
1314 u32 sclk, u32 min_sclk_in_sr)
1315 {
1316 struct trinity_power_info *pi = trinity_get_pi(rdev);
1317 u32 i;
1318 u32 temp;
1319 u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ?
1320 min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK;
1321
1322 if (sclk < min)
1323 return 0;
1324
1325 if (!pi->enable_sclk_ds)
1326 return 0;
1327
1328 for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) {
1329 temp = sclk / sumo_get_sleep_divider_from_id(i);
1330 if (temp >= min || i == 0)
1331 break;
1332 }
1333
1334 return (u8)i;
1335 }
1336
1337 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev,
1338 u32 lower_limit)
1339 {
1340 struct trinity_power_info *pi = trinity_get_pi(rdev);
1341 u32 i;
1342
1343 for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
1344 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
1345 return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
1346 }
1347
1348 if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries)
1349 DRM_ERROR("engine clock out of range!");
1350
1351 return 0;
1352 }
1353
1354 static void trinity_patch_thermal_state(struct radeon_device *rdev,
1355 struct trinity_ps *ps,
1356 struct trinity_ps *current_ps)
1357 {
1358 struct trinity_power_info *pi = trinity_get_pi(rdev);
1359 u32 sclk_in_sr = pi->sys_info.min_sclk;
1360 u32 current_vddc;
1361 u32 current_sclk;
1362 u32 current_index = 0;
1363
1364 if (current_ps) {
1365 current_vddc = current_ps->levels[current_index].vddc_index;
1366 current_sclk = current_ps->levels[current_index].sclk;
1367 } else {
1368 current_vddc = pi->boot_pl.vddc_index;
1369 current_sclk = pi->boot_pl.sclk;
1370 }
1371
1372 ps->levels[0].vddc_index = current_vddc;
1373
1374 if (ps->levels[0].sclk > current_sclk)
1375 ps->levels[0].sclk = current_sclk;
1376
1377 ps->levels[0].ds_divider_index =
1378 trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
1379 ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index;
1380 ps->levels[0].allow_gnb_slow = 1;
1381 ps->levels[0].force_nbp_state = 0;
1382 ps->levels[0].display_wm = 0;
1383 ps->levels[0].vce_wm =
1384 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1385 }
1386
1387 static u8 trinity_calculate_display_wm(struct radeon_device *rdev,
1388 struct trinity_ps *ps, u32 index)
1389 {
1390 if (ps == NULL || ps->num_levels <= 1)
1391 return 0;
1392 else if (ps->num_levels == 2) {
1393 if (index == 0)
1394 return 0;
1395 else
1396 return 1;
1397 } else {
1398 if (index == 0)
1399 return 0;
1400 else if (ps->levels[index].sclk < 30000)
1401 return 0;
1402 else
1403 return 1;
1404 }
1405 }
1406
1407 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev,
1408 struct radeon_ps *rps)
1409 {
1410 struct trinity_power_info *pi = trinity_get_pi(rdev);
1411 u32 i = 0;
1412
1413 for (i = 0; i < 4; i++) {
1414 if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) &&
1415 (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk))
1416 break;
1417 }
1418
1419 if (i >= 4) {
1420 DRM_ERROR("UVD clock index not found!\n");
1421 i = 3;
1422 }
1423 return i;
1424 }
1425
1426 static void trinity_adjust_uvd_state(struct radeon_device *rdev,
1427 struct radeon_ps *rps)
1428 {
1429 struct trinity_ps *ps = trinity_get_ps(rps);
1430 struct trinity_power_info *pi = trinity_get_pi(rdev);
1431 u32 high_index = 0;
1432 u32 low_index = 0;
1433
1434 if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) {
1435 high_index = trinity_get_uvd_clock_index(rdev, rps);
1436
1437 switch(high_index) {
1438 case 3:
1439 case 2:
1440 low_index = 1;
1441 break;
1442 case 1:
1443 case 0:
1444 default:
1445 low_index = 0;
1446 break;
1447 }
1448
1449 ps->vclk_low_divider =
1450 pi->sys_info.uvd_clock_table_entries[high_index].vclk_did;
1451 ps->dclk_low_divider =
1452 pi->sys_info.uvd_clock_table_entries[high_index].dclk_did;
1453 ps->vclk_high_divider =
1454 pi->sys_info.uvd_clock_table_entries[low_index].vclk_did;
1455 ps->dclk_high_divider =
1456 pi->sys_info.uvd_clock_table_entries[low_index].dclk_did;
1457 }
1458 }
1459
1460 static int trinity_get_vce_clock_voltage(struct radeon_device *rdev,
1461 u32 evclk, u32 ecclk, u16 *voltage)
1462 {
1463 u32 i;
1464 int ret = -EINVAL;
1465 struct radeon_vce_clock_voltage_dependency_table *table =
1466 &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
1467
1468 if (((evclk == 0) && (ecclk == 0)) ||
1469 (table && (table->count == 0))) {
1470 *voltage = 0;
1471 return 0;
1472 }
1473
1474 for (i = 0; i < table->count; i++) {
1475 if ((evclk <= table->entries[i].evclk) &&
1476 (ecclk <= table->entries[i].ecclk)) {
1477 *voltage = table->entries[i].v;
1478 ret = 0;
1479 break;
1480 }
1481 }
1482
1483
1484 if (ret)
1485 *voltage = table->entries[table->count - 1].v;
1486
1487 return ret;
1488 }
1489
1490 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev,
1491 struct radeon_ps *new_rps,
1492 struct radeon_ps *old_rps)
1493 {
1494 struct trinity_ps *ps = trinity_get_ps(new_rps);
1495 struct trinity_ps *current_ps = trinity_get_ps(old_rps);
1496 struct trinity_power_info *pi = trinity_get_pi(rdev);
1497 u32 min_voltage = 0;
1498 u32 min_sclk = pi->sys_info.min_sclk;
1499 u32 sclk_in_sr = pi->sys_info.min_sclk;
1500 u32 i;
1501 u16 min_vce_voltage;
1502 bool force_high;
1503 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1504
1505 if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1506 return trinity_patch_thermal_state(rdev, ps, current_ps);
1507
1508 trinity_adjust_uvd_state(rdev, new_rps);
1509
1510 if (new_rps->vce_active) {
1511 new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
1512 new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
1513 } else {
1514 new_rps->evclk = 0;
1515 new_rps->ecclk = 0;
1516 }
1517
1518 for (i = 0; i < ps->num_levels; i++) {
1519 if (ps->levels[i].vddc_index < min_voltage)
1520 ps->levels[i].vddc_index = min_voltage;
1521
1522 if (ps->levels[i].sclk < min_sclk)
1523 ps->levels[i].sclk =
1524 trinity_get_valid_engine_clock(rdev, min_sclk);
1525
1526
1527 if (new_rps->vce_active) {
1528
1529 if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
1530 ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
1531
1532 trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
1533 if (ps->levels[i].vddc_index < min_vce_voltage)
1534 ps->levels[i].vddc_index = min_vce_voltage;
1535 }
1536
1537 ps->levels[i].ds_divider_index =
1538 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1539
1540 ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1541
1542 ps->levels[i].allow_gnb_slow = 1;
1543 ps->levels[i].force_nbp_state = 0;
1544 ps->levels[i].display_wm =
1545 trinity_calculate_display_wm(rdev, ps, i);
1546 ps->levels[i].vce_wm =
1547 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1548 }
1549
1550 if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1551 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1552 ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1553
1554 if (pi->sys_info.nb_dpm_enable) {
1555 ps->Dpm0PgNbPsLo = 0x1;
1556 ps->Dpm0PgNbPsHi = 0x0;
1557 ps->DpmXNbPsLo = 0x2;
1558 ps->DpmXNbPsHi = 0x1;
1559
1560 if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1561 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1562 force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1563 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1564 (pi->sys_info.uma_channel_number == 1)));
1565 force_high = (num_active_displays >= 3) || force_high;
1566 ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1567 ps->Dpm0PgNbPsHi = 0x1;
1568 ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1569 ps->DpmXNbPsHi = 0x2;
1570 ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1571 }
1572 }
1573 }
1574
1575 static void trinity_cleanup_asic(struct radeon_device *rdev)
1576 {
1577 sumo_take_smu_control(rdev, false);
1578 }
1579
1580 #if 0
1581 static void trinity_pre_display_configuration_change(struct radeon_device *rdev)
1582 {
1583 struct trinity_power_info *pi = trinity_get_pi(rdev);
1584
1585 if (pi->voltage_drop_in_dce)
1586 trinity_dce_enable_voltage_adjustment(rdev, false);
1587 }
1588 #endif
1589
1590 static void trinity_add_dccac_value(struct radeon_device *rdev)
1591 {
1592 u32 gpu_cac_avrg_cntl_window_size;
1593 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1594 u64 disp_clk = rdev->clock.default_dispclk / 100;
1595 u32 dc_cac_value;
1596
1597 gpu_cac_avrg_cntl_window_size =
1598 (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT;
1599
1600 dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >>
1601 (32 - gpu_cac_avrg_cntl_window_size));
1602
1603 WREG32_SMC(DC_CAC_VALUE, dc_cac_value);
1604 }
1605
1606 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev)
1607 {
1608 struct trinity_power_info *pi = trinity_get_pi(rdev);
1609
1610 if (pi->voltage_drop_in_dce)
1611 trinity_dce_enable_voltage_adjustment(rdev, true);
1612 trinity_add_dccac_value(rdev);
1613 }
1614
1615 union power_info {
1616 struct _ATOM_POWERPLAY_INFO info;
1617 struct _ATOM_POWERPLAY_INFO_V2 info_2;
1618 struct _ATOM_POWERPLAY_INFO_V3 info_3;
1619 struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
1620 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
1621 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
1622 };
1623
1624 union pplib_clock_info {
1625 struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
1626 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
1627 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
1628 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
1629 };
1630
1631 union pplib_power_state {
1632 struct _ATOM_PPLIB_STATE v1;
1633 struct _ATOM_PPLIB_STATE_V2 v2;
1634 };
1635
1636 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev,
1637 struct radeon_ps *rps,
1638 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
1639 u8 table_rev)
1640 {
1641 struct trinity_ps *ps = trinity_get_ps(rps);
1642
1643 rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
1644 rps->class = le16_to_cpu(non_clock_info->usClassification);
1645 rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
1646
1647 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
1648 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
1649 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
1650 } else {
1651 rps->vclk = 0;
1652 rps->dclk = 0;
1653 }
1654
1655 if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
1656 rdev->pm.dpm.boot_ps = rps;
1657 trinity_patch_boot_state(rdev, ps);
1658 }
1659 if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
1660 rdev->pm.dpm.uvd_ps = rps;
1661 }
1662
1663 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev,
1664 struct radeon_ps *rps, int index,
1665 union pplib_clock_info *clock_info)
1666 {
1667 struct trinity_power_info *pi = trinity_get_pi(rdev);
1668 struct trinity_ps *ps = trinity_get_ps(rps);
1669 struct trinity_pl *pl = &ps->levels[index];
1670 u32 sclk;
1671
1672 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1673 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1674 pl->sclk = sclk;
1675 pl->vddc_index = clock_info->sumo.vddcIndex;
1676
1677 ps->num_levels = index + 1;
1678
1679 if (pi->enable_sclk_ds) {
1680 pl->ds_divider_index = 5;
1681 pl->ss_divider_index = 5;
1682 }
1683 }
1684
1685 static int trinity_parse_power_table(struct radeon_device *rdev)
1686 {
1687 struct radeon_mode_info *mode_info = &rdev->mode_info;
1688 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
1689 union pplib_power_state *power_state;
1690 int i, j, k, non_clock_array_index, clock_array_index;
1691 union pplib_clock_info *clock_info;
1692 struct _StateArray *state_array;
1693 struct _ClockInfoArray *clock_info_array;
1694 struct _NonClockInfoArray *non_clock_info_array;
1695 union power_info *power_info;
1696 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
1697 u16 data_offset;
1698 u8 frev, crev;
1699 u8 *power_state_offset;
1700 struct sumo_ps *ps;
1701
1702 if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
1703 &frev, &crev, &data_offset))
1704 return -EINVAL;
1705 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
1706
1707 state_array = (struct _StateArray *)
1708 (mode_info->atom_context->bios + data_offset +
1709 le16_to_cpu(power_info->pplib.usStateArrayOffset));
1710 clock_info_array = (struct _ClockInfoArray *)
1711 (mode_info->atom_context->bios + data_offset +
1712 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
1713 non_clock_info_array = (struct _NonClockInfoArray *)
1714 (mode_info->atom_context->bios + data_offset +
1715 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
1716
1717 rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
1718 sizeof(struct radeon_ps),
1719 GFP_KERNEL);
1720 if (!rdev->pm.dpm.ps)
1721 return -ENOMEM;
1722 power_state_offset = (u8 *)state_array->states;
1723 for (i = 0; i < state_array->ucNumEntries; i++) {
1724 u8 *idx;
1725 power_state = (union pplib_power_state *)power_state_offset;
1726 non_clock_array_index = power_state->v2.nonClockInfoIndex;
1727 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
1728 &non_clock_info_array->nonClockInfo[non_clock_array_index];
1729 if (!rdev->pm.power_state[i].clock_info)
1730 return -EINVAL;
1731 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
1732 if (ps == NULL) {
1733 kfree(rdev->pm.dpm.ps);
1734 return -ENOMEM;
1735 }
1736 rdev->pm.dpm.ps[i].ps_priv = ps;
1737 k = 0;
1738 idx = (u8 *)&power_state->v2.clockInfoIndex[0];
1739 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
1740 clock_array_index = idx[j];
1741 if (clock_array_index >= clock_info_array->ucNumEntries)
1742 continue;
1743 if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
1744 break;
1745 clock_info = (union pplib_clock_info *)
1746 ((u8 *)&clock_info_array->clockInfo[0] +
1747 (clock_array_index * clock_info_array->ucEntrySize));
1748 trinity_parse_pplib_clock_info(rdev,
1749 &rdev->pm.dpm.ps[i], k,
1750 clock_info);
1751 k++;
1752 }
1753 trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
1754 non_clock_info,
1755 non_clock_info_array->ucEntrySize);
1756 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
1757 }
1758 rdev->pm.dpm.num_ps = state_array->ucNumEntries;
1759
1760
1761 for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
1762 u32 sclk;
1763 clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
1764 clock_info = (union pplib_clock_info *)
1765 &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
1766 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
1767 sclk |= clock_info->sumo.ucEngineClockHigh << 16;
1768 rdev->pm.dpm.vce_states[i].sclk = sclk;
1769 rdev->pm.dpm.vce_states[i].mclk = 0;
1770 }
1771
1772 return 0;
1773 }
1774
1775 union igp_info {
1776 struct _ATOM_INTEGRATED_SYSTEM_INFO info;
1777 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
1778 struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
1779 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
1780 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7;
1781 };
1782
1783 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did)
1784 {
1785 struct trinity_power_info *pi = trinity_get_pi(rdev);
1786 u32 divider;
1787
1788 if (did >= 8 && did <= 0x3f)
1789 divider = did * 25;
1790 else if (did > 0x3f && did <= 0x5f)
1791 divider = (did - 64) * 50 + 1600;
1792 else if (did > 0x5f && did <= 0x7e)
1793 divider = (did - 96) * 100 + 3200;
1794 else if (did == 0x7f)
1795 divider = 128 * 100;
1796 else
1797 return 10000;
1798
1799 return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider;
1800 }
1801
1802 static int trinity_parse_sys_info_table(struct radeon_device *rdev)
1803 {
1804 struct trinity_power_info *pi = trinity_get_pi(rdev);
1805 struct radeon_mode_info *mode_info = &rdev->mode_info;
1806 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
1807 union igp_info *igp_info;
1808 u8 frev, crev;
1809 u16 data_offset;
1810 int i;
1811
1812 if (atom_parse_data_header(mode_info->atom_context, index, NULL,
1813 &frev, &crev, &data_offset)) {
1814 igp_info = (union igp_info *)(mode_info->atom_context->bios +
1815 data_offset);
1816
1817 if (crev != 7) {
1818 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
1819 return -EINVAL;
1820 }
1821 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock);
1822 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock);
1823 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock);
1824 pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq);
1825 pi->sys_info.bootup_nb_voltage_index =
1826 le16_to_cpu(igp_info->info_7.usBootUpNBVoltage);
1827 if (igp_info->info_7.ucHtcTmpLmt == 0)
1828 pi->sys_info.htc_tmp_lmt = 203;
1829 else
1830 pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt;
1831 if (igp_info->info_7.ucHtcHystLmt == 0)
1832 pi->sys_info.htc_hyst_lmt = 5;
1833 else
1834 pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt;
1835 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
1836 DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
1837 }
1838
1839 if (pi->enable_nbps_policy)
1840 pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable;
1841 else
1842 pi->sys_info.nb_dpm_enable = 0;
1843
1844 for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) {
1845 pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]);
1846 pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]);
1847 }
1848
1849 pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage);
1850 pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage);
1851 pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage);
1852 pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage);
1853
1854 if (!pi->sys_info.nb_dpm_enable) {
1855 for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) {
1856 pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0];
1857 pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0];
1858 pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0];
1859 }
1860 }
1861
1862 pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber;
1863
1864 sumo_construct_sclk_voltage_mapping_table(rdev,
1865 &pi->sys_info.sclk_voltage_mapping_table,
1866 igp_info->info_7.sAvail_SCLK);
1867 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
1868 igp_info->info_7.sAvail_SCLK);
1869
1870 pi->sys_info.uvd_clock_table_entries[0].vclk_did =
1871 igp_info->info_7.ucDPMState0VclkFid;
1872 pi->sys_info.uvd_clock_table_entries[1].vclk_did =
1873 igp_info->info_7.ucDPMState1VclkFid;
1874 pi->sys_info.uvd_clock_table_entries[2].vclk_did =
1875 igp_info->info_7.ucDPMState2VclkFid;
1876 pi->sys_info.uvd_clock_table_entries[3].vclk_did =
1877 igp_info->info_7.ucDPMState3VclkFid;
1878
1879 pi->sys_info.uvd_clock_table_entries[0].dclk_did =
1880 igp_info->info_7.ucDPMState0DclkFid;
1881 pi->sys_info.uvd_clock_table_entries[1].dclk_did =
1882 igp_info->info_7.ucDPMState1DclkFid;
1883 pi->sys_info.uvd_clock_table_entries[2].dclk_did =
1884 igp_info->info_7.ucDPMState2DclkFid;
1885 pi->sys_info.uvd_clock_table_entries[3].dclk_did =
1886 igp_info->info_7.ucDPMState3DclkFid;
1887
1888 for (i = 0; i < 4; i++) {
1889 pi->sys_info.uvd_clock_table_entries[i].vclk =
1890 trinity_convert_did_to_freq(rdev,
1891 pi->sys_info.uvd_clock_table_entries[i].vclk_did);
1892 pi->sys_info.uvd_clock_table_entries[i].dclk =
1893 trinity_convert_did_to_freq(rdev,
1894 pi->sys_info.uvd_clock_table_entries[i].dclk_did);
1895 }
1896
1897
1898
1899 }
1900 return 0;
1901 }
1902
1903 int trinity_dpm_init(struct radeon_device *rdev)
1904 {
1905 struct trinity_power_info *pi;
1906 int ret, i;
1907
1908 pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL);
1909 if (pi == NULL)
1910 return -ENOMEM;
1911 rdev->pm.dpm.priv = pi;
1912
1913 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++)
1914 pi->at[i] = TRINITY_AT_DFLT;
1915
1916 if (radeon_bapm == -1) {
1917
1918
1919
1920
1921
1922
1923 if (rdev->pdev->subsystem_vendor == 0x1462)
1924 pi->enable_bapm = true;
1925 else
1926 pi->enable_bapm = false;
1927 } else if (radeon_bapm == 0) {
1928 pi->enable_bapm = false;
1929 } else {
1930 pi->enable_bapm = true;
1931 }
1932 pi->enable_nbps_policy = true;
1933 pi->enable_sclk_ds = true;
1934 pi->enable_gfx_power_gating = true;
1935 pi->enable_gfx_clock_gating = true;
1936 pi->enable_mg_clock_gating = false;
1937 pi->enable_gfx_dynamic_mgpg = false;
1938 pi->override_dynamic_mgpg = false;
1939 pi->enable_auto_thermal_throttling = true;
1940 pi->voltage_drop_in_dce = false;
1941 pi->uvd_dpm = true;
1942
1943 ret = trinity_parse_sys_info_table(rdev);
1944 if (ret)
1945 return ret;
1946
1947 trinity_construct_boot_state(rdev);
1948
1949 ret = r600_get_platform_caps(rdev);
1950 if (ret)
1951 return ret;
1952
1953 ret = r600_parse_extended_power_table(rdev);
1954 if (ret)
1955 return ret;
1956
1957 ret = trinity_parse_power_table(rdev);
1958 if (ret)
1959 return ret;
1960
1961 pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
1962 pi->enable_dpm = true;
1963
1964 return 0;
1965 }
1966
1967 void trinity_dpm_print_power_state(struct radeon_device *rdev,
1968 struct radeon_ps *rps)
1969 {
1970 int i;
1971 struct trinity_ps *ps = trinity_get_ps(rps);
1972
1973 r600_dpm_print_class_info(rps->class, rps->class2);
1974 r600_dpm_print_cap_info(rps->caps);
1975 printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
1976 for (i = 0; i < ps->num_levels; i++) {
1977 struct trinity_pl *pl = &ps->levels[i];
1978 printk("\t\tpower level %d sclk: %u vddc: %u\n",
1979 i, pl->sclk,
1980 trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
1981 }
1982 r600_dpm_print_ps_status(rdev, rps);
1983 }
1984
1985 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
1986 struct seq_file *m)
1987 {
1988 struct trinity_power_info *pi = trinity_get_pi(rdev);
1989 struct radeon_ps *rps = &pi->current_rps;
1990 struct trinity_ps *ps = trinity_get_ps(rps);
1991 struct trinity_pl *pl;
1992 u32 current_index =
1993 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
1994 CURRENT_STATE_SHIFT;
1995
1996 if (current_index >= ps->num_levels) {
1997 seq_printf(m, "invalid dpm profile %d\n", current_index);
1998 } else {
1999 pl = &ps->levels[current_index];
2000 seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
2001 seq_printf(m, "power level %d sclk: %u vddc: %u\n",
2002 current_index, pl->sclk,
2003 trinity_convert_voltage_index_to_value(rdev, pl->vddc_index));
2004 }
2005 }
2006
2007 u32 trinity_dpm_get_current_sclk(struct radeon_device *rdev)
2008 {
2009 struct trinity_power_info *pi = trinity_get_pi(rdev);
2010 struct radeon_ps *rps = &pi->current_rps;
2011 struct trinity_ps *ps = trinity_get_ps(rps);
2012 struct trinity_pl *pl;
2013 u32 current_index =
2014 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >>
2015 CURRENT_STATE_SHIFT;
2016
2017 if (current_index >= ps->num_levels) {
2018 return 0;
2019 } else {
2020 pl = &ps->levels[current_index];
2021 return pl->sclk;
2022 }
2023 }
2024
2025 u32 trinity_dpm_get_current_mclk(struct radeon_device *rdev)
2026 {
2027 struct trinity_power_info *pi = trinity_get_pi(rdev);
2028
2029 return pi->sys_info.bootup_uma_clk;
2030 }
2031
2032 void trinity_dpm_fini(struct radeon_device *rdev)
2033 {
2034 int i;
2035
2036 trinity_cleanup_asic(rdev);
2037
2038 for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
2039 kfree(rdev->pm.dpm.ps[i].ps_priv);
2040 }
2041 kfree(rdev->pm.dpm.ps);
2042 kfree(rdev->pm.dpm.priv);
2043 r600_free_extended_power_table(rdev);
2044 }
2045
2046 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low)
2047 {
2048 struct trinity_power_info *pi = trinity_get_pi(rdev);
2049 struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps);
2050
2051 if (low)
2052 return requested_state->levels[0].sclk;
2053 else
2054 return requested_state->levels[requested_state->num_levels - 1].sclk;
2055 }
2056
2057 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low)
2058 {
2059 struct trinity_power_info *pi = trinity_get_pi(rdev);
2060
2061 return pi->sys_info.bootup_uma_clk;
2062 }