1 /* 2 * Copyright 2016 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 "smu7_hwmgr.h" 25 #include "smu7_clockpowergating.h" 26 #include "smu7_common.h" 27 28 static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) 29 { 30 return smum_send_msg_to_smc(hwmgr, enable ? 31 PPSMC_MSG_UVDDPM_Enable : 32 PPSMC_MSG_UVDDPM_Disable); 33 } 34 35 static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) 36 { 37 return smum_send_msg_to_smc(hwmgr, enable ? 38 PPSMC_MSG_VCEDPM_Enable : 39 PPSMC_MSG_VCEDPM_Disable); 40 } 41 42 static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) 43 { 44 if (!bgate) 45 smum_update_smc_table(hwmgr, SMU_UVD_TABLE); 46 return smu7_enable_disable_uvd_dpm(hwmgr, !bgate); 47 } 48 49 static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate) 50 { 51 if (!bgate) 52 smum_update_smc_table(hwmgr, SMU_VCE_TABLE); 53 return smu7_enable_disable_vce_dpm(hwmgr, !bgate); 54 } 55 56 int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr) 57 { 58 if (phm_cf_want_uvd_power_gating(hwmgr)) 59 return smum_send_msg_to_smc(hwmgr, 60 PPSMC_MSG_UVDPowerOFF); 61 return 0; 62 } 63 64 static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) 65 { 66 if (phm_cf_want_uvd_power_gating(hwmgr)) { 67 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 68 PHM_PlatformCaps_UVDDynamicPowerGating)) { 69 return smum_send_msg_to_smc_with_parameter(hwmgr, 70 PPSMC_MSG_UVDPowerON, 1); 71 } else { 72 return smum_send_msg_to_smc_with_parameter(hwmgr, 73 PPSMC_MSG_UVDPowerON, 0); 74 } 75 } 76 77 return 0; 78 } 79 80 static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) 81 { 82 if (phm_cf_want_vce_power_gating(hwmgr)) 83 return smum_send_msg_to_smc(hwmgr, 84 PPSMC_MSG_VCEPowerOFF); 85 return 0; 86 } 87 88 static int smu7_powerup_vce(struct pp_hwmgr *hwmgr) 89 { 90 if (phm_cf_want_vce_power_gating(hwmgr)) 91 return smum_send_msg_to_smc(hwmgr, 92 PPSMC_MSG_VCEPowerON); 93 return 0; 94 } 95 96 int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr) 97 { 98 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 99 100 data->uvd_power_gated = false; 101 data->vce_power_gated = false; 102 103 smu7_powerup_uvd(hwmgr); 104 smu7_powerup_vce(hwmgr); 105 106 return 0; 107 } 108 109 void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) 110 { 111 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 112 113 data->uvd_power_gated = bgate; 114 115 if (bgate) { 116 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 117 AMD_IP_BLOCK_TYPE_UVD, 118 AMD_PG_STATE_GATE); 119 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 120 AMD_IP_BLOCK_TYPE_UVD, 121 AMD_CG_STATE_GATE); 122 smu7_update_uvd_dpm(hwmgr, true); 123 smu7_powerdown_uvd(hwmgr); 124 } else { 125 smu7_powerup_uvd(hwmgr); 126 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 127 AMD_IP_BLOCK_TYPE_UVD, 128 AMD_CG_STATE_UNGATE); 129 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 130 AMD_IP_BLOCK_TYPE_UVD, 131 AMD_PG_STATE_UNGATE); 132 smu7_update_uvd_dpm(hwmgr, false); 133 } 134 135 } 136 137 void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) 138 { 139 struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); 140 141 data->vce_power_gated = bgate; 142 143 if (bgate) { 144 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 145 AMD_IP_BLOCK_TYPE_VCE, 146 AMD_PG_STATE_GATE); 147 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 148 AMD_IP_BLOCK_TYPE_VCE, 149 AMD_CG_STATE_GATE); 150 smu7_update_vce_dpm(hwmgr, true); 151 smu7_powerdown_vce(hwmgr); 152 } else { 153 smu7_powerup_vce(hwmgr); 154 amdgpu_device_ip_set_clockgating_state(hwmgr->adev, 155 AMD_IP_BLOCK_TYPE_VCE, 156 AMD_CG_STATE_UNGATE); 157 amdgpu_device_ip_set_powergating_state(hwmgr->adev, 158 AMD_IP_BLOCK_TYPE_VCE, 159 AMD_PG_STATE_UNGATE); 160 smu7_update_vce_dpm(hwmgr, false); 161 } 162 } 163 164 int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, 165 const uint32_t *msg_id) 166 { 167 PPSMC_Msg msg; 168 uint32_t value; 169 170 if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU)) 171 return 0; 172 173 switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) { 174 case PP_GROUP_GFX: 175 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { 176 case PP_BLOCK_GFX_CG: 177 if (PP_STATE_SUPPORT_CG & *msg_id) { 178 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? 179 PPSMC_MSG_EnableClockGatingFeature : 180 PPSMC_MSG_DisableClockGatingFeature; 181 value = CG_GFX_CGCG_MASK; 182 183 if (smum_send_msg_to_smc_with_parameter( 184 hwmgr, msg, value)) 185 return -EINVAL; 186 } 187 if (PP_STATE_SUPPORT_LS & *msg_id) { 188 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS 189 ? PPSMC_MSG_EnableClockGatingFeature 190 : PPSMC_MSG_DisableClockGatingFeature; 191 value = CG_GFX_CGLS_MASK; 192 193 if (smum_send_msg_to_smc_with_parameter( 194 hwmgr, msg, value)) 195 return -EINVAL; 196 } 197 break; 198 199 case PP_BLOCK_GFX_3D: 200 if (PP_STATE_SUPPORT_CG & *msg_id) { 201 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? 202 PPSMC_MSG_EnableClockGatingFeature : 203 PPSMC_MSG_DisableClockGatingFeature; 204 value = CG_GFX_3DCG_MASK; 205 206 if (smum_send_msg_to_smc_with_parameter( 207 hwmgr, msg, value)) 208 return -EINVAL; 209 } 210 211 if (PP_STATE_SUPPORT_LS & *msg_id) { 212 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 213 PPSMC_MSG_EnableClockGatingFeature : 214 PPSMC_MSG_DisableClockGatingFeature; 215 value = CG_GFX_3DLS_MASK; 216 217 if (smum_send_msg_to_smc_with_parameter( 218 hwmgr, msg, value)) 219 return -EINVAL; 220 } 221 break; 222 223 case PP_BLOCK_GFX_RLC: 224 if (PP_STATE_SUPPORT_LS & *msg_id) { 225 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 226 PPSMC_MSG_EnableClockGatingFeature : 227 PPSMC_MSG_DisableClockGatingFeature; 228 value = CG_GFX_RLC_LS_MASK; 229 230 if (smum_send_msg_to_smc_with_parameter( 231 hwmgr, msg, value)) 232 return -EINVAL; 233 } 234 break; 235 236 case PP_BLOCK_GFX_CP: 237 if (PP_STATE_SUPPORT_LS & *msg_id) { 238 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 239 PPSMC_MSG_EnableClockGatingFeature : 240 PPSMC_MSG_DisableClockGatingFeature; 241 value = CG_GFX_CP_LS_MASK; 242 243 if (smum_send_msg_to_smc_with_parameter( 244 hwmgr, msg, value)) 245 return -EINVAL; 246 } 247 break; 248 249 case PP_BLOCK_GFX_MG: 250 if (PP_STATE_SUPPORT_CG & *msg_id) { 251 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? 252 PPSMC_MSG_EnableClockGatingFeature : 253 PPSMC_MSG_DisableClockGatingFeature; 254 value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK | 255 CG_GFX_OTHERS_MGCG_MASK); 256 257 if (smum_send_msg_to_smc_with_parameter( 258 hwmgr, msg, value)) 259 return -EINVAL; 260 } 261 break; 262 263 default: 264 return -EINVAL; 265 } 266 break; 267 268 case PP_GROUP_SYS: 269 switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { 270 case PP_BLOCK_SYS_BIF: 271 if (PP_STATE_SUPPORT_CG & *msg_id) { 272 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ? 273 PPSMC_MSG_EnableClockGatingFeature : 274 PPSMC_MSG_DisableClockGatingFeature; 275 value = CG_SYS_BIF_MGCG_MASK; 276 277 if (smum_send_msg_to_smc_with_parameter( 278 hwmgr, msg, value)) 279 return -EINVAL; 280 } 281 if (PP_STATE_SUPPORT_LS & *msg_id) { 282 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 283 PPSMC_MSG_EnableClockGatingFeature : 284 PPSMC_MSG_DisableClockGatingFeature; 285 value = CG_SYS_BIF_MGLS_MASK; 286 287 if (smum_send_msg_to_smc_with_parameter( 288 hwmgr, msg, value)) 289 return -EINVAL; 290 } 291 break; 292 293 case PP_BLOCK_SYS_MC: 294 if (PP_STATE_SUPPORT_CG & *msg_id) { 295 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? 296 PPSMC_MSG_EnableClockGatingFeature : 297 PPSMC_MSG_DisableClockGatingFeature; 298 value = CG_SYS_MC_MGCG_MASK; 299 300 if (smum_send_msg_to_smc_with_parameter( 301 hwmgr, msg, value)) 302 return -EINVAL; 303 } 304 305 if (PP_STATE_SUPPORT_LS & *msg_id) { 306 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 307 PPSMC_MSG_EnableClockGatingFeature : 308 PPSMC_MSG_DisableClockGatingFeature; 309 value = CG_SYS_MC_MGLS_MASK; 310 311 if (smum_send_msg_to_smc_with_parameter( 312 hwmgr, msg, value)) 313 return -EINVAL; 314 } 315 break; 316 317 case PP_BLOCK_SYS_DRM: 318 if (PP_STATE_SUPPORT_CG & *msg_id) { 319 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ? 320 PPSMC_MSG_EnableClockGatingFeature : 321 PPSMC_MSG_DisableClockGatingFeature; 322 value = CG_SYS_DRM_MGCG_MASK; 323 324 if (smum_send_msg_to_smc_with_parameter( 325 hwmgr, msg, value)) 326 return -EINVAL; 327 } 328 if (PP_STATE_SUPPORT_LS & *msg_id) { 329 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 330 PPSMC_MSG_EnableClockGatingFeature : 331 PPSMC_MSG_DisableClockGatingFeature; 332 value = CG_SYS_DRM_MGLS_MASK; 333 334 if (smum_send_msg_to_smc_with_parameter( 335 hwmgr, msg, value)) 336 return -EINVAL; 337 } 338 break; 339 340 case PP_BLOCK_SYS_HDP: 341 if (PP_STATE_SUPPORT_CG & *msg_id) { 342 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? 343 PPSMC_MSG_EnableClockGatingFeature : 344 PPSMC_MSG_DisableClockGatingFeature; 345 value = CG_SYS_HDP_MGCG_MASK; 346 347 if (smum_send_msg_to_smc_with_parameter( 348 hwmgr, msg, value)) 349 return -EINVAL; 350 } 351 352 if (PP_STATE_SUPPORT_LS & *msg_id) { 353 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 354 PPSMC_MSG_EnableClockGatingFeature : 355 PPSMC_MSG_DisableClockGatingFeature; 356 value = CG_SYS_HDP_MGLS_MASK; 357 358 if (smum_send_msg_to_smc_with_parameter( 359 hwmgr, msg, value)) 360 return -EINVAL; 361 } 362 break; 363 364 case PP_BLOCK_SYS_SDMA: 365 if (PP_STATE_SUPPORT_CG & *msg_id) { 366 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? 367 PPSMC_MSG_EnableClockGatingFeature : 368 PPSMC_MSG_DisableClockGatingFeature; 369 value = CG_SYS_SDMA_MGCG_MASK; 370 371 if (smum_send_msg_to_smc_with_parameter( 372 hwmgr, msg, value)) 373 return -EINVAL; 374 } 375 376 if (PP_STATE_SUPPORT_LS & *msg_id) { 377 msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? 378 PPSMC_MSG_EnableClockGatingFeature : 379 PPSMC_MSG_DisableClockGatingFeature; 380 value = CG_SYS_SDMA_MGLS_MASK; 381 382 if (smum_send_msg_to_smc_with_parameter( 383 hwmgr, msg, value)) 384 return -EINVAL; 385 } 386 break; 387 388 case PP_BLOCK_SYS_ROM: 389 if (PP_STATE_SUPPORT_CG & *msg_id) { 390 msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? 391 PPSMC_MSG_EnableClockGatingFeature : 392 PPSMC_MSG_DisableClockGatingFeature; 393 value = CG_SYS_ROM_MASK; 394 395 if (smum_send_msg_to_smc_with_parameter( 396 hwmgr, msg, value)) 397 return -EINVAL; 398 } 399 break; 400 401 default: 402 return -EINVAL; 403 404 } 405 break; 406 407 default: 408 return -EINVAL; 409 410 } 411 412 return 0; 413 } 414 415 /* This function is for Polaris11 only for now, 416 * Powerplay will only control the static per CU Power Gating. 417 * Dynamic per CU Power Gating will be done in gfx. 418 */ 419 int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable) 420 { 421 struct amdgpu_device *adev = hwmgr->adev; 422 423 if (enable) 424 return smum_send_msg_to_smc_with_parameter(hwmgr, 425 PPSMC_MSG_GFX_CU_PG_ENABLE, 426 adev->gfx.cu_info.number); 427 else 428 return smum_send_msg_to_smc(hwmgr, 429 PPSMC_MSG_GFX_CU_PG_DISABLE); 430 } 431