drm/amd/powerplay: add gfx off control function
authorHuang Rui <ray.huang@amd.com>
Fri, 2 Mar 2018 07:10:52 +0000 (15:10 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 15 May 2018 18:43:39 +0000 (13:43 -0500)
gfx_off_control is used to be called for sending enabling/disabling gfxoff
message.

Signed-off-by: Huang Rui <ray.huang@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h

index f0727b4f1ebf5f61b90ce2d853b7995a2cbc3788..fde1e5c00a3c2cb015cc37e9fe1b43e48ed40933 100644 (file)
 #define SMU10_DISPCLK_BYPASS_THRESHOLD     10000 /* 100Mhz */
 #define SMC_RAM_END                     0x40000
 
+#define mmPWR_MISC_CNTL_STATUS                                 0x0183
+#define mmPWR_MISC_CNTL_STATUS_BASE_IDX                                0
+#define PWR_MISC_CNTL_STATUS__PWR_GFX_RLC_CGPG_EN__SHIFT       0x0
+#define PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT         0x1
+#define PWR_MISC_CNTL_STATUS__PWR_GFX_RLC_CGPG_EN_MASK         0x00000001L
+#define PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK           0x00000006L
+
 static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic;
 
 
@@ -243,13 +250,31 @@ static int smu10_power_off_asic(struct pp_hwmgr *hwmgr)
        return smu10_reset_cc6_data(hwmgr);
 }
 
+static bool smu10_is_gfx_on(struct pp_hwmgr *hwmgr)
+{
+       uint32_t reg;
+       struct amdgpu_device *adev = hwmgr->adev;
+
+       reg = RREG32_SOC15(PWR, 0, mmPWR_MISC_CNTL_STATUS);
+       if ((reg & PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK) ==
+           (0x2 << PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT))
+               return true;
+
+       return false;
+}
+
 static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr)
 {
        struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 
-       if (smu10_data->gfx_off_controled_by_driver)
+       if (smu10_data->gfx_off_controled_by_driver) {
                smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff);
 
+               /* confirm gfx is back to "on" state */
+               while (!smu10_is_gfx_on(hwmgr))
+                       msleep(1);
+       }
+
        return 0;
 }
 
@@ -273,6 +298,14 @@ static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
        return smu10_enable_gfx_off(hwmgr);
 }
 
+static int smu10_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable)
+{
+       if (enable)
+               return smu10_enable_gfx_off(hwmgr);
+       else
+               return smu10_disable_gfx_off(hwmgr);
+}
+
 static int smu10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
                                struct pp_power_state  *prequest_ps,
                        const struct pp_power_state *pcurrent_ps)
@@ -1060,6 +1093,7 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
        .power_state_set = smu10_set_power_state_tasks,
        .dynamic_state_management_disable = smu10_disable_dpm_tasks,
        .set_mmhub_powergating_by_smu = smu10_set_mmhub_powergating_by_smu,
+       .gfx_off_control = smu10_gfx_off_control,
 };
 
 int smu10_init_function_pointers(struct pp_hwmgr *hwmgr)
index 0d2b3cebd9cfd385a5e3f25a26f427bb300572f8..3d9743f5bb4559189cdf4043ee7c4c2ec6c0c848 100644 (file)
@@ -296,6 +296,7 @@ struct pp_hwmgr_func {
        int (*display_clock_voltage_request)(struct pp_hwmgr *hwmgr,
                        struct pp_display_clock_request *clock);
        int (*get_max_high_clocks)(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks);
+       int (*gfx_off_control)(struct pp_hwmgr *hwmgr, bool enable);
        int (*power_off_asic)(struct pp_hwmgr *hwmgr);
        int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask);
        int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf);