rcu: Remove rcu_user_hooks_switch
[cascardo/linux.git] / drivers / gpu / drm / amd / powerplay / hwmgr / cz_clockpowergating.c
1 /*
2  * Copyright 2015 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 "hwmgr.h"
25 #include "cz_clockpowergating.h"
26 #include "cz_ppsmc.h"
27
28 /* PhyID -> Status Mapping in DDI_PHY_GEN_STATUS
29     0    GFX0L (3:0),                  (27:24),
30     1    GFX0H (7:4),                  (31:28),
31     2    GFX1L (3:0),                  (19:16),
32     3    GFX1H (7:4),                  (23:20),
33     4    DDIL   (3:0),                   (11: 8),
34     5    DDIH  (7:4),                   (15:12),
35     6    DDI2L (3:0),                   ( 3: 0),
36     7    DDI2H (7:4),                   ( 7: 4),
37 */
38 #define DDI_PHY_GEN_STATUS_VAL(phyID)   (1 << ((3 - ((phyID & 0x07)/2))*8 + (phyID & 0x01)*4))
39 #define IS_PHY_ID_USED_BY_PLL(PhyID)    (((0xF3 & (1 << PhyID)) & 0xFF) ? true : false)
40
41
42 int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating)
43 {
44         int ret = 0;
45
46         switch (block) {
47         case PHM_AsicBlock_UVD_MVC:
48         case PHM_AsicBlock_UVD:
49         case PHM_AsicBlock_UVD_HD:
50         case PHM_AsicBlock_UVD_SD:
51                 if (gating == PHM_ClockGateSetting_StaticOff)
52                         ret = cz_dpm_powerdown_uvd(hwmgr);
53                 else
54                         ret = cz_dpm_powerup_uvd(hwmgr);
55                 break;
56         case PHM_AsicBlock_GFX:
57         default:
58                 break;
59         }
60
61         return ret;
62 }
63
64
65 bool cz_phm_is_safe_for_asic_block(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, enum PHM_AsicBlock block)
66 {
67         return true;
68 }
69
70
71 int cz_phm_enable_disable_gfx_power_gating(struct pp_hwmgr *hwmgr, bool enable)
72 {
73         return 0;
74 }
75
76 int cz_phm_smu_power_up_down_pcie(struct pp_hwmgr *hwmgr, uint32_t target, bool up, uint32_t args)
77 {
78         /* TODO */
79         return 0;
80 }
81
82 int cz_phm_initialize_display_phy_access(struct pp_hwmgr *hwmgr, bool initialize, bool accesshw)
83 {
84         /* TODO */
85         return 0;
86 }
87
88 int cz_phm_get_display_phy_access_info(struct pp_hwmgr *hwmgr)
89 {
90         /* TODO */
91         return 0;
92 }
93
94 int cz_phm_gate_unused_display_phys(struct pp_hwmgr *hwmgr)
95 {
96         /* TODO */
97         return 0;
98 }
99
100 int cz_phm_ungate_all_display_phys(struct pp_hwmgr *hwmgr)
101 {
102         /* TODO */
103         return 0;
104 }
105
106 static int cz_tf_uvd_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result)
107 {
108         return 0;
109 }
110
111 static int cz_tf_vce_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result)
112 {
113         return 0;
114 }
115
116 int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable)
117 {
118         struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
119         uint32_t dpm_features = 0;
120
121         if (enable &&
122                 phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
123                                   PHM_PlatformCaps_UVDDPM)) {
124                 cz_hwmgr->dpm_flags |= DPMFlags_UVD_Enabled;
125                 dpm_features |= UVD_DPM_MASK;
126                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
127                             PPSMC_MSG_EnableAllSmuFeatures, dpm_features);
128         } else {
129                 dpm_features |= UVD_DPM_MASK;
130                 cz_hwmgr->dpm_flags &= ~DPMFlags_UVD_Enabled;
131                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
132                            PPSMC_MSG_DisableAllSmuFeatures, dpm_features);
133         }
134         return 0;
135 }
136
137 int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable)
138 {
139         struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
140         uint32_t dpm_features = 0;
141
142         if (enable && phm_cap_enabled(
143                                 hwmgr->platform_descriptor.platformCaps,
144                                 PHM_PlatformCaps_VCEDPM)) {
145                 cz_hwmgr->dpm_flags |= DPMFlags_VCE_Enabled;
146                 dpm_features |= VCE_DPM_MASK;
147                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
148                             PPSMC_MSG_EnableAllSmuFeatures, dpm_features);
149         } else {
150                 dpm_features |= VCE_DPM_MASK;
151                 cz_hwmgr->dpm_flags &= ~DPMFlags_VCE_Enabled;
152                 smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
153                            PPSMC_MSG_DisableAllSmuFeatures, dpm_features);
154         }
155
156         return 0;
157 }
158
159
160 int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
161 {
162         struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
163
164         if (cz_hwmgr->uvd_power_gated == bgate)
165                 return 0;
166
167         cz_hwmgr->uvd_power_gated = bgate;
168
169         if (bgate) {
170                 cgs_set_clockgating_state(hwmgr->device,
171                                                 AMD_IP_BLOCK_TYPE_UVD,
172                                                 AMD_CG_STATE_UNGATE);
173                 cgs_set_powergating_state(hwmgr->device,
174                                                 AMD_IP_BLOCK_TYPE_UVD,
175                                                 AMD_PG_STATE_GATE);
176                 cz_dpm_update_uvd_dpm(hwmgr, true);
177                 cz_dpm_powerdown_uvd(hwmgr);
178         } else {
179                 cz_dpm_powerup_uvd(hwmgr);
180                 cgs_set_clockgating_state(hwmgr->device,
181                                                 AMD_IP_BLOCK_TYPE_UVD,
182                                                 AMD_PG_STATE_GATE);
183                 cgs_set_powergating_state(hwmgr->device,
184                                                 AMD_IP_BLOCK_TYPE_UVD,
185                                                 AMD_CG_STATE_UNGATE);
186                 cz_dpm_update_uvd_dpm(hwmgr, false);
187         }
188
189         return 0;
190 }
191
192 int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
193 {
194         struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
195
196         if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
197                                         PHM_PlatformCaps_VCEPowerGating)) {
198                 if (cz_hwmgr->vce_power_gated != bgate) {
199                         if (bgate) {
200                                 cgs_set_clockgating_state(
201                                                         hwmgr->device,
202                                                         AMD_IP_BLOCK_TYPE_VCE,
203                                                         AMD_CG_STATE_UNGATE);
204                                 cgs_set_powergating_state(
205                                                         hwmgr->device,
206                                                         AMD_IP_BLOCK_TYPE_VCE,
207                                                         AMD_PG_STATE_GATE);
208                                 cz_enable_disable_vce_dpm(hwmgr, false);
209                         /* TODO: to figure out why vce can't be poweroff*/
210                                 cz_hwmgr->vce_power_gated = true;
211                         } else {
212                                 cz_dpm_powerup_vce(hwmgr);
213                                 cz_hwmgr->vce_power_gated = false;
214                                 cgs_set_clockgating_state(
215                                                         hwmgr->device,
216                                                         AMD_IP_BLOCK_TYPE_VCE,
217                                                         AMD_PG_STATE_GATE);
218                                 cgs_set_powergating_state(
219                                                         hwmgr->device,
220                                                         AMD_IP_BLOCK_TYPE_VCE,
221                                                         AMD_CG_STATE_UNGATE);
222                                 cz_dpm_update_vce_dpm(hwmgr);
223                                 cz_enable_disable_vce_dpm(hwmgr, true);
224                                 return 0;
225                         }
226                 }
227         } else {
228                 cz_dpm_update_vce_dpm(hwmgr);
229                 cz_enable_disable_vce_dpm(hwmgr, true);
230                 return 0;
231         }
232
233         if (!cz_hwmgr->vce_power_gated)
234                 cz_dpm_update_vce_dpm(hwmgr);
235
236         return 0;
237 }
238
239
240 static struct phm_master_table_item cz_enable_clock_power_gatings_list[] = {
241         /*we don't need an exit table here, because there is only D3 cold on Kv*/
242         { phm_cf_want_uvd_power_gating, cz_tf_uvd_power_gating_initialize },
243         { phm_cf_want_vce_power_gating, cz_tf_vce_power_gating_initialize },
244         /* to do { NULL, cz_tf_xdma_power_gating_enable }, */
245         { NULL, NULL }
246 };
247
248 struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = {
249         0,
250         PHM_MasterTableFlag_None,
251         cz_enable_clock_power_gatings_list
252 };