• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
cz_phm_set_asic_block_gating(struct pp_hwmgr * hwmgr,enum PHM_AsicBlock block,enum PHM_ClockGateSetting gating)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 
cz_phm_is_safe_for_asic_block(struct pp_hwmgr * hwmgr,const struct pp_hw_power_state * state,enum PHM_AsicBlock block)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 
cz_phm_enable_disable_gfx_power_gating(struct pp_hwmgr * hwmgr,bool enable)71 int cz_phm_enable_disable_gfx_power_gating(struct pp_hwmgr *hwmgr, bool enable)
72 {
73 	return 0;
74 }
75 
cz_phm_smu_power_up_down_pcie(struct pp_hwmgr * hwmgr,uint32_t target,bool up,uint32_t args)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 
cz_phm_initialize_display_phy_access(struct pp_hwmgr * hwmgr,bool initialize,bool accesshw)82 int cz_phm_initialize_display_phy_access(struct pp_hwmgr *hwmgr, bool initialize, bool accesshw)
83 {
84 	/* TODO */
85 	return 0;
86 }
87 
cz_phm_get_display_phy_access_info(struct pp_hwmgr * hwmgr)88 int cz_phm_get_display_phy_access_info(struct pp_hwmgr *hwmgr)
89 {
90 	/* TODO */
91 	return 0;
92 }
93 
cz_phm_gate_unused_display_phys(struct pp_hwmgr * hwmgr)94 int cz_phm_gate_unused_display_phys(struct pp_hwmgr *hwmgr)
95 {
96 	/* TODO */
97 	return 0;
98 }
99 
cz_phm_ungate_all_display_phys(struct pp_hwmgr * hwmgr)100 int cz_phm_ungate_all_display_phys(struct pp_hwmgr *hwmgr)
101 {
102 	/* TODO */
103 	return 0;
104 }
105 
cz_tf_uvd_power_gating_initialize(struct pp_hwmgr * hwmgr,void * pInput,void * pOutput,void * pStorage,int Result)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 
cz_tf_vce_power_gating_initialize(struct pp_hwmgr * hwmgr,void * pInput,void * pOutput,void * pStorage,int Result)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 
cz_enable_disable_uvd_dpm(struct pp_hwmgr * hwmgr,bool enable)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 
cz_enable_disable_vce_dpm(struct pp_hwmgr * hwmgr,bool enable)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 
cz_dpm_powergate_uvd(struct pp_hwmgr * hwmgr,bool bgate)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_powergating_state(hwmgr->device,
181 						AMD_IP_BLOCK_TYPE_UVD,
182 						AMD_CG_STATE_UNGATE);
183 		cgs_set_clockgating_state(hwmgr->device,
184 						AMD_IP_BLOCK_TYPE_UVD,
185 						AMD_PG_STATE_GATE);
186 		cz_dpm_update_uvd_dpm(hwmgr, false);
187 	}
188 
189 	return 0;
190 }
191 
cz_dpm_powergate_vce(struct pp_hwmgr * hwmgr,bool bgate)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_GATE);
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 				cz_dpm_powerdown_vce(hwmgr);
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_powergating_state(
215 							hwmgr->device,
216 							AMD_IP_BLOCK_TYPE_VCE,
217 							AMD_CG_STATE_UNGATE);
218 				cgs_set_clockgating_state(
219 							hwmgr->device,
220 							AMD_IP_BLOCK_TYPE_VCE,
221 							AMD_PG_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_hwmgr->vce_power_gated = bgate;
229 		cz_dpm_update_vce_dpm(hwmgr);
230 		cz_enable_disable_vce_dpm(hwmgr, !bgate);
231 		return 0;
232 	}
233 
234 	if (!cz_hwmgr->vce_power_gated)
235 		cz_dpm_update_vce_dpm(hwmgr);
236 
237 	return 0;
238 }
239 
240 
241 static const struct phm_master_table_item cz_enable_clock_power_gatings_list[] = {
242 	/*we don't need an exit table here, because there is only D3 cold on Kv*/
243 	{ phm_cf_want_uvd_power_gating, cz_tf_uvd_power_gating_initialize },
244 	{ phm_cf_want_vce_power_gating, cz_tf_vce_power_gating_initialize },
245 	/* to do { NULL, cz_tf_xdma_power_gating_enable }, */
246 	{ NULL, NULL }
247 };
248 
249 const struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = {
250 	0,
251 	PHM_MasterTableFlag_None,
252 	cz_enable_clock_power_gatings_list
253 };
254