LCOV - code coverage report
Current view: top level - dev/pci/drm/radeon - sumo_dpm.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1122 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 98 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  */
      23             : 
      24             : #include <dev/pci/drm/drmP.h>
      25             : #include "radeon.h"
      26             : #include "radeon_asic.h"
      27             : #include "sumod.h"
      28             : #include "r600_dpm.h"
      29             : #include "cypress_dpm.h"
      30             : #include "sumo_dpm.h"
      31             : 
      32             : #define SUMO_MAX_DEEPSLEEP_DIVIDER_ID 5
      33             : #define SUMO_MINIMUM_ENGINE_CLOCK 800
      34             : #define BOOST_DPM_LEVEL 7
      35             : 
      36             : static const u32 sumo_utc[SUMO_PM_NUMBER_OF_TC] =
      37             : {
      38             :         SUMO_UTC_DFLT_00,
      39             :         SUMO_UTC_DFLT_01,
      40             :         SUMO_UTC_DFLT_02,
      41             :         SUMO_UTC_DFLT_03,
      42             :         SUMO_UTC_DFLT_04,
      43             :         SUMO_UTC_DFLT_05,
      44             :         SUMO_UTC_DFLT_06,
      45             :         SUMO_UTC_DFLT_07,
      46             :         SUMO_UTC_DFLT_08,
      47             :         SUMO_UTC_DFLT_09,
      48             :         SUMO_UTC_DFLT_10,
      49             :         SUMO_UTC_DFLT_11,
      50             :         SUMO_UTC_DFLT_12,
      51             :         SUMO_UTC_DFLT_13,
      52             :         SUMO_UTC_DFLT_14,
      53             : };
      54             : 
      55             : static const u32 sumo_dtc[SUMO_PM_NUMBER_OF_TC] =
      56             : {
      57             :         SUMO_DTC_DFLT_00,
      58             :         SUMO_DTC_DFLT_01,
      59             :         SUMO_DTC_DFLT_02,
      60             :         SUMO_DTC_DFLT_03,
      61             :         SUMO_DTC_DFLT_04,
      62             :         SUMO_DTC_DFLT_05,
      63             :         SUMO_DTC_DFLT_06,
      64             :         SUMO_DTC_DFLT_07,
      65             :         SUMO_DTC_DFLT_08,
      66             :         SUMO_DTC_DFLT_09,
      67             :         SUMO_DTC_DFLT_10,
      68             :         SUMO_DTC_DFLT_11,
      69             :         SUMO_DTC_DFLT_12,
      70             :         SUMO_DTC_DFLT_13,
      71             :         SUMO_DTC_DFLT_14,
      72             : };
      73             : 
      74           0 : static struct sumo_ps *sumo_get_ps(struct radeon_ps *rps)
      75             : {
      76           0 :         struct sumo_ps *ps = rps->ps_priv;
      77             : 
      78           0 :         return ps;
      79             : }
      80             : 
      81           0 : struct sumo_power_info *sumo_get_pi(struct radeon_device *rdev)
      82             : {
      83           0 :         struct sumo_power_info *pi = rdev->pm.dpm.priv;
      84             : 
      85           0 :         return pi;
      86             : }
      87             : 
      88           0 : static void sumo_gfx_clockgating_enable(struct radeon_device *rdev, bool enable)
      89             : {
      90           0 :         if (enable)
      91           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
      92             :         else {
      93           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
      94           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
      95           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
      96           0 :                 RREG32(GB_ADDR_CONFIG);
      97             :         }
      98           0 : }
      99             : 
     100             : #define CGCG_CGTT_LOCAL0_MASK 0xE5BFFFFF
     101             : #define CGCG_CGTT_LOCAL1_MASK 0xEFFF07FF
     102             : 
     103           0 : static void sumo_mg_clockgating_enable(struct radeon_device *rdev, bool enable)
     104             : {
     105             :         u32 local0;
     106             :         u32 local1;
     107             : 
     108           0 :         local0 = RREG32(CG_CGTT_LOCAL_0);
     109           0 :         local1 = RREG32(CG_CGTT_LOCAL_1);
     110             : 
     111           0 :         if (enable) {
     112           0 :                 WREG32(CG_CGTT_LOCAL_0, (0 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
     113           0 :                 WREG32(CG_CGTT_LOCAL_1, (0 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
     114           0 :         } else {
     115           0 :                 WREG32(CG_CGTT_LOCAL_0, (0xFFFFFFFF & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) );
     116           0 :                 WREG32(CG_CGTT_LOCAL_1, (0xFFFFCFFF & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) );
     117             :         }
     118           0 : }
     119             : 
     120           0 : static void sumo_program_git(struct radeon_device *rdev)
     121             : {
     122           0 :         u32 p, u;
     123           0 :         u32 xclk = radeon_get_xclk(rdev);
     124             : 
     125           0 :         r600_calculate_u_and_p(SUMO_GICST_DFLT,
     126             :                                xclk, 16, &p, &u);
     127             : 
     128           0 :         WREG32_P(CG_GIT, CG_GICST(p), ~CG_GICST_MASK);
     129           0 : }
     130             : 
     131           0 : static void sumo_program_grsd(struct radeon_device *rdev)
     132             : {
     133           0 :         u32 p, u;
     134           0 :         u32 xclk = radeon_get_xclk(rdev);
     135             :         u32 grs = 256 * 25 / 100;
     136             : 
     137           0 :         r600_calculate_u_and_p(1, xclk, 14, &p, &u);
     138             : 
     139           0 :         WREG32(CG_GCOOR, PHC(grs) | SDC(p) | SU(u));
     140           0 : }
     141             : 
     142           0 : void sumo_gfx_clockgating_initialize(struct radeon_device *rdev)
     143             : {
     144           0 :         sumo_program_git(rdev);
     145           0 :         sumo_program_grsd(rdev);
     146           0 : }
     147             : 
     148           0 : static void sumo_gfx_powergating_initialize(struct radeon_device *rdev)
     149             : {
     150             :         u32 rcu_pwr_gating_cntl;
     151           0 :         u32 p, u;
     152             :         u32 p_c, p_p, d_p;
     153             :         u32 r_t, i_t;
     154           0 :         u32 xclk = radeon_get_xclk(rdev);
     155             : 
     156           0 :         if (rdev->family == CHIP_PALM) {
     157             :                 p_c = 4;
     158             :                 d_p = 10;
     159             :                 r_t = 10;
     160             :                 i_t = 4;
     161             :                 p_p = 50 + 1000/200 + 6 * 32;
     162           0 :         } else {
     163             :                 p_c = 16;
     164             :                 d_p = 50;
     165             :                 r_t = 50;
     166             :                 i_t  = 50;
     167             :                 p_p = 113;
     168             :         }
     169             : 
     170           0 :         WREG32(CG_SCRATCH2, 0x01B60A17);
     171             : 
     172           0 :         r600_calculate_u_and_p(SUMO_GFXPOWERGATINGT_DFLT,
     173             :                                xclk, 16, &p, &u);
     174             : 
     175           0 :         WREG32_P(CG_PWR_GATING_CNTL, PGP(p) | PGU(u),
     176             :                  ~(PGP_MASK | PGU_MASK));
     177             : 
     178           0 :         r600_calculate_u_and_p(SUMO_VOLTAGEDROPT_DFLT,
     179             :                                xclk, 16, &p, &u);
     180             : 
     181           0 :         WREG32_P(CG_CG_VOLTAGE_CNTL, PGP(p) | PGU(u),
     182             :                  ~(PGP_MASK | PGU_MASK));
     183             : 
     184           0 :         if (rdev->family == CHIP_PALM) {
     185           0 :                 WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x10103210);
     186           0 :                 WREG32_RCU(RCU_PWR_GATING_SEQ1, 0x10101010);
     187           0 :         } else {
     188           0 :                 WREG32_RCU(RCU_PWR_GATING_SEQ0, 0x76543210);
     189           0 :                 WREG32_RCU(RCU_PWR_GATING_SEQ1, 0xFEDCBA98);
     190             :         }
     191             : 
     192           0 :         rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL);
     193           0 :         rcu_pwr_gating_cntl &=
     194             :                 ~(RSVD_MASK | PCV_MASK | PGS_MASK);
     195           0 :         rcu_pwr_gating_cntl |= PCV(p_c) | PGS(1) | PWR_GATING_EN;
     196           0 :         if (rdev->family == CHIP_PALM) {
     197           0 :                 rcu_pwr_gating_cntl &= ~PCP_MASK;
     198           0 :                 rcu_pwr_gating_cntl |= PCP(0x77);
     199           0 :         }
     200           0 :         WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl);
     201             : 
     202           0 :         rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2);
     203             :         rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK);
     204           0 :         rcu_pwr_gating_cntl |= MPPU(p_p) | MPPD(50);
     205           0 :         WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl);
     206             : 
     207           0 :         rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3);
     208             :         rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK);
     209           0 :         rcu_pwr_gating_cntl |= DPPU(d_p) | DPPD(50);
     210           0 :         WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl);
     211             : 
     212           0 :         rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_4);
     213             :         rcu_pwr_gating_cntl &= ~(RT_MASK | IT_MASK);
     214           0 :         rcu_pwr_gating_cntl |= RT(r_t) | IT(i_t);
     215           0 :         WREG32_RCU(RCU_PWR_GATING_CNTL_4, rcu_pwr_gating_cntl);
     216             : 
     217           0 :         if (rdev->family == CHIP_PALM)
     218           0 :                 WREG32_RCU(RCU_PWR_GATING_CNTL_5, 0xA02);
     219             : 
     220           0 :         sumo_smu_pg_init(rdev);
     221             : 
     222           0 :         rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL);
     223           0 :         rcu_pwr_gating_cntl &=
     224             :                 ~(RSVD_MASK | PCV_MASK | PGS_MASK);
     225           0 :         rcu_pwr_gating_cntl |= PCV(p_c) | PGS(4) | PWR_GATING_EN;
     226           0 :         if (rdev->family == CHIP_PALM) {
     227           0 :                 rcu_pwr_gating_cntl &= ~PCP_MASK;
     228           0 :                 rcu_pwr_gating_cntl |= PCP(0x77);
     229           0 :         }
     230           0 :         WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl);
     231             : 
     232           0 :         if (rdev->family == CHIP_PALM) {
     233           0 :                 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2);
     234             :                 rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK);
     235             :                 rcu_pwr_gating_cntl |= MPPU(113) | MPPD(50);
     236           0 :                 WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl);
     237             : 
     238           0 :                 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3);
     239             :                 rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK);
     240             :                 rcu_pwr_gating_cntl |= DPPU(16) | DPPD(50);
     241           0 :                 WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl);
     242           0 :         }
     243             : 
     244           0 :         sumo_smu_pg_init(rdev);
     245             : 
     246           0 :         rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL);
     247           0 :         rcu_pwr_gating_cntl &=
     248             :                 ~(RSVD_MASK | PCV_MASK | PGS_MASK);
     249           0 :         rcu_pwr_gating_cntl |= PGS(5) | PWR_GATING_EN;
     250             : 
     251           0 :         if (rdev->family == CHIP_PALM) {
     252           0 :                 rcu_pwr_gating_cntl |= PCV(4);
     253           0 :                 rcu_pwr_gating_cntl &= ~PCP_MASK;
     254           0 :                 rcu_pwr_gating_cntl |= PCP(0x77);
     255           0 :         } else
     256           0 :                 rcu_pwr_gating_cntl |= PCV(11);
     257           0 :         WREG32_RCU(RCU_PWR_GATING_CNTL, rcu_pwr_gating_cntl);
     258             : 
     259           0 :         if (rdev->family == CHIP_PALM) {
     260           0 :                 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_2);
     261             :                 rcu_pwr_gating_cntl &= ~(MPPU_MASK | MPPD_MASK);
     262             :                 rcu_pwr_gating_cntl |= MPPU(113) | MPPD(50);
     263           0 :                 WREG32_RCU(RCU_PWR_GATING_CNTL_2, rcu_pwr_gating_cntl);
     264             : 
     265           0 :                 rcu_pwr_gating_cntl = RREG32_RCU(RCU_PWR_GATING_CNTL_3);
     266             :                 rcu_pwr_gating_cntl &= ~(DPPU_MASK | DPPD_MASK);
     267             :                 rcu_pwr_gating_cntl |= DPPU(22) | DPPD(50);
     268           0 :                 WREG32_RCU(RCU_PWR_GATING_CNTL_3, rcu_pwr_gating_cntl);
     269           0 :         }
     270             : 
     271           0 :         sumo_smu_pg_init(rdev);
     272           0 : }
     273             : 
     274           0 : static void sumo_gfx_powergating_enable(struct radeon_device *rdev, bool enable)
     275             : {
     276           0 :         if (enable)
     277           0 :                 WREG32_P(CG_PWR_GATING_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN);
     278             :         else {
     279           0 :                 WREG32_P(CG_PWR_GATING_CNTL, 0, ~DYN_PWR_DOWN_EN);
     280           0 :                 RREG32(GB_ADDR_CONFIG);
     281             :         }
     282           0 : }
     283             : 
     284           0 : static int sumo_enable_clock_power_gating(struct radeon_device *rdev)
     285             : {
     286           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     287             : 
     288           0 :         if (pi->enable_gfx_clock_gating)
     289           0 :                 sumo_gfx_clockgating_initialize(rdev);
     290           0 :         if (pi->enable_gfx_power_gating)
     291           0 :                 sumo_gfx_powergating_initialize(rdev);
     292           0 :         if (pi->enable_mg_clock_gating)
     293           0 :                 sumo_mg_clockgating_enable(rdev, true);
     294           0 :         if (pi->enable_gfx_clock_gating)
     295           0 :                 sumo_gfx_clockgating_enable(rdev, true);
     296           0 :         if (pi->enable_gfx_power_gating)
     297           0 :                 sumo_gfx_powergating_enable(rdev, true);
     298             : 
     299           0 :         return 0;
     300             : }
     301             : 
     302           0 : static void sumo_disable_clock_power_gating(struct radeon_device *rdev)
     303             : {
     304           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     305             : 
     306           0 :         if (pi->enable_gfx_clock_gating)
     307           0 :                 sumo_gfx_clockgating_enable(rdev, false);
     308           0 :         if (pi->enable_gfx_power_gating)
     309           0 :                 sumo_gfx_powergating_enable(rdev, false);
     310           0 :         if (pi->enable_mg_clock_gating)
     311           0 :                 sumo_mg_clockgating_enable(rdev, false);
     312           0 : }
     313             : 
     314           0 : static void sumo_calculate_bsp(struct radeon_device *rdev,
     315             :                                u32 high_clk)
     316             : {
     317           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     318           0 :         u32 xclk = radeon_get_xclk(rdev);
     319             : 
     320           0 :         pi->pasi = 65535 * 100 / high_clk;
     321           0 :         pi->asi = 65535 * 100 / high_clk;
     322             : 
     323           0 :         r600_calculate_u_and_p(pi->asi,
     324           0 :                                xclk, 16, &pi->bsp, &pi->bsu);
     325             : 
     326           0 :         r600_calculate_u_and_p(pi->pasi,
     327           0 :                                xclk, 16, &pi->pbsp, &pi->pbsu);
     328             : 
     329           0 :         pi->dsp = BSP(pi->bsp) | BSU(pi->bsu);
     330           0 :         pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu);
     331           0 : }
     332             : 
     333           0 : static void sumo_init_bsp(struct radeon_device *rdev)
     334             : {
     335           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     336             : 
     337           0 :         WREG32(CG_BSP_0, pi->psp);
     338           0 : }
     339             : 
     340             : 
     341           0 : static void sumo_program_bsp(struct radeon_device *rdev,
     342             :                              struct radeon_ps *rps)
     343             : {
     344           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     345           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
     346             :         u32 i;
     347           0 :         u32 highest_engine_clock = ps->levels[ps->num_levels - 1].sclk;
     348             : 
     349           0 :         if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
     350           0 :                 highest_engine_clock = pi->boost_pl.sclk;
     351             : 
     352           0 :         sumo_calculate_bsp(rdev, highest_engine_clock);
     353             : 
     354           0 :         for (i = 0; i < ps->num_levels - 1; i++)
     355           0 :                 WREG32(CG_BSP_0 + (i * 4), pi->dsp);
     356             : 
     357           0 :         WREG32(CG_BSP_0 + (i * 4), pi->psp);
     358             : 
     359           0 :         if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
     360           0 :                 WREG32(CG_BSP_0 + (BOOST_DPM_LEVEL * 4), pi->psp);
     361           0 : }
     362             : 
     363           0 : static void sumo_write_at(struct radeon_device *rdev,
     364             :                           u32 index, u32 value)
     365             : {
     366           0 :         if (index == 0)
     367           0 :                 WREG32(CG_AT_0, value);
     368           0 :         else if (index == 1)
     369           0 :                 WREG32(CG_AT_1, value);
     370           0 :         else if (index == 2)
     371           0 :                 WREG32(CG_AT_2, value);
     372           0 :         else if (index == 3)
     373           0 :                 WREG32(CG_AT_3, value);
     374           0 :         else if (index == 4)
     375           0 :                 WREG32(CG_AT_4, value);
     376           0 :         else if (index == 5)
     377           0 :                 WREG32(CG_AT_5, value);
     378           0 :         else if (index == 6)
     379           0 :                 WREG32(CG_AT_6, value);
     380           0 :         else if (index == 7)
     381           0 :                 WREG32(CG_AT_7, value);
     382           0 : }
     383             : 
     384           0 : static void sumo_program_at(struct radeon_device *rdev,
     385             :                             struct radeon_ps *rps)
     386             : {
     387           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     388           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
     389             :         u32 asi;
     390             :         u32 i;
     391             :         u32 m_a;
     392             :         u32 a_t;
     393           0 :         u32 r[SUMO_MAX_HARDWARE_POWERLEVELS];
     394           0 :         u32 l[SUMO_MAX_HARDWARE_POWERLEVELS];
     395             : 
     396           0 :         r[0] = SUMO_R_DFLT0;
     397           0 :         r[1] = SUMO_R_DFLT1;
     398           0 :         r[2] = SUMO_R_DFLT2;
     399           0 :         r[3] = SUMO_R_DFLT3;
     400           0 :         r[4] = SUMO_R_DFLT4;
     401             : 
     402           0 :         l[0] = SUMO_L_DFLT0;
     403           0 :         l[1] = SUMO_L_DFLT1;
     404           0 :         l[2] = SUMO_L_DFLT2;
     405           0 :         l[3] = SUMO_L_DFLT3;
     406           0 :         l[4] = SUMO_L_DFLT4;
     407             : 
     408           0 :         for (i = 0; i < ps->num_levels; i++) {
     409           0 :                 asi = (i == ps->num_levels - 1) ? pi->pasi : pi->asi;
     410             : 
     411           0 :                 m_a = asi * ps->levels[i].sclk / 100;
     412             : 
     413           0 :                 a_t = CG_R(m_a * r[i] / 100) | CG_L(m_a * l[i] / 100);
     414             : 
     415           0 :                 sumo_write_at(rdev, i, a_t);
     416             :         }
     417             : 
     418           0 :         if (ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) {
     419           0 :                 asi = pi->pasi;
     420             : 
     421           0 :                 m_a = asi * pi->boost_pl.sclk / 100;
     422             : 
     423           0 :                 a_t = CG_R(m_a * r[ps->num_levels - 1] / 100) |
     424           0 :                         CG_L(m_a * l[ps->num_levels - 1] / 100);
     425             : 
     426           0 :                 sumo_write_at(rdev, BOOST_DPM_LEVEL, a_t);
     427           0 :         }
     428           0 : }
     429             : 
     430           0 : static void sumo_program_tp(struct radeon_device *rdev)
     431             : {
     432             :         int i;
     433             :         enum r600_td td = R600_TD_DFLT;
     434             : 
     435           0 :         for (i = 0; i < SUMO_PM_NUMBER_OF_TC; i++) {
     436           0 :                 WREG32_P(CG_FFCT_0 + (i * 4), UTC_0(sumo_utc[i]), ~UTC_0_MASK);
     437           0 :                 WREG32_P(CG_FFCT_0 + (i * 4), DTC_0(sumo_dtc[i]), ~DTC_0_MASK);
     438             :         }
     439             : 
     440           0 :         if (td == R600_TD_AUTO)
     441           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL);
     442             :         else
     443           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL);
     444             : 
     445           0 :         if (td == R600_TD_UP)
     446           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE);
     447             : 
     448           0 :         if (td == R600_TD_DOWN)
     449           0 :                 WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);
     450           0 : }
     451             : 
     452           0 : void sumo_program_vc(struct radeon_device *rdev, u32 vrc)
     453             : {
     454           0 :         WREG32(CG_FTV, vrc);
     455           0 : }
     456             : 
     457           0 : void sumo_clear_vc(struct radeon_device *rdev)
     458             : {
     459           0 :         WREG32(CG_FTV, 0);
     460           0 : }
     461             : 
     462           0 : void sumo_program_sstp(struct radeon_device *rdev)
     463             : {
     464           0 :         u32 p, u;
     465           0 :         u32 xclk = radeon_get_xclk(rdev);
     466             : 
     467           0 :         r600_calculate_u_and_p(SUMO_SST_DFLT,
     468             :                                xclk, 16, &p, &u);
     469             : 
     470           0 :         WREG32(CG_SSP, SSTU(u) | SST(p));
     471           0 : }
     472             : 
     473           0 : static void sumo_set_divider_value(struct radeon_device *rdev,
     474             :                                    u32 index, u32 divider)
     475             : {
     476           0 :         u32 reg_index = index / 4;
     477           0 :         u32 field_index = index % 4;
     478             : 
     479           0 :         if (field_index == 0)
     480           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     481             :                          SCLK_FSTATE_0_DIV(divider), ~SCLK_FSTATE_0_DIV_MASK);
     482           0 :         else if (field_index == 1)
     483           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     484             :                          SCLK_FSTATE_1_DIV(divider), ~SCLK_FSTATE_1_DIV_MASK);
     485           0 :         else if (field_index == 2)
     486           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     487             :                          SCLK_FSTATE_2_DIV(divider), ~SCLK_FSTATE_2_DIV_MASK);
     488           0 :         else if (field_index == 3)
     489           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     490             :                          SCLK_FSTATE_3_DIV(divider), ~SCLK_FSTATE_3_DIV_MASK);
     491           0 : }
     492             : 
     493           0 : static void sumo_set_ds_dividers(struct radeon_device *rdev,
     494             :                                  u32 index, u32 divider)
     495             : {
     496           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     497             : 
     498           0 :         if (pi->enable_sclk_ds) {
     499           0 :                 u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_6);
     500             : 
     501           0 :                 dpm_ctrl &= ~(0x7 << (index * 3));
     502           0 :                 dpm_ctrl |= (divider << (index * 3));
     503           0 :                 WREG32(CG_SCLK_DPM_CTRL_6, dpm_ctrl);
     504           0 :         }
     505           0 : }
     506             : 
     507           0 : static void sumo_set_ss_dividers(struct radeon_device *rdev,
     508             :                                  u32 index, u32 divider)
     509             : {
     510           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     511             : 
     512           0 :         if (pi->enable_sclk_ds) {
     513           0 :                 u32 dpm_ctrl = RREG32(CG_SCLK_DPM_CTRL_11);
     514             : 
     515           0 :                 dpm_ctrl &= ~(0x7 << (index * 3));
     516           0 :                 dpm_ctrl |= (divider << (index * 3));
     517           0 :                 WREG32(CG_SCLK_DPM_CTRL_11, dpm_ctrl);
     518           0 :         }
     519           0 : }
     520             : 
     521           0 : static void sumo_set_vid(struct radeon_device *rdev, u32 index, u32 vid)
     522             : {
     523           0 :         u32 voltage_cntl = RREG32(CG_DPM_VOLTAGE_CNTL);
     524             : 
     525           0 :         voltage_cntl &= ~(DPM_STATE0_LEVEL_MASK << (index * 2));
     526           0 :         voltage_cntl |= (vid << (DPM_STATE0_LEVEL_SHIFT + index * 2));
     527           0 :         WREG32(CG_DPM_VOLTAGE_CNTL, voltage_cntl);
     528           0 : }
     529             : 
     530           0 : static void sumo_set_allos_gnb_slow(struct radeon_device *rdev, u32 index, u32 gnb_slow)
     531             : {
     532           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     533             :         u32 temp = gnb_slow;
     534             :         u32 cg_sclk_dpm_ctrl_3;
     535             : 
     536           0 :         if (pi->driver_nbps_policy_disable)
     537           0 :                 temp = 1;
     538             : 
     539           0 :         cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3);
     540           0 :         cg_sclk_dpm_ctrl_3 &= ~(GNB_SLOW_FSTATE_0_MASK << index);
     541           0 :         cg_sclk_dpm_ctrl_3 |= (temp << (GNB_SLOW_FSTATE_0_SHIFT + index));
     542             : 
     543           0 :         WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3);
     544           0 : }
     545             : 
     546           0 : static void sumo_program_power_level(struct radeon_device *rdev,
     547             :                                      struct sumo_pl *pl, u32 index)
     548             : {
     549           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     550             :         int ret;
     551           0 :         struct atom_clock_dividers dividers;
     552           0 :         u32 ds_en = RREG32(DEEP_SLEEP_CNTL) & ENABLE_DS;
     553             : 
     554           0 :         ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
     555           0 :                                              pl->sclk, false, &dividers);
     556           0 :         if (ret)
     557           0 :                 return;
     558             : 
     559           0 :         sumo_set_divider_value(rdev, index, dividers.post_div);
     560             : 
     561           0 :         sumo_set_vid(rdev, index, pl->vddc_index);
     562             : 
     563           0 :         if (pl->ss_divider_index == 0 || pl->ds_divider_index == 0) {
     564           0 :                 if (ds_en)
     565           0 :                         WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS);
     566             :         } else {
     567           0 :                 sumo_set_ss_dividers(rdev, index, pl->ss_divider_index);
     568           0 :                 sumo_set_ds_dividers(rdev, index, pl->ds_divider_index);
     569             : 
     570           0 :                 if (!ds_en)
     571           0 :                         WREG32_P(DEEP_SLEEP_CNTL, ENABLE_DS, ~ENABLE_DS);
     572             :         }
     573             : 
     574           0 :         sumo_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow);
     575             : 
     576           0 :         if (pi->enable_boost)
     577           0 :                 sumo_set_tdp_limit(rdev, index, pl->sclk_dpm_tdp_limit);
     578           0 : }
     579             : 
     580           0 : static void sumo_power_level_enable(struct radeon_device *rdev, u32 index, bool enable)
     581             : {
     582           0 :         u32 reg_index = index / 4;
     583           0 :         u32 field_index = index % 4;
     584             : 
     585           0 :         if (field_index == 0)
     586           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     587             :                          enable ? SCLK_FSTATE_0_VLD : 0, ~SCLK_FSTATE_0_VLD);
     588           0 :         else if (field_index == 1)
     589           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     590             :                          enable ? SCLK_FSTATE_1_VLD : 0, ~SCLK_FSTATE_1_VLD);
     591           0 :         else if (field_index == 2)
     592           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     593             :                          enable ? SCLK_FSTATE_2_VLD : 0, ~SCLK_FSTATE_2_VLD);
     594           0 :         else if (field_index == 3)
     595           0 :                 WREG32_P(CG_SCLK_DPM_CTRL + (reg_index * 4),
     596             :                          enable ? SCLK_FSTATE_3_VLD : 0, ~SCLK_FSTATE_3_VLD);
     597           0 : }
     598             : 
     599           0 : static bool sumo_dpm_enabled(struct radeon_device *rdev)
     600             : {
     601           0 :         if (RREG32(CG_SCLK_DPM_CTRL_3) & DPM_SCLK_ENABLE)
     602           0 :                 return true;
     603             :         else
     604           0 :                 return false;
     605           0 : }
     606             : 
     607           0 : static void sumo_start_dpm(struct radeon_device *rdev)
     608             : {
     609           0 :         WREG32_P(CG_SCLK_DPM_CTRL_3, DPM_SCLK_ENABLE, ~DPM_SCLK_ENABLE);
     610           0 : }
     611             : 
     612           0 : static void sumo_stop_dpm(struct radeon_device *rdev)
     613             : {
     614           0 :         WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~DPM_SCLK_ENABLE);
     615           0 : }
     616             : 
     617           0 : static void sumo_set_forced_mode(struct radeon_device *rdev, bool enable)
     618             : {
     619           0 :         if (enable)
     620           0 :                 WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE_EN, ~FORCE_SCLK_STATE_EN);
     621             :         else
     622           0 :                 WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_SCLK_STATE_EN);
     623           0 : }
     624             : 
     625           0 : static void sumo_set_forced_mode_enabled(struct radeon_device *rdev)
     626             : {
     627             :         int i;
     628             : 
     629           0 :         sumo_set_forced_mode(rdev, true);
     630           0 :         for (i = 0; i < rdev->usec_timeout; i++) {
     631           0 :                 if (RREG32(CG_SCLK_STATUS) & SCLK_OVERCLK_DETECT)
     632             :                         break;
     633           0 :                 udelay(1);
     634             :         }
     635           0 : }
     636             : 
     637           0 : static void sumo_wait_for_level_0(struct radeon_device *rdev)
     638             : {
     639             :         int i;
     640             : 
     641           0 :         for (i = 0; i < rdev->usec_timeout; i++) {
     642           0 :                 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_SCLK_INDEX_MASK) == 0)
     643             :                         break;
     644           0 :                 udelay(1);
     645             :         }
     646           0 :         for (i = 0; i < rdev->usec_timeout; i++) {
     647           0 :                 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) == 0)
     648             :                         break;
     649           0 :                 udelay(1);
     650             :         }
     651           0 : }
     652             : 
     653           0 : static void sumo_set_forced_mode_disabled(struct radeon_device *rdev)
     654             : {
     655           0 :         sumo_set_forced_mode(rdev, false);
     656           0 : }
     657             : 
     658           0 : static void sumo_enable_power_level_0(struct radeon_device *rdev)
     659             : {
     660           0 :         sumo_power_level_enable(rdev, 0, true);
     661           0 : }
     662             : 
     663           0 : static void sumo_patch_boost_state(struct radeon_device *rdev,
     664             :                                    struct radeon_ps *rps)
     665             : {
     666           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     667           0 :         struct sumo_ps *new_ps = sumo_get_ps(rps);
     668             : 
     669           0 :         if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE) {
     670           0 :                 pi->boost_pl = new_ps->levels[new_ps->num_levels - 1];
     671           0 :                 pi->boost_pl.sclk = pi->sys_info.boost_sclk;
     672           0 :                 pi->boost_pl.vddc_index = pi->sys_info.boost_vid_2bit;
     673           0 :                 pi->boost_pl.sclk_dpm_tdp_limit = pi->sys_info.sclk_dpm_tdp_limit_boost;
     674           0 :         }
     675           0 : }
     676             : 
     677           0 : static void sumo_pre_notify_alt_vddnb_change(struct radeon_device *rdev,
     678             :                                              struct radeon_ps *new_rps,
     679             :                                              struct radeon_ps *old_rps)
     680             : {
     681           0 :         struct sumo_ps *new_ps = sumo_get_ps(new_rps);
     682           0 :         struct sumo_ps *old_ps = sumo_get_ps(old_rps);
     683             :         u32 nbps1_old = 0;
     684             :         u32 nbps1_new = 0;
     685             : 
     686           0 :         if (old_ps != NULL)
     687           0 :                 nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) ? 1 : 0;
     688             : 
     689           0 :         nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE) ? 1 : 0;
     690             : 
     691           0 :         if (nbps1_old == 1 && nbps1_new == 0)
     692           0 :                 sumo_smu_notify_alt_vddnb_change(rdev, 0, 0);
     693           0 : }
     694             : 
     695           0 : static void sumo_post_notify_alt_vddnb_change(struct radeon_device *rdev,
     696             :                                               struct radeon_ps *new_rps,
     697             :                                               struct radeon_ps *old_rps)
     698             : {
     699           0 :         struct sumo_ps *new_ps = sumo_get_ps(new_rps);
     700           0 :         struct sumo_ps *old_ps = sumo_get_ps(old_rps);
     701             :         u32 nbps1_old = 0;
     702             :         u32 nbps1_new = 0;
     703             : 
     704           0 :         if (old_ps != NULL)
     705           0 :                 nbps1_old = (old_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)? 1 : 0;
     706             : 
     707           0 :         nbps1_new = (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)? 1 : 0;
     708             : 
     709           0 :         if (nbps1_old == 0 && nbps1_new == 1)
     710           0 :                 sumo_smu_notify_alt_vddnb_change(rdev, 1, 1);
     711           0 : }
     712             : 
     713           0 : static void sumo_enable_boost(struct radeon_device *rdev,
     714             :                               struct radeon_ps *rps,
     715             :                               bool enable)
     716             : {
     717           0 :         struct sumo_ps *new_ps = sumo_get_ps(rps);
     718             : 
     719           0 :         if (enable) {
     720           0 :                 if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
     721           0 :                         sumo_boost_state_enable(rdev, true);
     722             :         } else
     723           0 :                 sumo_boost_state_enable(rdev, false);
     724           0 : }
     725             : 
     726           0 : static void sumo_set_forced_level(struct radeon_device *rdev, u32 index)
     727             : {
     728           0 :         WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_SCLK_STATE(index), ~FORCE_SCLK_STATE_MASK);
     729           0 : }
     730             : 
     731           0 : static void sumo_set_forced_level_0(struct radeon_device *rdev)
     732             : {
     733           0 :         sumo_set_forced_level(rdev, 0);
     734           0 : }
     735             : 
     736           0 : static void sumo_program_wl(struct radeon_device *rdev,
     737             :                             struct radeon_ps *rps)
     738             : {
     739           0 :         struct sumo_ps *new_ps = sumo_get_ps(rps);
     740           0 :         u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4);
     741             : 
     742           0 :         dpm_ctrl4 &= 0xFFFFFF00;
     743           0 :         dpm_ctrl4 |= (1 << (new_ps->num_levels - 1));
     744             : 
     745           0 :         if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
     746           0 :                 dpm_ctrl4 |= (1 << BOOST_DPM_LEVEL);
     747             : 
     748           0 :         WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4);
     749           0 : }
     750             : 
     751           0 : static void sumo_program_power_levels_0_to_n(struct radeon_device *rdev,
     752             :                                              struct radeon_ps *new_rps,
     753             :                                              struct radeon_ps *old_rps)
     754             : {
     755           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     756           0 :         struct sumo_ps *new_ps = sumo_get_ps(new_rps);
     757           0 :         struct sumo_ps *old_ps = sumo_get_ps(old_rps);
     758             :         u32 i;
     759           0 :         u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels;
     760             : 
     761           0 :         for (i = 0; i < new_ps->num_levels; i++) {
     762           0 :                 sumo_program_power_level(rdev, &new_ps->levels[i], i);
     763           0 :                 sumo_power_level_enable(rdev, i, true);
     764             :         }
     765             : 
     766           0 :         for (i = new_ps->num_levels; i < n_current_state_levels; i++)
     767           0 :                 sumo_power_level_enable(rdev, i, false);
     768             : 
     769           0 :         if (new_ps->flags & SUMO_POWERSTATE_FLAGS_BOOST_STATE)
     770           0 :                 sumo_program_power_level(rdev, &pi->boost_pl, BOOST_DPM_LEVEL);
     771           0 : }
     772             : 
     773           0 : static void sumo_enable_acpi_pm(struct radeon_device *rdev)
     774             : {
     775           0 :         WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN);
     776           0 : }
     777             : 
     778           0 : static void sumo_program_power_level_enter_state(struct radeon_device *rdev)
     779             : {
     780           0 :         WREG32_P(CG_SCLK_DPM_CTRL_5, SCLK_FSTATE_BOOTUP(0), ~SCLK_FSTATE_BOOTUP_MASK);
     781           0 : }
     782             : 
     783           0 : static void sumo_program_acpi_power_level(struct radeon_device *rdev)
     784             : {
     785           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     786           0 :         struct atom_clock_dividers dividers;
     787             :         int ret;
     788             : 
     789           0 :         ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
     790           0 :                                              pi->acpi_pl.sclk,
     791             :                                              false, &dividers);
     792           0 :         if (ret)
     793           0 :                 return;
     794             : 
     795           0 :         WREG32_P(CG_ACPI_CNTL, SCLK_ACPI_DIV(dividers.post_div), ~SCLK_ACPI_DIV_MASK);
     796           0 :         WREG32_P(CG_ACPI_VOLTAGE_CNTL, 0, ~ACPI_VOLTAGE_EN);
     797           0 : }
     798             : 
     799           0 : static void sumo_program_bootup_state(struct radeon_device *rdev)
     800             : {
     801           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     802           0 :         u32 dpm_ctrl4 = RREG32(CG_SCLK_DPM_CTRL_4);
     803             :         u32 i;
     804             : 
     805           0 :         sumo_program_power_level(rdev, &pi->boot_pl, 0);
     806             : 
     807           0 :         dpm_ctrl4 &= 0xFFFFFF00;
     808           0 :         WREG32(CG_SCLK_DPM_CTRL_4, dpm_ctrl4);
     809             : 
     810           0 :         for (i = 1; i < 8; i++)
     811           0 :                 sumo_power_level_enable(rdev, i, false);
     812           0 : }
     813             : 
     814           0 : static void sumo_setup_uvd_clocks(struct radeon_device *rdev,
     815             :                                   struct radeon_ps *new_rps,
     816             :                                   struct radeon_ps *old_rps)
     817             : {
     818           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     819             : 
     820           0 :         if (pi->enable_gfx_power_gating) {
     821           0 :                 sumo_gfx_powergating_enable(rdev, false);
     822           0 :         }
     823             : 
     824           0 :         radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk);
     825             : 
     826           0 :         if (pi->enable_gfx_power_gating) {
     827           0 :                 if (!pi->disable_gfx_power_gating_in_uvd ||
     828           0 :                     !r600_is_uvd_state(new_rps->class, new_rps->class2))
     829           0 :                         sumo_gfx_powergating_enable(rdev, true);
     830             :         }
     831           0 : }
     832             : 
     833           0 : static void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
     834             :                                                     struct radeon_ps *new_rps,
     835             :                                                     struct radeon_ps *old_rps)
     836             : {
     837           0 :         struct sumo_ps *new_ps = sumo_get_ps(new_rps);
     838           0 :         struct sumo_ps *current_ps = sumo_get_ps(old_rps);
     839             : 
     840           0 :         if ((new_rps->vclk == old_rps->vclk) &&
     841           0 :             (new_rps->dclk == old_rps->dclk))
     842           0 :                 return;
     843             : 
     844           0 :         if (new_ps->levels[new_ps->num_levels - 1].sclk >=
     845           0 :             current_ps->levels[current_ps->num_levels - 1].sclk)
     846           0 :                 return;
     847             : 
     848           0 :         sumo_setup_uvd_clocks(rdev, new_rps, old_rps);
     849           0 : }
     850             : 
     851           0 : static void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
     852             :                                                    struct radeon_ps *new_rps,
     853             :                                                    struct radeon_ps *old_rps)
     854             : {
     855           0 :         struct sumo_ps *new_ps = sumo_get_ps(new_rps);
     856           0 :         struct sumo_ps *current_ps = sumo_get_ps(old_rps);
     857             : 
     858           0 :         if ((new_rps->vclk == old_rps->vclk) &&
     859           0 :             (new_rps->dclk == old_rps->dclk))
     860           0 :                 return;
     861             : 
     862           0 :         if (new_ps->levels[new_ps->num_levels - 1].sclk <
     863           0 :             current_ps->levels[current_ps->num_levels - 1].sclk)
     864           0 :                 return;
     865             : 
     866           0 :         sumo_setup_uvd_clocks(rdev, new_rps, old_rps);
     867           0 : }
     868             : 
     869           0 : void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
     870             : {
     871             : /* This bit selects who handles display phy powergating.
     872             :  * Clear the bit to let atom handle it.
     873             :  * Set it to let the driver handle it.
     874             :  * For now we just let atom handle it.
     875             :  */
     876             : #if 0
     877             :         u32 v = RREG32(DOUT_SCRATCH3);
     878             : 
     879             :         if (enable)
     880             :                 v |= 0x4;
     881             :         else
     882             :                 v &= 0xFFFFFFFB;
     883             : 
     884             :         WREG32(DOUT_SCRATCH3, v);
     885             : #endif
     886           0 : }
     887             : 
     888           0 : static void sumo_enable_sclk_ds(struct radeon_device *rdev, bool enable)
     889             : {
     890           0 :         if (enable) {
     891           0 :                 u32 deep_sleep_cntl = RREG32(DEEP_SLEEP_CNTL);
     892           0 :                 u32 deep_sleep_cntl2 = RREG32(DEEP_SLEEP_CNTL2);
     893             :                 u32 t = 1;
     894             : 
     895           0 :                 deep_sleep_cntl &= ~R_DIS;
     896           0 :                 deep_sleep_cntl &= ~HS_MASK;
     897           0 :                 deep_sleep_cntl |= HS(t > 4095 ? 4095 : t);
     898             : 
     899           0 :                 deep_sleep_cntl2 |= LB_UFP_EN;
     900           0 :                 deep_sleep_cntl2 &= INOUT_C_MASK;
     901           0 :                 deep_sleep_cntl2 |= INOUT_C(0xf);
     902             : 
     903           0 :                 WREG32(DEEP_SLEEP_CNTL2, deep_sleep_cntl2);
     904           0 :                 WREG32(DEEP_SLEEP_CNTL, deep_sleep_cntl);
     905           0 :         } else
     906           0 :                 WREG32_P(DEEP_SLEEP_CNTL, 0, ~ENABLE_DS);
     907           0 : }
     908             : 
     909           0 : static void sumo_program_bootup_at(struct radeon_device *rdev)
     910             : {
     911           0 :         WREG32_P(CG_AT_0, CG_R(0xffff), ~CG_R_MASK);
     912           0 :         WREG32_P(CG_AT_0, CG_L(0), ~CG_L_MASK);
     913           0 : }
     914             : 
     915           0 : static void sumo_reset_am(struct radeon_device *rdev)
     916             : {
     917           0 :         WREG32_P(SCLK_PWRMGT_CNTL, FIR_RESET, ~FIR_RESET);
     918           0 : }
     919             : 
     920           0 : static void sumo_start_am(struct radeon_device *rdev)
     921             : {
     922           0 :         WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_RESET);
     923           0 : }
     924             : 
     925           0 : static void sumo_program_ttp(struct radeon_device *rdev)
     926             : {
     927           0 :         u32 xclk = radeon_get_xclk(rdev);
     928           0 :         u32 p, u;
     929           0 :         u32 cg_sclk_dpm_ctrl_5 = RREG32(CG_SCLK_DPM_CTRL_5);
     930             : 
     931           0 :         r600_calculate_u_and_p(1000,
     932             :                                xclk, 16, &p, &u);
     933             : 
     934           0 :         cg_sclk_dpm_ctrl_5 &= ~(TT_TP_MASK | TT_TU_MASK);
     935           0 :         cg_sclk_dpm_ctrl_5 |= TT_TP(p) | TT_TU(u);
     936             : 
     937           0 :         WREG32(CG_SCLK_DPM_CTRL_5, cg_sclk_dpm_ctrl_5);
     938           0 : }
     939             : 
     940           0 : static void sumo_program_ttt(struct radeon_device *rdev)
     941             : {
     942           0 :         u32 cg_sclk_dpm_ctrl_3 = RREG32(CG_SCLK_DPM_CTRL_3);
     943           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     944             : 
     945           0 :         cg_sclk_dpm_ctrl_3 &= ~(GNB_TT_MASK | GNB_THERMTHRO_MASK);
     946           0 :         cg_sclk_dpm_ctrl_3 |= GNB_TT(pi->thermal_auto_throttling + 49);
     947             : 
     948           0 :         WREG32(CG_SCLK_DPM_CTRL_3, cg_sclk_dpm_ctrl_3);
     949           0 : }
     950             : 
     951             : 
     952           0 : static void sumo_enable_voltage_scaling(struct radeon_device *rdev, bool enable)
     953             : {
     954           0 :         if (enable) {
     955           0 :                 WREG32_P(CG_DPM_VOLTAGE_CNTL, DPM_VOLTAGE_EN, ~DPM_VOLTAGE_EN);
     956           0 :                 WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~CG_VOLTAGE_EN);
     957           0 :         } else {
     958           0 :                 WREG32_P(CG_CG_VOLTAGE_CNTL, CG_VOLTAGE_EN, ~CG_VOLTAGE_EN);
     959           0 :                 WREG32_P(CG_DPM_VOLTAGE_CNTL, 0, ~DPM_VOLTAGE_EN);
     960             :         }
     961           0 : }
     962             : 
     963           0 : static void sumo_override_cnb_thermal_events(struct radeon_device *rdev)
     964             : {
     965           0 :         WREG32_P(CG_SCLK_DPM_CTRL_3, CNB_THERMTHRO_MASK_SCLK,
     966             :                  ~CNB_THERMTHRO_MASK_SCLK);
     967           0 : }
     968             : 
     969           0 : static void sumo_program_dc_hto(struct radeon_device *rdev)
     970             : {
     971           0 :         u32 cg_sclk_dpm_ctrl_4 = RREG32(CG_SCLK_DPM_CTRL_4);
     972           0 :         u32 p, u;
     973           0 :         u32 xclk = radeon_get_xclk(rdev);
     974             : 
     975           0 :         r600_calculate_u_and_p(100000,
     976             :                                xclk, 14, &p, &u);
     977             : 
     978           0 :         cg_sclk_dpm_ctrl_4 &= ~(DC_HDC_MASK | DC_HU_MASK);
     979           0 :         cg_sclk_dpm_ctrl_4 |= DC_HDC(p) | DC_HU(u);
     980             : 
     981           0 :         WREG32(CG_SCLK_DPM_CTRL_4, cg_sclk_dpm_ctrl_4);
     982           0 : }
     983             : 
     984           0 : static void sumo_force_nbp_state(struct radeon_device *rdev,
     985             :                                  struct radeon_ps *rps)
     986             : {
     987           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
     988           0 :         struct sumo_ps *new_ps = sumo_get_ps(rps);
     989             : 
     990           0 :         if (!pi->driver_nbps_policy_disable) {
     991           0 :                 if (new_ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)
     992           0 :                         WREG32_P(CG_SCLK_DPM_CTRL_3, FORCE_NB_PSTATE_1, ~FORCE_NB_PSTATE_1);
     993             :                 else
     994           0 :                         WREG32_P(CG_SCLK_DPM_CTRL_3, 0, ~FORCE_NB_PSTATE_1);
     995             :         }
     996           0 : }
     997             : 
     998           0 : u32 sumo_get_sleep_divider_from_id(u32 id)
     999             : {
    1000           0 :         return 1 << id;
    1001             : }
    1002             : 
    1003           0 : u32 sumo_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
    1004             :                                          u32 sclk,
    1005             :                                          u32 min_sclk_in_sr)
    1006             : {
    1007           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1008             :         u32 i;
    1009             :         u32 temp;
    1010           0 :         u32 min = (min_sclk_in_sr > SUMO_MINIMUM_ENGINE_CLOCK) ?
    1011             :                 min_sclk_in_sr : SUMO_MINIMUM_ENGINE_CLOCK;
    1012             : 
    1013           0 :         if (sclk < min)
    1014           0 :                 return 0;
    1015             : 
    1016           0 :         if (!pi->enable_sclk_ds)
    1017           0 :                 return 0;
    1018             : 
    1019           0 :         for (i = SUMO_MAX_DEEPSLEEP_DIVIDER_ID;  ; i--) {
    1020           0 :                 temp = sclk / sumo_get_sleep_divider_from_id(i);
    1021             : 
    1022           0 :                 if (temp >= min || i == 0)
    1023             :                         break;
    1024             :         }
    1025           0 :         return i;
    1026           0 : }
    1027             : 
    1028           0 : static u32 sumo_get_valid_engine_clock(struct radeon_device *rdev,
    1029             :                                        u32 lower_limit)
    1030             : {
    1031           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1032             :         u32 i;
    1033             : 
    1034           0 :         for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) {
    1035           0 :                 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit)
    1036           0 :                         return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency;
    1037             :         }
    1038             : 
    1039           0 :         return pi->sys_info.sclk_voltage_mapping_table.entries[pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1].sclk_frequency;
    1040           0 : }
    1041             : 
    1042           0 : static void sumo_patch_thermal_state(struct radeon_device *rdev,
    1043             :                                      struct sumo_ps *ps,
    1044             :                                      struct sumo_ps *current_ps)
    1045             : {
    1046           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1047           0 :         u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
    1048             :         u32 current_vddc;
    1049             :         u32 current_sclk;
    1050             :         u32 current_index = 0;
    1051             : 
    1052           0 :         if (current_ps) {
    1053           0 :                 current_vddc = current_ps->levels[current_index].vddc_index;
    1054           0 :                 current_sclk = current_ps->levels[current_index].sclk;
    1055           0 :         } else {
    1056           0 :                 current_vddc = pi->boot_pl.vddc_index;
    1057           0 :                 current_sclk = pi->boot_pl.sclk;
    1058             :         }
    1059             : 
    1060           0 :         ps->levels[0].vddc_index = current_vddc;
    1061             : 
    1062           0 :         if (ps->levels[0].sclk > current_sclk)
    1063           0 :                 ps->levels[0].sclk = current_sclk;
    1064             : 
    1065           0 :         ps->levels[0].ss_divider_index =
    1066           0 :                 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr);
    1067             : 
    1068           0 :         ps->levels[0].ds_divider_index =
    1069           0 :                 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, SUMO_MINIMUM_ENGINE_CLOCK);
    1070             : 
    1071           0 :         if (ps->levels[0].ds_divider_index > ps->levels[0].ss_divider_index + 1)
    1072           0 :                 ps->levels[0].ds_divider_index = ps->levels[0].ss_divider_index + 1;
    1073             : 
    1074           0 :         if (ps->levels[0].ss_divider_index == ps->levels[0].ds_divider_index) {
    1075           0 :                 if (ps->levels[0].ss_divider_index > 1)
    1076           0 :                         ps->levels[0].ss_divider_index = ps->levels[0].ss_divider_index - 1;
    1077             :         }
    1078             : 
    1079           0 :         if (ps->levels[0].ss_divider_index == 0)
    1080           0 :                 ps->levels[0].ds_divider_index = 0;
    1081             : 
    1082           0 :         if (ps->levels[0].ds_divider_index == 0)
    1083           0 :                 ps->levels[0].ss_divider_index = 0;
    1084           0 : }
    1085             : 
    1086           0 : static void sumo_apply_state_adjust_rules(struct radeon_device *rdev,
    1087             :                                           struct radeon_ps *new_rps,
    1088             :                                           struct radeon_ps *old_rps)
    1089             : {
    1090           0 :         struct sumo_ps *ps = sumo_get_ps(new_rps);
    1091           0 :         struct sumo_ps *current_ps = sumo_get_ps(old_rps);
    1092           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1093             :         u32 min_voltage = 0; /* ??? */
    1094           0 :         u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */
    1095             :         u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */
    1096             :         u32 i;
    1097             : 
    1098           0 :         if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL)
    1099           0 :                 return sumo_patch_thermal_state(rdev, ps, current_ps);
    1100             : 
    1101           0 :         if (pi->enable_boost) {
    1102           0 :                 if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE)
    1103           0 :                         ps->flags |= SUMO_POWERSTATE_FLAGS_BOOST_STATE;
    1104             :         }
    1105             : 
    1106           0 :         if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) ||
    1107           0 :             (new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) ||
    1108           0 :             (new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE))
    1109           0 :                 ps->flags |= SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE;
    1110             : 
    1111           0 :         for (i = 0; i < ps->num_levels; i++) {
    1112           0 :                 if (ps->levels[i].vddc_index < min_voltage)
    1113           0 :                         ps->levels[i].vddc_index = min_voltage;
    1114             : 
    1115           0 :                 if (ps->levels[i].sclk < min_sclk)
    1116           0 :                         ps->levels[i].sclk =
    1117           0 :                                 sumo_get_valid_engine_clock(rdev, min_sclk);
    1118             : 
    1119           0 :                 ps->levels[i].ss_divider_index =
    1120           0 :                         sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr);
    1121             : 
    1122           0 :                 ps->levels[i].ds_divider_index =
    1123           0 :                         sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, SUMO_MINIMUM_ENGINE_CLOCK);
    1124             : 
    1125           0 :                 if (ps->levels[i].ds_divider_index > ps->levels[i].ss_divider_index + 1)
    1126           0 :                         ps->levels[i].ds_divider_index = ps->levels[i].ss_divider_index + 1;
    1127             : 
    1128           0 :                 if (ps->levels[i].ss_divider_index == ps->levels[i].ds_divider_index) {
    1129           0 :                         if (ps->levels[i].ss_divider_index > 1)
    1130           0 :                                 ps->levels[i].ss_divider_index = ps->levels[i].ss_divider_index - 1;
    1131             :                 }
    1132             : 
    1133           0 :                 if (ps->levels[i].ss_divider_index == 0)
    1134           0 :                         ps->levels[i].ds_divider_index = 0;
    1135             : 
    1136           0 :                 if (ps->levels[i].ds_divider_index == 0)
    1137           0 :                         ps->levels[i].ss_divider_index = 0;
    1138             : 
    1139           0 :                 if (ps->flags & SUMO_POWERSTATE_FLAGS_FORCE_NBPS1_STATE)
    1140           0 :                         ps->levels[i].allow_gnb_slow = 1;
    1141           0 :                 else if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) ||
    1142           0 :                          (new_rps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC))
    1143           0 :                         ps->levels[i].allow_gnb_slow = 0;
    1144           0 :                 else if (i == ps->num_levels - 1)
    1145           0 :                         ps->levels[i].allow_gnb_slow = 0;
    1146             :                 else
    1147           0 :                         ps->levels[i].allow_gnb_slow = 1;
    1148             :         }
    1149           0 : }
    1150             : 
    1151           0 : static void sumo_cleanup_asic(struct radeon_device *rdev)
    1152             : {
    1153           0 :         sumo_take_smu_control(rdev, false);
    1154           0 : }
    1155             : 
    1156           0 : static int sumo_set_thermal_temperature_range(struct radeon_device *rdev,
    1157             :                                               int min_temp, int max_temp)
    1158             : {
    1159             :         int low_temp = 0 * 1000;
    1160             :         int high_temp = 255 * 1000;
    1161             : 
    1162           0 :         if (low_temp < min_temp)
    1163           0 :                 low_temp = min_temp;
    1164           0 :         if (high_temp > max_temp)
    1165           0 :                 high_temp = max_temp;
    1166           0 :         if (high_temp < low_temp) {
    1167           0 :                 DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
    1168           0 :                 return -EINVAL;
    1169             :         }
    1170             : 
    1171           0 :         WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK);
    1172           0 :         WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK);
    1173             : 
    1174           0 :         rdev->pm.dpm.thermal.min_temp = low_temp;
    1175           0 :         rdev->pm.dpm.thermal.max_temp = high_temp;
    1176             : 
    1177           0 :         return 0;
    1178           0 : }
    1179             : 
    1180           0 : static void sumo_update_current_ps(struct radeon_device *rdev,
    1181             :                                    struct radeon_ps *rps)
    1182             : {
    1183           0 :         struct sumo_ps *new_ps = sumo_get_ps(rps);
    1184           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1185             : 
    1186           0 :         pi->current_rps = *rps;
    1187           0 :         pi->current_ps = *new_ps;
    1188           0 :         pi->current_rps.ps_priv = &pi->current_ps;
    1189           0 : }
    1190             : 
    1191           0 : static void sumo_update_requested_ps(struct radeon_device *rdev,
    1192             :                                      struct radeon_ps *rps)
    1193             : {
    1194           0 :         struct sumo_ps *new_ps = sumo_get_ps(rps);
    1195           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1196             : 
    1197           0 :         pi->requested_rps = *rps;
    1198           0 :         pi->requested_ps = *new_ps;
    1199           0 :         pi->requested_rps.ps_priv = &pi->requested_ps;
    1200           0 : }
    1201             : 
    1202           0 : int sumo_dpm_enable(struct radeon_device *rdev)
    1203             : {
    1204           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1205             : 
    1206           0 :         if (sumo_dpm_enabled(rdev))
    1207           0 :                 return -EINVAL;
    1208             : 
    1209           0 :         sumo_program_bootup_state(rdev);
    1210           0 :         sumo_init_bsp(rdev);
    1211           0 :         sumo_reset_am(rdev);
    1212           0 :         sumo_program_tp(rdev);
    1213           0 :         sumo_program_bootup_at(rdev);
    1214           0 :         sumo_start_am(rdev);
    1215           0 :         if (pi->enable_auto_thermal_throttling) {
    1216           0 :                 sumo_program_ttp(rdev);
    1217           0 :                 sumo_program_ttt(rdev);
    1218           0 :         }
    1219           0 :         sumo_program_dc_hto(rdev);
    1220           0 :         sumo_program_power_level_enter_state(rdev);
    1221           0 :         sumo_enable_voltage_scaling(rdev, true);
    1222           0 :         sumo_program_sstp(rdev);
    1223           0 :         sumo_program_vc(rdev, SUMO_VRC_DFLT);
    1224           0 :         sumo_override_cnb_thermal_events(rdev);
    1225           0 :         sumo_start_dpm(rdev);
    1226           0 :         sumo_wait_for_level_0(rdev);
    1227           0 :         if (pi->enable_sclk_ds)
    1228           0 :                 sumo_enable_sclk_ds(rdev, true);
    1229           0 :         if (pi->enable_boost)
    1230           0 :                 sumo_enable_boost_timer(rdev);
    1231             : 
    1232           0 :         sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
    1233             : 
    1234           0 :         return 0;
    1235           0 : }
    1236             : 
    1237           0 : int sumo_dpm_late_enable(struct radeon_device *rdev)
    1238             : {
    1239             :         int ret;
    1240             : 
    1241           0 :         ret = sumo_enable_clock_power_gating(rdev);
    1242           0 :         if (ret)
    1243           0 :                 return ret;
    1244             : 
    1245           0 :         if (rdev->irq.installed &&
    1246           0 :             r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
    1247           0 :                 ret = sumo_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
    1248           0 :                 if (ret)
    1249           0 :                         return ret;
    1250           0 :                 rdev->irq.dpm_thermal = true;
    1251           0 :                 radeon_irq_set(rdev);
    1252           0 :         }
    1253             : 
    1254           0 :         return 0;
    1255           0 : }
    1256             : 
    1257           0 : void sumo_dpm_disable(struct radeon_device *rdev)
    1258             : {
    1259           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1260             : 
    1261           0 :         if (!sumo_dpm_enabled(rdev))
    1262           0 :                 return;
    1263           0 :         sumo_disable_clock_power_gating(rdev);
    1264           0 :         if (pi->enable_sclk_ds)
    1265           0 :                 sumo_enable_sclk_ds(rdev, false);
    1266           0 :         sumo_clear_vc(rdev);
    1267           0 :         sumo_wait_for_level_0(rdev);
    1268           0 :         sumo_stop_dpm(rdev);
    1269           0 :         sumo_enable_voltage_scaling(rdev, false);
    1270             : 
    1271           0 :         if (rdev->irq.installed &&
    1272           0 :             r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
    1273           0 :                 rdev->irq.dpm_thermal = false;
    1274           0 :                 radeon_irq_set(rdev);
    1275           0 :         }
    1276             : 
    1277           0 :         sumo_update_current_ps(rdev, rdev->pm.dpm.boot_ps);
    1278           0 : }
    1279             : 
    1280           0 : int sumo_dpm_pre_set_power_state(struct radeon_device *rdev)
    1281             : {
    1282           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1283           0 :         struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps;
    1284             :         struct radeon_ps *new_ps = &requested_ps;
    1285             : 
    1286           0 :         sumo_update_requested_ps(rdev, new_ps);
    1287             : 
    1288           0 :         if (pi->enable_dynamic_patch_ps)
    1289           0 :                 sumo_apply_state_adjust_rules(rdev,
    1290           0 :                                               &pi->requested_rps,
    1291           0 :                                               &pi->current_rps);
    1292             : 
    1293           0 :         return 0;
    1294           0 : }
    1295             : 
    1296           0 : int sumo_dpm_set_power_state(struct radeon_device *rdev)
    1297             : {
    1298           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1299           0 :         struct radeon_ps *new_ps = &pi->requested_rps;
    1300           0 :         struct radeon_ps *old_ps = &pi->current_rps;
    1301             : 
    1302           0 :         if (pi->enable_dpm)
    1303           0 :                 sumo_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
    1304           0 :         if (pi->enable_boost) {
    1305           0 :                 sumo_enable_boost(rdev, new_ps, false);
    1306           0 :                 sumo_patch_boost_state(rdev, new_ps);
    1307           0 :         }
    1308           0 :         if (pi->enable_dpm) {
    1309           0 :                 sumo_pre_notify_alt_vddnb_change(rdev, new_ps, old_ps);
    1310           0 :                 sumo_enable_power_level_0(rdev);
    1311           0 :                 sumo_set_forced_level_0(rdev);
    1312           0 :                 sumo_set_forced_mode_enabled(rdev);
    1313           0 :                 sumo_wait_for_level_0(rdev);
    1314           0 :                 sumo_program_power_levels_0_to_n(rdev, new_ps, old_ps);
    1315           0 :                 sumo_program_wl(rdev, new_ps);
    1316           0 :                 sumo_program_bsp(rdev, new_ps);
    1317           0 :                 sumo_program_at(rdev, new_ps);
    1318           0 :                 sumo_force_nbp_state(rdev, new_ps);
    1319           0 :                 sumo_set_forced_mode_disabled(rdev);
    1320           0 :                 sumo_set_forced_mode_enabled(rdev);
    1321           0 :                 sumo_set_forced_mode_disabled(rdev);
    1322           0 :                 sumo_post_notify_alt_vddnb_change(rdev, new_ps, old_ps);
    1323           0 :         }
    1324           0 :         if (pi->enable_boost)
    1325           0 :                 sumo_enable_boost(rdev, new_ps, true);
    1326           0 :         if (pi->enable_dpm)
    1327           0 :                 sumo_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
    1328             : 
    1329           0 :         return 0;
    1330             : }
    1331             : 
    1332           0 : void sumo_dpm_post_set_power_state(struct radeon_device *rdev)
    1333             : {
    1334           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1335           0 :         struct radeon_ps *new_ps = &pi->requested_rps;
    1336             : 
    1337           0 :         sumo_update_current_ps(rdev, new_ps);
    1338           0 : }
    1339             : 
    1340             : #if 0
    1341             : void sumo_dpm_reset_asic(struct radeon_device *rdev)
    1342             : {
    1343             :         sumo_program_bootup_state(rdev);
    1344             :         sumo_enable_power_level_0(rdev);
    1345             :         sumo_set_forced_level_0(rdev);
    1346             :         sumo_set_forced_mode_enabled(rdev);
    1347             :         sumo_wait_for_level_0(rdev);
    1348             :         sumo_set_forced_mode_disabled(rdev);
    1349             :         sumo_set_forced_mode_enabled(rdev);
    1350             :         sumo_set_forced_mode_disabled(rdev);
    1351             : }
    1352             : #endif
    1353             : 
    1354           0 : void sumo_dpm_setup_asic(struct radeon_device *rdev)
    1355             : {
    1356           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1357             : 
    1358           0 :         sumo_initialize_m3_arb(rdev);
    1359           0 :         pi->fw_version = sumo_get_running_fw_version(rdev);
    1360             :         DRM_INFO("Found smc ucode version: 0x%08x\n", pi->fw_version);
    1361           0 :         sumo_program_acpi_power_level(rdev);
    1362           0 :         sumo_enable_acpi_pm(rdev);
    1363           0 :         sumo_take_smu_control(rdev, true);
    1364           0 : }
    1365             : 
    1366           0 : void sumo_dpm_display_configuration_changed(struct radeon_device *rdev)
    1367             : {
    1368             : 
    1369           0 : }
    1370             : 
    1371             : union power_info {
    1372             :         struct _ATOM_POWERPLAY_INFO info;
    1373             :         struct _ATOM_POWERPLAY_INFO_V2 info_2;
    1374             :         struct _ATOM_POWERPLAY_INFO_V3 info_3;
    1375             :         struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
    1376             :         struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
    1377             :         struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
    1378             : };
    1379             : 
    1380             : union pplib_clock_info {
    1381             :         struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
    1382             :         struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
    1383             :         struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
    1384             :         struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
    1385             : };
    1386             : 
    1387             : union pplib_power_state {
    1388             :         struct _ATOM_PPLIB_STATE v1;
    1389             :         struct _ATOM_PPLIB_STATE_V2 v2;
    1390             : };
    1391             : 
    1392           0 : static void sumo_patch_boot_state(struct radeon_device *rdev,
    1393             :                                   struct sumo_ps *ps)
    1394             : {
    1395           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1396             : 
    1397           0 :         ps->num_levels = 1;
    1398           0 :         ps->flags = 0;
    1399           0 :         ps->levels[0] = pi->boot_pl;
    1400           0 : }
    1401             : 
    1402           0 : static void sumo_parse_pplib_non_clock_info(struct radeon_device *rdev,
    1403             :                                             struct radeon_ps *rps,
    1404             :                                             struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
    1405             :                                             u8 table_rev)
    1406             : {
    1407           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
    1408             : 
    1409           0 :         rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
    1410           0 :         rps->class = le16_to_cpu(non_clock_info->usClassification);
    1411           0 :         rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
    1412             : 
    1413           0 :         if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
    1414           0 :                 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
    1415           0 :                 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
    1416           0 :         } else {
    1417           0 :                 rps->vclk = 0;
    1418           0 :                 rps->dclk = 0;
    1419             :         }
    1420             : 
    1421           0 :         if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
    1422           0 :                 rdev->pm.dpm.boot_ps = rps;
    1423           0 :                 sumo_patch_boot_state(rdev, ps);
    1424           0 :         }
    1425           0 :         if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
    1426           0 :                 rdev->pm.dpm.uvd_ps = rps;
    1427           0 : }
    1428             : 
    1429           0 : static void sumo_parse_pplib_clock_info(struct radeon_device *rdev,
    1430             :                                         struct radeon_ps *rps, int index,
    1431             :                                         union pplib_clock_info *clock_info)
    1432             : {
    1433           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1434           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
    1435           0 :         struct sumo_pl *pl = &ps->levels[index];
    1436             :         u32 sclk;
    1437             : 
    1438           0 :         sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow);
    1439           0 :         sclk |= clock_info->sumo.ucEngineClockHigh << 16;
    1440           0 :         pl->sclk = sclk;
    1441           0 :         pl->vddc_index = clock_info->sumo.vddcIndex;
    1442           0 :         pl->sclk_dpm_tdp_limit = clock_info->sumo.tdpLimit;
    1443             : 
    1444           0 :         ps->num_levels = index + 1;
    1445             : 
    1446           0 :         if (pi->enable_sclk_ds) {
    1447           0 :                 pl->ds_divider_index = 5;
    1448           0 :                 pl->ss_divider_index = 4;
    1449           0 :         }
    1450           0 : }
    1451             : 
    1452           0 : static int sumo_parse_power_table(struct radeon_device *rdev)
    1453             : {
    1454           0 :         struct radeon_mode_info *mode_info = &rdev->mode_info;
    1455             :         struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
    1456             :         union pplib_power_state *power_state;
    1457             :         int i, j, k, non_clock_array_index, clock_array_index;
    1458             :         union pplib_clock_info *clock_info;
    1459             :         struct _StateArray *state_array;
    1460             :         struct _ClockInfoArray *clock_info_array;
    1461             :         struct _NonClockInfoArray *non_clock_info_array;
    1462             :         union power_info *power_info;
    1463             :         int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
    1464           0 :         u16 data_offset;
    1465           0 :         u8 frev, crev;
    1466             :         u8 *power_state_offset;
    1467             :         struct sumo_ps *ps;
    1468             : 
    1469           0 :         if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
    1470             :                                    &frev, &crev, &data_offset))
    1471           0 :                 return -EINVAL;
    1472           0 :         power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
    1473             : 
    1474           0 :         state_array = (struct _StateArray *)
    1475           0 :                 (mode_info->atom_context->bios + data_offset +
    1476           0 :                  le16_to_cpu(power_info->pplib.usStateArrayOffset));
    1477           0 :         clock_info_array = (struct _ClockInfoArray *)
    1478           0 :                 (mode_info->atom_context->bios + data_offset +
    1479           0 :                  le16_to_cpu(power_info->pplib.usClockInfoArrayOffset));
    1480           0 :         non_clock_info_array = (struct _NonClockInfoArray *)
    1481           0 :                 (mode_info->atom_context->bios + data_offset +
    1482           0 :                  le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
    1483             : 
    1484           0 :         rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
    1485           0 :                                   state_array->ucNumEntries, GFP_KERNEL);
    1486           0 :         if (!rdev->pm.dpm.ps)
    1487           0 :                 return -ENOMEM;
    1488           0 :         power_state_offset = (u8 *)state_array->states;
    1489           0 :         for (i = 0; i < state_array->ucNumEntries; i++) {
    1490             :                 u8 *idx;
    1491           0 :                 power_state = (union pplib_power_state *)power_state_offset;
    1492           0 :                 non_clock_array_index = power_state->v2.nonClockInfoIndex;
    1493             :                 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
    1494           0 :                         &non_clock_info_array->nonClockInfo[non_clock_array_index];
    1495           0 :                 if (!rdev->pm.power_state[i].clock_info)
    1496           0 :                         return -EINVAL;
    1497           0 :                 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
    1498           0 :                 if (ps == NULL) {
    1499           0 :                         kfree(rdev->pm.dpm.ps);
    1500           0 :                         return -ENOMEM;
    1501             :                 }
    1502           0 :                 rdev->pm.dpm.ps[i].ps_priv = ps;
    1503             :                 k = 0;
    1504           0 :                 idx = (u8 *)&power_state->v2.clockInfoIndex[0];
    1505           0 :                 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
    1506           0 :                         clock_array_index = idx[j];
    1507           0 :                         if (k >= SUMO_MAX_HARDWARE_POWERLEVELS)
    1508             :                                 break;
    1509             : 
    1510           0 :                         clock_info = (union pplib_clock_info *)
    1511           0 :                                 ((u8 *)&clock_info_array->clockInfo[0] +
    1512           0 :                                  (clock_array_index * clock_info_array->ucEntrySize));
    1513           0 :                         sumo_parse_pplib_clock_info(rdev,
    1514           0 :                                                     &rdev->pm.dpm.ps[i], k,
    1515             :                                                     clock_info);
    1516           0 :                         k++;
    1517             :                 }
    1518           0 :                 sumo_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
    1519             :                                                 non_clock_info,
    1520           0 :                                                 non_clock_info_array->ucEntrySize);
    1521           0 :                 power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
    1522           0 :         }
    1523           0 :         rdev->pm.dpm.num_ps = state_array->ucNumEntries;
    1524           0 :         return 0;
    1525           0 : }
    1526             : 
    1527           0 : u32 sumo_convert_vid2_to_vid7(struct radeon_device *rdev,
    1528             :                               struct sumo_vid_mapping_table *vid_mapping_table,
    1529             :                               u32 vid_2bit)
    1530             : {
    1531             :         u32 i;
    1532             : 
    1533           0 :         for (i = 0; i < vid_mapping_table->num_entries; i++) {
    1534           0 :                 if (vid_mapping_table->entries[i].vid_2bit == vid_2bit)
    1535           0 :                         return vid_mapping_table->entries[i].vid_7bit;
    1536             :         }
    1537             : 
    1538           0 :         return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit;
    1539           0 : }
    1540             : 
    1541             : #if 0
    1542             : u32 sumo_convert_vid7_to_vid2(struct radeon_device *rdev,
    1543             :                               struct sumo_vid_mapping_table *vid_mapping_table,
    1544             :                               u32 vid_7bit)
    1545             : {
    1546             :         u32 i;
    1547             : 
    1548             :         for (i = 0; i < vid_mapping_table->num_entries; i++) {
    1549             :                 if (vid_mapping_table->entries[i].vid_7bit == vid_7bit)
    1550             :                         return vid_mapping_table->entries[i].vid_2bit;
    1551             :         }
    1552             : 
    1553             :         return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit;
    1554             : }
    1555             : #endif
    1556             : 
    1557           0 : static u16 sumo_convert_voltage_index_to_value(struct radeon_device *rdev,
    1558             :                                                u32 vid_2bit)
    1559             : {
    1560           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1561           0 :         u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit);
    1562             : 
    1563           0 :         if (vid_7bit > 0x7C)
    1564           0 :                 return 0;
    1565             : 
    1566           0 :         return (15500 - vid_7bit * 125 + 5) / 10;
    1567           0 : }
    1568             : 
    1569           0 : static void sumo_construct_display_voltage_mapping_table(struct radeon_device *rdev,
    1570             :                                                          struct sumo_disp_clock_voltage_mapping_table *disp_clk_voltage_mapping_table,
    1571             :                                                          ATOM_CLK_VOLT_CAPABILITY *table)
    1572             : {
    1573             :         u32 i;
    1574             : 
    1575           0 :         for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) {
    1576           0 :                 if (table[i].ulMaximumSupportedCLK == 0)
    1577             :                         break;
    1578             : 
    1579           0 :                 disp_clk_voltage_mapping_table->display_clock_frequency[i] =
    1580             :                         table[i].ulMaximumSupportedCLK;
    1581             :         }
    1582             : 
    1583           0 :         disp_clk_voltage_mapping_table->num_max_voltage_levels = i;
    1584             : 
    1585           0 :         if (disp_clk_voltage_mapping_table->num_max_voltage_levels == 0) {
    1586           0 :                 disp_clk_voltage_mapping_table->display_clock_frequency[0] = 80000;
    1587           0 :                 disp_clk_voltage_mapping_table->num_max_voltage_levels = 1;
    1588           0 :         }
    1589           0 : }
    1590             : 
    1591           0 : void sumo_construct_sclk_voltage_mapping_table(struct radeon_device *rdev,
    1592             :                                                struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table,
    1593             :                                                ATOM_AVAILABLE_SCLK_LIST *table)
    1594             : {
    1595             :         u32 i;
    1596             :         u32 n = 0;
    1597             :         u32 prev_sclk = 0;
    1598             : 
    1599           0 :         for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
    1600           0 :                 if (table[i].ulSupportedSCLK > prev_sclk) {
    1601           0 :                         sclk_voltage_mapping_table->entries[n].sclk_frequency =
    1602             :                                 table[i].ulSupportedSCLK;
    1603           0 :                         sclk_voltage_mapping_table->entries[n].vid_2bit =
    1604           0 :                                 table[i].usVoltageIndex;
    1605           0 :                         prev_sclk = table[i].ulSupportedSCLK;
    1606           0 :                         n++;
    1607           0 :                 }
    1608             :         }
    1609             : 
    1610           0 :         sclk_voltage_mapping_table->num_max_dpm_entries = n;
    1611           0 : }
    1612             : 
    1613           0 : void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
    1614             :                                       struct sumo_vid_mapping_table *vid_mapping_table,
    1615             :                                       ATOM_AVAILABLE_SCLK_LIST *table)
    1616             : {
    1617             :         u32 i, j;
    1618             : 
    1619           0 :         for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
    1620           0 :                 if (table[i].ulSupportedSCLK != 0) {
    1621           0 :                         vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
    1622           0 :                                 table[i].usVoltageID;
    1623           0 :                         vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
    1624           0 :                                 table[i].usVoltageIndex;
    1625           0 :                 }
    1626             :         }
    1627             : 
    1628           0 :         for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) {
    1629           0 :                 if (vid_mapping_table->entries[i].vid_7bit == 0) {
    1630           0 :                         for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES; j++) {
    1631           0 :                                 if (vid_mapping_table->entries[j].vid_7bit != 0) {
    1632             :                                         vid_mapping_table->entries[i] =
    1633           0 :                                                 vid_mapping_table->entries[j];
    1634           0 :                                         vid_mapping_table->entries[j].vid_7bit = 0;
    1635           0 :                                         break;
    1636             :                                 }
    1637             :                         }
    1638             : 
    1639           0 :                         if (j == SUMO_MAX_NUMBER_VOLTAGES)
    1640             :                                 break;
    1641             :                 }
    1642             :         }
    1643             : 
    1644           0 :         vid_mapping_table->num_entries = i;
    1645           0 : }
    1646             : 
    1647             : union igp_info {
    1648             :         struct _ATOM_INTEGRATED_SYSTEM_INFO info;
    1649             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2;
    1650             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5;
    1651             :         struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6;
    1652             : };
    1653             : 
    1654           0 : static int sumo_parse_sys_info_table(struct radeon_device *rdev)
    1655             : {
    1656           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1657           0 :         struct radeon_mode_info *mode_info = &rdev->mode_info;
    1658             :         int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
    1659             :         union igp_info *igp_info;
    1660           0 :         u8 frev, crev;
    1661           0 :         u16 data_offset;
    1662             :         int i;
    1663             : 
    1664           0 :         if (atom_parse_data_header(mode_info->atom_context, index, NULL,
    1665             :                                    &frev, &crev, &data_offset)) {
    1666           0 :                 igp_info = (union igp_info *)(mode_info->atom_context->bios +
    1667           0 :                                               data_offset);
    1668             : 
    1669           0 :                 if (crev != 6) {
    1670           0 :                         DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev);
    1671           0 :                         return -EINVAL;
    1672             :                 }
    1673           0 :                 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_6.ulBootUpEngineClock);
    1674           0 :                 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_6.ulMinEngineClock);
    1675           0 :                 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_6.ulBootUpUMAClock);
    1676           0 :                 pi->sys_info.bootup_nb_voltage_index =
    1677           0 :                         le16_to_cpu(igp_info->info_6.usBootUpNBVoltage);
    1678           0 :                 if (igp_info->info_6.ucHtcTmpLmt == 0)
    1679           0 :                         pi->sys_info.htc_tmp_lmt = 203;
    1680             :                 else
    1681           0 :                         pi->sys_info.htc_tmp_lmt = igp_info->info_6.ucHtcTmpLmt;
    1682           0 :                 if (igp_info->info_6.ucHtcHystLmt == 0)
    1683           0 :                         pi->sys_info.htc_hyst_lmt = 5;
    1684             :                 else
    1685           0 :                         pi->sys_info.htc_hyst_lmt = igp_info->info_6.ucHtcHystLmt;
    1686           0 :                 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) {
    1687           0 :                         DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n");
    1688           0 :                 }
    1689           0 :                 for (i = 0; i < NUMBER_OF_M3ARB_PARAM_SETS; i++) {
    1690           0 :                         pi->sys_info.csr_m3_arb_cntl_default[i] =
    1691           0 :                                 le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_DEFAULT[i]);
    1692           0 :                         pi->sys_info.csr_m3_arb_cntl_uvd[i] =
    1693           0 :                                 le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_UVD[i]);
    1694           0 :                         pi->sys_info.csr_m3_arb_cntl_fs3d[i] =
    1695           0 :                                 le32_to_cpu(igp_info->info_6.ulCSR_M3_ARB_CNTL_FS3D[i]);
    1696             :                 }
    1697           0 :                 pi->sys_info.sclk_dpm_boost_margin =
    1698           0 :                         le32_to_cpu(igp_info->info_6.SclkDpmBoostMargin);
    1699           0 :                 pi->sys_info.sclk_dpm_throttle_margin =
    1700           0 :                         le32_to_cpu(igp_info->info_6.SclkDpmThrottleMargin);
    1701           0 :                 pi->sys_info.sclk_dpm_tdp_limit_pg =
    1702           0 :                         le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitPG);
    1703           0 :                 pi->sys_info.gnb_tdp_limit = le16_to_cpu(igp_info->info_6.GnbTdpLimit);
    1704           0 :                 pi->sys_info.sclk_dpm_tdp_limit_boost =
    1705           0 :                         le16_to_cpu(igp_info->info_6.SclkDpmTdpLimitBoost);
    1706           0 :                 pi->sys_info.boost_sclk = le32_to_cpu(igp_info->info_6.ulBoostEngineCLock);
    1707           0 :                 pi->sys_info.boost_vid_2bit = igp_info->info_6.ulBoostVid_2bit;
    1708           0 :                 if (igp_info->info_6.EnableBoost)
    1709           0 :                         pi->sys_info.enable_boost = true;
    1710             :                 else
    1711           0 :                         pi->sys_info.enable_boost = false;
    1712           0 :                 sumo_construct_display_voltage_mapping_table(rdev,
    1713           0 :                                                              &pi->sys_info.disp_clk_voltage_mapping_table,
    1714           0 :                                                              igp_info->info_6.sDISPCLK_Voltage);
    1715           0 :                 sumo_construct_sclk_voltage_mapping_table(rdev,
    1716           0 :                                                           &pi->sys_info.sclk_voltage_mapping_table,
    1717           0 :                                                           igp_info->info_6.sAvail_SCLK);
    1718           0 :                 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table,
    1719             :                                                  igp_info->info_6.sAvail_SCLK);
    1720             : 
    1721           0 :         }
    1722           0 :         return 0;
    1723           0 : }
    1724             : 
    1725           0 : static void sumo_construct_boot_and_acpi_state(struct radeon_device *rdev)
    1726             : {
    1727           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1728             : 
    1729           0 :         pi->boot_pl.sclk = pi->sys_info.bootup_sclk;
    1730           0 :         pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index;
    1731           0 :         pi->boot_pl.ds_divider_index = 0;
    1732           0 :         pi->boot_pl.ss_divider_index = 0;
    1733           0 :         pi->boot_pl.allow_gnb_slow = 1;
    1734           0 :         pi->acpi_pl = pi->boot_pl;
    1735           0 :         pi->current_ps.num_levels = 1;
    1736           0 :         pi->current_ps.levels[0] = pi->boot_pl;
    1737           0 : }
    1738             : 
    1739           0 : int sumo_dpm_init(struct radeon_device *rdev)
    1740             : {
    1741             :         struct sumo_power_info *pi;
    1742           0 :         u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT;
    1743             :         int ret;
    1744             : 
    1745           0 :         pi = kzalloc(sizeof(struct sumo_power_info), GFP_KERNEL);
    1746           0 :         if (pi == NULL)
    1747           0 :                 return -ENOMEM;
    1748           0 :         rdev->pm.dpm.priv = pi;
    1749             : 
    1750           0 :         pi->driver_nbps_policy_disable = false;
    1751           0 :         if ((rdev->family == CHIP_PALM) && (hw_rev < 3))
    1752           0 :                 pi->disable_gfx_power_gating_in_uvd = true;
    1753             :         else
    1754           0 :                 pi->disable_gfx_power_gating_in_uvd = false;
    1755           0 :         pi->enable_alt_vddnb = true;
    1756           0 :         pi->enable_sclk_ds = true;
    1757           0 :         pi->enable_dynamic_m3_arbiter = false;
    1758           0 :         pi->enable_dynamic_patch_ps = true;
    1759             :         /* Some PALM chips don't seem to properly ungate gfx when UVD is in use;
    1760             :          * for now just disable gfx PG.
    1761             :          */
    1762           0 :         if (rdev->family == CHIP_PALM)
    1763           0 :                 pi->enable_gfx_power_gating = false;
    1764             :         else
    1765           0 :                 pi->enable_gfx_power_gating = true;
    1766           0 :         pi->enable_gfx_clock_gating = true;
    1767           0 :         pi->enable_mg_clock_gating = true;
    1768           0 :         pi->enable_auto_thermal_throttling = true;
    1769             : 
    1770           0 :         ret = sumo_parse_sys_info_table(rdev);
    1771           0 :         if (ret)
    1772           0 :                 return ret;
    1773             : 
    1774           0 :         sumo_construct_boot_and_acpi_state(rdev);
    1775             : 
    1776           0 :         ret = r600_get_platform_caps(rdev);
    1777           0 :         if (ret)
    1778           0 :                 return ret;
    1779             : 
    1780           0 :         ret = sumo_parse_power_table(rdev);
    1781           0 :         if (ret)
    1782           0 :                 return ret;
    1783             : 
    1784           0 :         pi->pasi = CYPRESS_HASI_DFLT;
    1785           0 :         pi->asi = RV770_ASI_DFLT;
    1786           0 :         pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt;
    1787           0 :         pi->enable_boost = pi->sys_info.enable_boost;
    1788           0 :         pi->enable_dpm = true;
    1789             : 
    1790           0 :         return 0;
    1791           0 : }
    1792             : 
    1793           0 : void sumo_dpm_print_power_state(struct radeon_device *rdev,
    1794             :                                 struct radeon_ps *rps)
    1795             : {
    1796             :         int i;
    1797           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
    1798             : 
    1799           0 :         r600_dpm_print_class_info(rps->class, rps->class2);
    1800           0 :         r600_dpm_print_cap_info(rps->caps);
    1801           0 :         printk("\tuvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
    1802           0 :         for (i = 0; i < ps->num_levels; i++) {
    1803           0 :                 struct sumo_pl *pl = &ps->levels[i];
    1804           0 :                 printk("\t\tpower level %d    sclk: %u vddc: %u\n",
    1805             :                        i, pl->sclk,
    1806             :                        sumo_convert_voltage_index_to_value(rdev, pl->vddc_index));
    1807             :         }
    1808           0 :         r600_dpm_print_ps_status(rdev, rps);
    1809           0 : }
    1810             : 
    1811           0 : void sumo_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
    1812             :                                                       struct seq_file *m)
    1813             : {
    1814           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1815           0 :         struct radeon_ps *rps = &pi->current_rps;
    1816           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
    1817             :         struct sumo_pl *pl;
    1818             :         u32 current_index =
    1819           0 :                 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) >>
    1820             :                 CURR_INDEX_SHIFT;
    1821             : 
    1822           0 :         if (current_index == BOOST_DPM_LEVEL) {
    1823           0 :                 pl = &pi->boost_pl;
    1824           0 :                 seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
    1825           0 :                 seq_printf(m, "power level %d    sclk: %u vddc: %u\n",
    1826           0 :                            current_index, pl->sclk,
    1827           0 :                            sumo_convert_voltage_index_to_value(rdev, pl->vddc_index));
    1828           0 :         } else if (current_index >= ps->num_levels) {
    1829           0 :                 seq_printf(m, "invalid dpm profile %d\n", current_index);
    1830           0 :         } else {
    1831           0 :                 pl = &ps->levels[current_index];
    1832           0 :                 seq_printf(m, "uvd    vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
    1833           0 :                 seq_printf(m, "power level %d    sclk: %u vddc: %u\n",
    1834           0 :                            current_index, pl->sclk,
    1835           0 :                            sumo_convert_voltage_index_to_value(rdev, pl->vddc_index));
    1836             :         }
    1837           0 : }
    1838             : 
    1839           0 : u32 sumo_dpm_get_current_sclk(struct radeon_device *rdev)
    1840             : {
    1841           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1842           0 :         struct radeon_ps *rps = &pi->current_rps;
    1843           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
    1844             :         struct sumo_pl *pl;
    1845             :         u32 current_index =
    1846           0 :                 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURR_INDEX_MASK) >>
    1847             :                 CURR_INDEX_SHIFT;
    1848             : 
    1849           0 :         if (current_index == BOOST_DPM_LEVEL) {
    1850           0 :                 pl = &pi->boost_pl;
    1851           0 :                 return pl->sclk;
    1852           0 :         } else if (current_index >= ps->num_levels) {
    1853           0 :                 return 0;
    1854             :         } else {
    1855           0 :                 pl = &ps->levels[current_index];
    1856           0 :                 return pl->sclk;
    1857             :         }
    1858           0 : }
    1859             : 
    1860           0 : u32 sumo_dpm_get_current_mclk(struct radeon_device *rdev)
    1861             : {
    1862           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1863             : 
    1864           0 :         return pi->sys_info.bootup_uma_clk;
    1865             : }
    1866             : 
    1867           0 : void sumo_dpm_fini(struct radeon_device *rdev)
    1868             : {
    1869             :         int i;
    1870             : 
    1871           0 :         sumo_cleanup_asic(rdev); /* ??? */
    1872             : 
    1873           0 :         for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
    1874           0 :                 kfree(rdev->pm.dpm.ps[i].ps_priv);
    1875             :         }
    1876           0 :         kfree(rdev->pm.dpm.ps);
    1877           0 :         kfree(rdev->pm.dpm.priv);
    1878           0 : }
    1879             : 
    1880           0 : u32 sumo_dpm_get_sclk(struct radeon_device *rdev, bool low)
    1881             : {
    1882           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1883           0 :         struct sumo_ps *requested_state = sumo_get_ps(&pi->requested_rps);
    1884             : 
    1885           0 :         if (low)
    1886           0 :                 return requested_state->levels[0].sclk;
    1887             :         else
    1888           0 :                 return requested_state->levels[requested_state->num_levels - 1].sclk;
    1889           0 : }
    1890             : 
    1891           0 : u32 sumo_dpm_get_mclk(struct radeon_device *rdev, bool low)
    1892             : {
    1893           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1894             : 
    1895           0 :         return pi->sys_info.bootup_uma_clk;
    1896             : }
    1897             : 
    1898           0 : int sumo_dpm_force_performance_level(struct radeon_device *rdev,
    1899             :                                      enum radeon_dpm_forced_level level)
    1900             : {
    1901           0 :         struct sumo_power_info *pi = sumo_get_pi(rdev);
    1902           0 :         struct radeon_ps *rps = &pi->current_rps;
    1903           0 :         struct sumo_ps *ps = sumo_get_ps(rps);
    1904             :         int i;
    1905             : 
    1906           0 :         if (ps->num_levels <= 1)
    1907           0 :                 return 0;
    1908             : 
    1909           0 :         if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
    1910           0 :                 if (pi->enable_boost)
    1911           0 :                         sumo_enable_boost(rdev, rps, false);
    1912           0 :                 sumo_power_level_enable(rdev, ps->num_levels - 1, true);
    1913           0 :                 sumo_set_forced_level(rdev, ps->num_levels - 1);
    1914           0 :                 sumo_set_forced_mode_enabled(rdev);
    1915           0 :                 for (i = 0; i < ps->num_levels - 1; i++) {
    1916           0 :                         sumo_power_level_enable(rdev, i, false);
    1917             :                 }
    1918           0 :                 sumo_set_forced_mode(rdev, false);
    1919           0 :                 sumo_set_forced_mode_enabled(rdev);
    1920           0 :                 sumo_set_forced_mode(rdev, false);
    1921           0 :         } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
    1922           0 :                 if (pi->enable_boost)
    1923           0 :                         sumo_enable_boost(rdev, rps, false);
    1924           0 :                 sumo_power_level_enable(rdev, 0, true);
    1925           0 :                 sumo_set_forced_level(rdev, 0);
    1926           0 :                 sumo_set_forced_mode_enabled(rdev);
    1927           0 :                 for (i = 1; i < ps->num_levels; i++) {
    1928           0 :                         sumo_power_level_enable(rdev, i, false);
    1929             :                 }
    1930           0 :                 sumo_set_forced_mode(rdev, false);
    1931           0 :                 sumo_set_forced_mode_enabled(rdev);
    1932           0 :                 sumo_set_forced_mode(rdev, false);
    1933           0 :         } else {
    1934           0 :                 for (i = 0; i < ps->num_levels; i++) {
    1935           0 :                         sumo_power_level_enable(rdev, i, true);
    1936             :                 }
    1937           0 :                 if (pi->enable_boost)
    1938           0 :                         sumo_enable_boost(rdev, rps, true);
    1939             :         }
    1940             : 
    1941           0 :         rdev->pm.dpm.forced_level = level;
    1942             : 
    1943           0 :         return 0;
    1944           0 : }

Generated by: LCOV version 1.13