Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
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     /* Register, Value, Mask */
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     /* Register, Value, Mask */
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     /* Register, Value, Mask */
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     /* Register, Value */
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, &dividers);
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     /* XXX double check hw_rev */
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, &dividers);
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, &dividers);
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         /* turn the clocks on when encoding, off otherwise */
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         /* not supported by the hw */
1170         return -EINVAL;
1171     } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
1172         ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1);
1173         if (ret)
1174             return ret;
1175     } else {
1176         for (i = 0; i < ps->num_levels; i++) {
1177             ret = trinity_dpm_n_levels_disabled(rdev, 0);
1178             if (ret)
1179                 return ret;
1180         }
1181     }
1182 
1183     rdev->pm.dpm.forced_level = level;
1184 
1185     return 0;
1186 }
1187 
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     /* if no match return the highest voltage */
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; /* XXX check against disp reqs */
1499     u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
1500     u32 i;
1501     u16 min_vce_voltage;
1502     bool force_high;
1503     u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count;
1504 
1505     if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
1506         return trinity_patch_thermal_state(rdev, ps, current_ps);
1507 
1508     trinity_adjust_uvd_state(rdev, new_rps);
1509 
1510     if (new_rps->vce_active) {
1511         new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
1512         new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
1513     } else {
1514         new_rps->evclk = 0;
1515         new_rps->ecclk = 0;
1516     }
1517 
1518     for (i = 0; i < ps->num_levels; i++) {
1519         if (ps->levels[i].vddc_index < min_voltage)
1520             ps->levels[i].vddc_index = min_voltage;
1521 
1522         if (ps->levels[i].sclk < min_sclk)
1523             ps->levels[i].sclk =
1524                 trinity_get_valid_engine_clock(rdev, min_sclk);
1525 
1526         /* patch in vce limits */
1527         if (new_rps->vce_active) {
1528             /* sclk */
1529             if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
1530                 ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
1531             /* vddc */
1532             trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage);
1533             if (ps->levels[i].vddc_index < min_vce_voltage)
1534                 ps->levels[i].vddc_index = min_vce_voltage;
1535         }
1536 
1537         ps->levels[i].ds_divider_index =
1538             sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
1539 
1540         ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index;
1541 
1542         ps->levels[i].allow_gnb_slow = 1;
1543         ps->levels[i].force_nbp_state = 0;
1544         ps->levels[i].display_wm =
1545             trinity_calculate_display_wm(rdev, ps, i);
1546         ps->levels[i].vce_wm =
1547             trinity_calculate_vce_wm(rdev, ps->levels[0].sclk);
1548     }
1549 
1550     if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1551         ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY))
1552         ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE;
1553 
1554     if (pi->sys_info.nb_dpm_enable) {
1555         ps->Dpm0PgNbPsLo = 0x1;
1556         ps->Dpm0PgNbPsHi = 0x0;
1557         ps->DpmXNbPsLo = 0x2;
1558         ps->DpmXNbPsHi = 0x1;
1559 
1560         if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) ||
1561             ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) {
1562             force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) ||
1563                       ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) &&
1564                        (pi->sys_info.uma_channel_number == 1)));
1565             force_high = (num_active_displays >= 3) || force_high;
1566             ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3;
1567             ps->Dpm0PgNbPsHi = 0x1;
1568             ps->DpmXNbPsLo = force_high ? 0x2 : 0x3;
1569             ps->DpmXNbPsHi = 0x2;
1570             ps->levels[ps->num_levels - 1].allow_gnb_slow = 0;
1571         }
1572     }
1573 }
1574 
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     /* fill in the vce power states */
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         /* There are stability issues reported on with
1918          * bapm enabled when switching between AC and battery
1919          * power.  At the same time, some MSI boards hang
1920          * if it's not enabled and dpm is enabled.  Just enable
1921          * it for MSI boards right now.
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; /* need to restructure dpm/modeset interaction */
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 }