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