1 /* 2 * Copyright 2012 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 <drm/drmP.h> 25 #include "radeon.h" 26 #include "radeon_asic.h" 27 #include "trinityd.h" 28 #include "r600_dpm.h" 29 #include "trinity_dpm.h" 30 #include <linux/seq_file.h> 31 32 #define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5 33 #define TRINITY_MINIMUM_ENGINE_CLOCK 800 34 #define SCLK_MIN_DIV_INTV_SHIFT 12 35 #define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000 36 37 #ifndef TRINITY_MGCG_SEQUENCE 38 #define TRINITY_MGCG_SEQUENCE 100 39 40 static const u32 trinity_mgcg_shls_default[] = 41 { 42 /* Register, Value, Mask */ 43 0x0000802c, 0xc0000000, 0xffffffff, 44 0x00003fc4, 0xc0000000, 0xffffffff, 45 0x00005448, 0x00000100, 0xffffffff, 46 0x000055e4, 0x00000100, 0xffffffff, 47 0x0000160c, 0x00000100, 0xffffffff, 48 0x00008984, 0x06000100, 0xffffffff, 49 0x0000c164, 0x00000100, 0xffffffff, 50 0x00008a18, 0x00000100, 0xffffffff, 51 0x0000897c, 0x06000100, 0xffffffff, 52 0x00008b28, 0x00000100, 0xffffffff, 53 0x00009144, 0x00800200, 0xffffffff, 54 0x00009a60, 0x00000100, 0xffffffff, 55 0x00009868, 0x00000100, 0xffffffff, 56 0x00008d58, 0x00000100, 0xffffffff, 57 0x00009510, 0x00000100, 0xffffffff, 58 0x0000949c, 0x00000100, 0xffffffff, 59 0x00009654, 0x00000100, 0xffffffff, 60 0x00009030, 0x00000100, 0xffffffff, 61 0x00009034, 0x00000100, 0xffffffff, 62 0x00009038, 0x00000100, 0xffffffff, 63 0x0000903c, 0x00000100, 0xffffffff, 64 0x00009040, 0x00000100, 0xffffffff, 65 0x0000a200, 0x00000100, 0xffffffff, 66 0x0000a204, 0x00000100, 0xffffffff, 67 0x0000a208, 0x00000100, 0xffffffff, 68 0x0000a20c, 0x00000100, 0xffffffff, 69 0x00009744, 0x00000100, 0xffffffff, 70 0x00003f80, 0x00000100, 0xffffffff, 71 0x0000a210, 0x00000100, 0xffffffff, 72 0x0000a214, 0x00000100, 0xffffffff, 73 0x000004d8, 0x00000100, 0xffffffff, 74 0x00009664, 0x00000100, 0xffffffff, 75 0x00009698, 0x00000100, 0xffffffff, 76 0x000004d4, 0x00000200, 0xffffffff, 77 0x000004d0, 0x00000000, 0xffffffff, 78 0x000030cc, 0x00000104, 0xffffffff, 79 0x0000d0c0, 0x00000100, 0xffffffff, 80 0x0000d8c0, 0x00000100, 0xffffffff, 81 0x0000951c, 0x00010000, 0xffffffff, 82 0x00009160, 0x00030002, 0xffffffff, 83 0x00009164, 0x00050004, 0xffffffff, 84 0x00009168, 0x00070006, 0xffffffff, 85 0x00009178, 0x00070000, 0xffffffff, 86 0x0000917c, 0x00030002, 0xffffffff, 87 0x00009180, 0x00050004, 0xffffffff, 88 0x0000918c, 0x00010006, 0xffffffff, 89 0x00009190, 0x00090008, 0xffffffff, 90 0x00009194, 0x00070000, 0xffffffff, 91 0x00009198, 0x00030002, 0xffffffff, 92 0x0000919c, 0x00050004, 0xffffffff, 93 0x000091a8, 0x00010006, 0xffffffff, 94 0x000091ac, 0x00090008, 0xffffffff, 95 0x000091b0, 0x00070000, 0xffffffff, 96 0x000091b4, 0x00030002, 0xffffffff, 97 0x000091b8, 0x00050004, 0xffffffff, 98 0x000091c4, 0x00010006, 0xffffffff, 99 0x000091c8, 0x00090008, 0xffffffff, 100 0x000091cc, 0x00070000, 0xffffffff, 101 0x000091d0, 0x00030002, 0xffffffff, 102 0x000091d4, 0x00050004, 0xffffffff, 103 0x000091e0, 0x00010006, 0xffffffff, 104 0x000091e4, 0x00090008, 0xffffffff, 105 0x000091e8, 0x00000000, 0xffffffff, 106 0x000091ec, 0x00070000, 0xffffffff, 107 0x000091f0, 0x00030002, 0xffffffff, 108 0x000091f4, 0x00050004, 0xffffffff, 109 0x00009200, 0x00010006, 0xffffffff, 110 0x00009204, 0x00090008, 0xffffffff, 111 0x00009208, 0x00070000, 0xffffffff, 112 0x0000920c, 0x00030002, 0xffffffff, 113 0x00009210, 0x00050004, 0xffffffff, 114 0x0000921c, 0x00010006, 0xffffffff, 115 0x00009220, 0x00090008, 0xffffffff, 116 0x00009294, 0x00000000, 0xffffffff 117 }; 118 119 static const u32 trinity_mgcg_shls_enable[] = 120 { 121 /* Register, Value, Mask */ 122 0x0000802c, 0xc0000000, 0xffffffff, 123 0x000008f8, 0x00000000, 0xffffffff, 124 0x000008fc, 0x00000000, 0x000133FF, 125 0x000008f8, 0x00000001, 0xffffffff, 126 0x000008fc, 0x00000000, 0xE00B03FC, 127 0x00009150, 0x96944200, 0xffffffff 128 }; 129 130 static const u32 trinity_mgcg_shls_disable[] = 131 { 132 /* Register, Value, Mask */ 133 0x0000802c, 0xc0000000, 0xffffffff, 134 0x00009150, 0x00600000, 0xffffffff, 135 0x000008f8, 0x00000000, 0xffffffff, 136 0x000008fc, 0xffffffff, 0x000133FF, 137 0x000008f8, 0x00000001, 0xffffffff, 138 0x000008fc, 0xffffffff, 0xE00B03FC 139 }; 140 #endif 141 142 #ifndef TRINITY_SYSLS_SEQUENCE 143 #define TRINITY_SYSLS_SEQUENCE 100 144 145 static const u32 trinity_sysls_default[] = 146 { 147 /* Register, Value, Mask */ 148 0x000055e8, 0x00000000, 0xffffffff, 149 0x0000d0bc, 0x00000000, 0xffffffff, 150 0x0000d8bc, 0x00000000, 0xffffffff, 151 0x000015c0, 0x000c1401, 0xffffffff, 152 0x0000264c, 0x000c0400, 0xffffffff, 153 0x00002648, 0x000c0400, 0xffffffff, 154 0x00002650, 0x000c0400, 0xffffffff, 155 0x000020b8, 0x000c0400, 0xffffffff, 156 0x000020bc, 0x000c0400, 0xffffffff, 157 0x000020c0, 0x000c0c80, 0xffffffff, 158 0x0000f4a0, 0x000000c0, 0xffffffff, 159 0x0000f4a4, 0x00680fff, 0xffffffff, 160 0x00002f50, 0x00000404, 0xffffffff, 161 0x000004c8, 0x00000001, 0xffffffff, 162 0x0000641c, 0x00000000, 0xffffffff, 163 0x00000c7c, 0x00000000, 0xffffffff, 164 0x00006dfc, 0x00000000, 0xffffffff 165 }; 166 167 static const u32 trinity_sysls_disable[] = 168 { 169 /* Register, Value, Mask */ 170 0x0000d0c0, 0x00000000, 0xffffffff, 171 0x0000d8c0, 0x00000000, 0xffffffff, 172 0x000055e8, 0x00000000, 0xffffffff, 173 0x0000d0bc, 0x00000000, 0xffffffff, 174 0x0000d8bc, 0x00000000, 0xffffffff, 175 0x000015c0, 0x00041401, 0xffffffff, 176 0x0000264c, 0x00040400, 0xffffffff, 177 0x00002648, 0x00040400, 0xffffffff, 178 0x00002650, 0x00040400, 0xffffffff, 179 0x000020b8, 0x00040400, 0xffffffff, 180 0x000020bc, 0x00040400, 0xffffffff, 181 0x000020c0, 0x00040c80, 0xffffffff, 182 0x0000f4a0, 0x000000c0, 0xffffffff, 183 0x0000f4a4, 0x00680000, 0xffffffff, 184 0x00002f50, 0x00000404, 0xffffffff, 185 0x000004c8, 0x00000001, 0xffffffff, 186 0x0000641c, 0x00007ffd, 0xffffffff, 187 0x00000c7c, 0x0000ff00, 0xffffffff, 188 0x00006dfc, 0x0000007f, 0xffffffff 189 }; 190 191 static const u32 trinity_sysls_enable[] = 192 { 193 /* Register, Value, Mask */ 194 0x000055e8, 0x00000001, 0xffffffff, 195 0x0000d0bc, 0x00000100, 0xffffffff, 196 0x0000d8bc, 0x00000100, 0xffffffff, 197 0x000015c0, 0x000c1401, 0xffffffff, 198 0x0000264c, 0x000c0400, 0xffffffff, 199 0x00002648, 0x000c0400, 0xffffffff, 200 0x00002650, 0x000c0400, 0xffffffff, 201 0x000020b8, 0x000c0400, 0xffffffff, 202 0x000020bc, 0x000c0400, 0xffffffff, 203 0x000020c0, 0x000c0c80, 0xffffffff, 204 0x0000f4a0, 0x000000c0, 0xffffffff, 205 0x0000f4a4, 0x00680fff, 0xffffffff, 206 0x00002f50, 0x00000903, 0xffffffff, 207 0x000004c8, 0x00000000, 0xffffffff, 208 0x0000641c, 0x00000000, 0xffffffff, 209 0x00000c7c, 0x00000000, 0xffffffff, 210 0x00006dfc, 0x00000000, 0xffffffff 211 }; 212 #endif 213 214 static const u32 trinity_override_mgpg_sequences[] = 215 { 216 /* Register, Value */ 217 0x00000200, 0xE030032C, 218 0x00000204, 0x00000FFF, 219 0x00000200, 0xE0300058, 220 0x00000204, 0x00030301, 221 0x00000200, 0xE0300054, 222 0x00000204, 0x500010FF, 223 0x00000200, 0xE0300074, 224 0x00000204, 0x00030301, 225 0x00000200, 0xE0300070, 226 0x00000204, 0x500010FF, 227 0x00000200, 0xE0300090, 228 0x00000204, 0x00030301, 229 0x00000200, 0xE030008C, 230 0x00000204, 0x500010FF, 231 0x00000200, 0xE03000AC, 232 0x00000204, 0x00030301, 233 0x00000200, 0xE03000A8, 234 0x00000204, 0x500010FF, 235 0x00000200, 0xE03000C8, 236 0x00000204, 0x00030301, 237 0x00000200, 0xE03000C4, 238 0x00000204, 0x500010FF, 239 0x00000200, 0xE03000E4, 240 0x00000204, 0x00030301, 241 0x00000200, 0xE03000E0, 242 0x00000204, 0x500010FF, 243 0x00000200, 0xE0300100, 244 0x00000204, 0x00030301, 245 0x00000200, 0xE03000FC, 246 0x00000204, 0x500010FF, 247 0x00000200, 0xE0300058, 248 0x00000204, 0x00030303, 249 0x00000200, 0xE0300054, 250 0x00000204, 0x600010FF, 251 0x00000200, 0xE0300074, 252 0x00000204, 0x00030303, 253 0x00000200, 0xE0300070, 254 0x00000204, 0x600010FF, 255 0x00000200, 0xE0300090, 256 0x00000204, 0x00030303, 257 0x00000200, 0xE030008C, 258 0x00000204, 0x600010FF, 259 0x00000200, 0xE03000AC, 260 0x00000204, 0x00030303, 261 0x00000200, 0xE03000A8, 262 0x00000204, 0x600010FF, 263 0x00000200, 0xE03000C8, 264 0x00000204, 0x00030303, 265 0x00000200, 0xE03000C4, 266 0x00000204, 0x600010FF, 267 0x00000200, 0xE03000E4, 268 0x00000204, 0x00030303, 269 0x00000200, 0xE03000E0, 270 0x00000204, 0x600010FF, 271 0x00000200, 0xE0300100, 272 0x00000204, 0x00030303, 273 0x00000200, 0xE03000FC, 274 0x00000204, 0x600010FF, 275 0x00000200, 0xE0300058, 276 0x00000204, 0x00030303, 277 0x00000200, 0xE0300054, 278 0x00000204, 0x700010FF, 279 0x00000200, 0xE0300074, 280 0x00000204, 0x00030303, 281 0x00000200, 0xE0300070, 282 0x00000204, 0x700010FF, 283 0x00000200, 0xE0300090, 284 0x00000204, 0x00030303, 285 0x00000200, 0xE030008C, 286 0x00000204, 0x700010FF, 287 0x00000200, 0xE03000AC, 288 0x00000204, 0x00030303, 289 0x00000200, 0xE03000A8, 290 0x00000204, 0x700010FF, 291 0x00000200, 0xE03000C8, 292 0x00000204, 0x00030303, 293 0x00000200, 0xE03000C4, 294 0x00000204, 0x700010FF, 295 0x00000200, 0xE03000E4, 296 0x00000204, 0x00030303, 297 0x00000200, 0xE03000E0, 298 0x00000204, 0x700010FF, 299 0x00000200, 0xE0300100, 300 0x00000204, 0x00030303, 301 0x00000200, 0xE03000FC, 302 0x00000204, 0x700010FF, 303 0x00000200, 0xE0300058, 304 0x00000204, 0x00010303, 305 0x00000200, 0xE0300054, 306 0x00000204, 0x800010FF, 307 0x00000200, 0xE0300074, 308 0x00000204, 0x00010303, 309 0x00000200, 0xE0300070, 310 0x00000204, 0x800010FF, 311 0x00000200, 0xE0300090, 312 0x00000204, 0x00010303, 313 0x00000200, 0xE030008C, 314 0x00000204, 0x800010FF, 315 0x00000200, 0xE03000AC, 316 0x00000204, 0x00010303, 317 0x00000200, 0xE03000A8, 318 0x00000204, 0x800010FF, 319 0x00000200, 0xE03000C4, 320 0x00000204, 0x800010FF, 321 0x00000200, 0xE03000C8, 322 0x00000204, 0x00010303, 323 0x00000200, 0xE03000E4, 324 0x00000204, 0x00010303, 325 0x00000200, 0xE03000E0, 326 0x00000204, 0x800010FF, 327 0x00000200, 0xE0300100, 328 0x00000204, 0x00010303, 329 0x00000200, 0xE03000FC, 330 0x00000204, 0x800010FF, 331 0x00000200, 0x0001f198, 332 0x00000204, 0x0003ffff, 333 0x00000200, 0x0001f19C, 334 0x00000204, 0x3fffffff, 335 0x00000200, 0xE030032C, 336 0x00000204, 0x00000000, 337 }; 338 339 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev, 340 const u32 *seq, u32 count); 341 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev); 342 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev, 343 struct radeon_ps *new_rps, 344 struct radeon_ps *old_rps); 345 struct trinity_ps *trinity_get_ps(struct radeon_ps *rps); 346 struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev); 347 void trinity_dpm_reset_asic(struct radeon_device *rdev); 348 349 struct trinity_ps *trinity_get_ps(struct radeon_ps *rps) 350 { 351 struct trinity_ps *ps = rps->ps_priv; 352 353 return ps; 354 } 355 356 struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev) 357 { 358 struct trinity_power_info *pi = rdev->pm.dpm.priv; 359 360 return pi; 361 } 362 363 static void trinity_gfx_powergating_initialize(struct radeon_device *rdev) 364 { 365 struct trinity_power_info *pi = trinity_get_pi(rdev); 366 u32 p, u; 367 u32 value; 368 struct atom_clock_dividers dividers; 369 u32 xclk = radeon_get_xclk(rdev); 370 u32 sssd = 1; 371 int ret; 372 u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT; 373 374 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 375 25000, false, ÷rs); 376 if (ret) 377 return; 378 379 value = RREG32_SMC(GFX_POWER_GATING_CNTL); 380 value &= ~(SSSD_MASK | PDS_DIV_MASK); 381 if (sssd) 382 value |= SSSD(1); 383 value |= PDS_DIV(dividers.post_div); 384 WREG32_SMC(GFX_POWER_GATING_CNTL, value); 385 386 r600_calculate_u_and_p(500, xclk, 16, &p, &u); 387 388 WREG32(CG_PG_CTRL, SP(p) | SU(u)); 389 390 WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK); 391 392 /* XXX double check hw_rev */ 393 if (pi->override_dynamic_mgpg && (hw_rev == 0)) 394 trinity_override_dynamic_mg_powergating(rdev); 395 396 } 397 398 #define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF 399 #define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE 400 #define CGTS_SM_CTRL_REG_DISABLE 0x00600000 401 #define CGTS_SM_CTRL_REG_ENABLE 0x96944200 402 403 static void trinity_mg_clockgating_enable(struct radeon_device *rdev, 404 bool enable) 405 { 406 u32 local0; 407 u32 local1; 408 409 if (enable) { 410 local0 = RREG32_CG(CG_CGTT_LOCAL_0); 411 local1 = RREG32_CG(CG_CGTT_LOCAL_1); 412 413 WREG32_CG(CG_CGTT_LOCAL_0, 414 (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 415 WREG32_CG(CG_CGTT_LOCAL_1, 416 (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 417 418 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE); 419 } else { 420 WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE); 421 422 local0 = RREG32_CG(CG_CGTT_LOCAL_0); 423 local1 = RREG32_CG(CG_CGTT_LOCAL_1); 424 425 WREG32_CG(CG_CGTT_LOCAL_0, 426 CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 427 WREG32_CG(CG_CGTT_LOCAL_1, 428 CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 429 } 430 } 431 432 static void trinity_mg_clockgating_initialize(struct radeon_device *rdev) 433 { 434 u32 count; 435 const u32 *seq = NULL; 436 437 seq = &trinity_mgcg_shls_default[0]; 438 count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32)); 439 440 trinity_program_clk_gating_hw_sequence(rdev, seq, count); 441 } 442 443 static void trinity_gfx_clockgating_enable(struct radeon_device *rdev, 444 bool enable) 445 { 446 if (enable) { 447 WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); 448 } else { 449 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); 450 WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON); 451 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON); 452 RREG32(GB_ADDR_CONFIG); 453 } 454 } 455 456 static void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev, 457 const u32 *seq, u32 count) 458 { 459 u32 i, length = count * 3; 460 461 for (i = 0; i < length; i += 3) 462 WREG32_P(seq[i], seq[i+1], ~seq[i+2]); 463 } 464 465 static void trinity_program_override_mgpg_sequences(struct radeon_device *rdev, 466 const u32 *seq, u32 count) 467 { 468 u32 i, length = count * 2; 469 470 for (i = 0; i < length; i += 2) 471 WREG32(seq[i], seq[i+1]); 472 473 } 474 475 static void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev) 476 { 477 u32 count; 478 const u32 *seq = NULL; 479 480 seq = &trinity_override_mgpg_sequences[0]; 481 count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32)); 482 483 trinity_program_override_mgpg_sequences(rdev, seq, count); 484 } 485 486 static void trinity_ls_clockgating_enable(struct radeon_device *rdev, 487 bool enable) 488 { 489 u32 count; 490 const u32 *seq = NULL; 491 492 if (enable) { 493 seq = &trinity_sysls_enable[0]; 494 count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32)); 495 } else { 496 seq = &trinity_sysls_disable[0]; 497 count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32)); 498 } 499 500 trinity_program_clk_gating_hw_sequence(rdev, seq, count); 501 } 502 503 static void trinity_gfx_powergating_enable(struct radeon_device *rdev, 504 bool enable) 505 { 506 if (enable) { 507 if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK) 508 WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01)); 509 510 WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN); 511 } else { 512 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN); 513 RREG32(GB_ADDR_CONFIG); 514 } 515 } 516 517 static void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev, 518 bool enable) 519 { 520 u32 value; 521 522 if (enable) { 523 value = RREG32_SMC(PM_I_CNTL_1); 524 value &= ~DS_PG_CNTL_MASK; 525 value |= DS_PG_CNTL(1); 526 WREG32_SMC(PM_I_CNTL_1, value); 527 528 value = RREG32_SMC(SMU_S_PG_CNTL); 529 value &= ~DS_PG_EN_MASK; 530 value |= DS_PG_EN(1); 531 WREG32_SMC(SMU_S_PG_CNTL, value); 532 } else { 533 value = RREG32_SMC(SMU_S_PG_CNTL); 534 value &= ~DS_PG_EN_MASK; 535 WREG32_SMC(SMU_S_PG_CNTL, value); 536 537 value = RREG32_SMC(PM_I_CNTL_1); 538 value &= ~DS_PG_CNTL_MASK; 539 WREG32_SMC(PM_I_CNTL_1, value); 540 } 541 542 trinity_gfx_dynamic_mgpg_config(rdev); 543 544 } 545 546 static void trinity_enable_clock_power_gating(struct radeon_device *rdev) 547 { 548 struct trinity_power_info *pi = trinity_get_pi(rdev); 549 550 if (pi->enable_gfx_clock_gating) 551 sumo_gfx_clockgating_initialize(rdev); 552 if (pi->enable_mg_clock_gating) 553 trinity_mg_clockgating_initialize(rdev); 554 if (pi->enable_gfx_power_gating) 555 trinity_gfx_powergating_initialize(rdev); 556 if (pi->enable_mg_clock_gating) { 557 trinity_ls_clockgating_enable(rdev, true); 558 trinity_mg_clockgating_enable(rdev, true); 559 } 560 if (pi->enable_gfx_clock_gating) 561 trinity_gfx_clockgating_enable(rdev, true); 562 if (pi->enable_gfx_dynamic_mgpg) 563 trinity_gfx_dynamic_mgpg_enable(rdev, true); 564 if (pi->enable_gfx_power_gating) 565 trinity_gfx_powergating_enable(rdev, true); 566 } 567 568 static void trinity_disable_clock_power_gating(struct radeon_device *rdev) 569 { 570 struct trinity_power_info *pi = trinity_get_pi(rdev); 571 572 if (pi->enable_gfx_power_gating) 573 trinity_gfx_powergating_enable(rdev, false); 574 if (pi->enable_gfx_dynamic_mgpg) 575 trinity_gfx_dynamic_mgpg_enable(rdev, false); 576 if (pi->enable_gfx_clock_gating) 577 trinity_gfx_clockgating_enable(rdev, false); 578 if (pi->enable_mg_clock_gating) { 579 trinity_mg_clockgating_enable(rdev, false); 580 trinity_ls_clockgating_enable(rdev, false); 581 } 582 } 583 584 static void trinity_set_divider_value(struct radeon_device *rdev, 585 u32 index, u32 sclk) 586 { 587 struct atom_clock_dividers dividers; 588 int ret; 589 u32 value; 590 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 591 592 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 593 sclk, false, ÷rs); 594 if (ret) 595 return; 596 597 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 598 value &= ~CLK_DIVIDER_MASK; 599 value |= CLK_DIVIDER(dividers.post_div); 600 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 601 602 ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 603 sclk/2, false, ÷rs); 604 if (ret) 605 return; 606 607 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix); 608 value &= ~PD_SCLK_DIVIDER_MASK; 609 value |= PD_SCLK_DIVIDER(dividers.post_div); 610 WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value); 611 } 612 613 static void trinity_set_ds_dividers(struct radeon_device *rdev, 614 u32 index, u32 divider) 615 { 616 u32 value; 617 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 618 619 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 620 value &= ~DS_DIV_MASK; 621 value |= DS_DIV(divider); 622 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 623 } 624 625 static void trinity_set_ss_dividers(struct radeon_device *rdev, 626 u32 index, u32 divider) 627 { 628 u32 value; 629 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 630 631 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 632 value &= ~DS_SH_DIV_MASK; 633 value |= DS_SH_DIV(divider); 634 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 635 } 636 637 static void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid) 638 { 639 struct trinity_power_info *pi = trinity_get_pi(rdev); 640 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid); 641 u32 value; 642 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 643 644 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 645 value &= ~VID_MASK; 646 value |= VID(vid_7bit); 647 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 648 649 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 650 value &= ~LVRT_MASK; 651 value |= LVRT(0); 652 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 653 } 654 655 static void trinity_set_allos_gnb_slow(struct radeon_device *rdev, 656 u32 index, u32 gnb_slow) 657 { 658 u32 value; 659 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 660 661 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix); 662 value &= ~GNB_SLOW_MASK; 663 value |= GNB_SLOW(gnb_slow); 664 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value); 665 } 666 667 static void trinity_set_force_nbp_state(struct radeon_device *rdev, 668 u32 index, u32 force_nbp_state) 669 { 670 u32 value; 671 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 672 673 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix); 674 value &= ~FORCE_NBPS1_MASK; 675 value |= FORCE_NBPS1(force_nbp_state); 676 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value); 677 } 678 679 static void trinity_set_display_wm(struct radeon_device *rdev, 680 u32 index, u32 wm) 681 { 682 u32 value; 683 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 684 685 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 686 value &= ~DISPLAY_WM_MASK; 687 value |= DISPLAY_WM(wm); 688 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 689 } 690 691 static void trinity_set_vce_wm(struct radeon_device *rdev, 692 u32 index, u32 wm) 693 { 694 u32 value; 695 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 696 697 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 698 value &= ~VCE_WM_MASK; 699 value |= VCE_WM(wm); 700 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 701 } 702 703 static void trinity_set_at(struct radeon_device *rdev, 704 u32 index, u32 at) 705 { 706 u32 value; 707 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 708 709 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix); 710 value &= ~AT_MASK; 711 value |= AT(at); 712 WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value); 713 } 714 715 static void trinity_program_power_level(struct radeon_device *rdev, 716 struct trinity_pl *pl, u32 index) 717 { 718 struct trinity_power_info *pi = trinity_get_pi(rdev); 719 720 if (index >= SUMO_MAX_HARDWARE_POWERLEVELS) 721 return; 722 723 trinity_set_divider_value(rdev, index, pl->sclk); 724 trinity_set_vid(rdev, index, pl->vddc_index); 725 trinity_set_ss_dividers(rdev, index, pl->ss_divider_index); 726 trinity_set_ds_dividers(rdev, index, pl->ds_divider_index); 727 trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow); 728 trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state); 729 trinity_set_display_wm(rdev, index, pl->display_wm); 730 trinity_set_vce_wm(rdev, index, pl->vce_wm); 731 trinity_set_at(rdev, index, pi->at[index]); 732 } 733 734 static void trinity_power_level_enable_disable(struct radeon_device *rdev, 735 u32 index, bool enable) 736 { 737 u32 value; 738 u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 739 740 value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 741 value &= ~STATE_VALID_MASK; 742 if (enable) 743 value |= STATE_VALID(1); 744 WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 745 } 746 747 static bool trinity_dpm_enabled(struct radeon_device *rdev) 748 { 749 if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1)) 750 return true; 751 else 752 return false; 753 } 754 755 static void trinity_start_dpm(struct radeon_device *rdev) 756 { 757 u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL); 758 759 value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK); 760 value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1); 761 WREG32_SMC(SMU_SCLK_DPM_CNTL, value); 762 763 WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); 764 WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN); 765 766 trinity_dpm_config(rdev, true); 767 } 768 769 static void trinity_wait_for_dpm_enabled(struct radeon_device *rdev) 770 { 771 int i; 772 773 for (i = 0; i < rdev->usec_timeout; i++) { 774 if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN) 775 break; 776 udelay(1); 777 } 778 for (i = 0; i < rdev->usec_timeout; i++) { 779 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0) 780 break; 781 udelay(1); 782 } 783 for (i = 0; i < rdev->usec_timeout; i++) { 784 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0) 785 break; 786 udelay(1); 787 } 788 } 789 790 static void trinity_stop_dpm(struct radeon_device *rdev) 791 { 792 u32 sclk_dpm_cntl; 793 794 WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN); 795 796 sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL); 797 sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK); 798 WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl); 799 800 trinity_dpm_config(rdev, false); 801 } 802 803 static void trinity_start_am(struct radeon_device *rdev) 804 { 805 WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT)); 806 } 807 808 static void trinity_reset_am(struct radeon_device *rdev) 809 { 810 WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT, 811 ~(RESET_SCLK_CNT | RESET_BUSY_CNT)); 812 } 813 814 static void trinity_wait_for_level_0(struct radeon_device *rdev) 815 { 816 int i; 817 818 for (i = 0; i < rdev->usec_timeout; i++) { 819 if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0) 820 break; 821 udelay(1); 822 } 823 } 824 825 static void trinity_enable_power_level_0(struct radeon_device *rdev) 826 { 827 trinity_power_level_enable_disable(rdev, 0, true); 828 } 829 830 static void trinity_force_level_0(struct radeon_device *rdev) 831 { 832 trinity_dpm_force_state(rdev, 0); 833 } 834 835 static void trinity_unforce_levels(struct radeon_device *rdev) 836 { 837 trinity_dpm_no_forced_level(rdev); 838 } 839 840 static void trinity_program_power_levels_0_to_n(struct radeon_device *rdev, 841 struct radeon_ps *new_rps, 842 struct radeon_ps *old_rps) 843 { 844 struct trinity_ps *new_ps = trinity_get_ps(new_rps); 845 struct trinity_ps *old_ps = trinity_get_ps(old_rps); 846 u32 i; 847 u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels; 848 849 for (i = 0; i < new_ps->num_levels; i++) { 850 trinity_program_power_level(rdev, &new_ps->levels[i], i); 851 trinity_power_level_enable_disable(rdev, i, true); 852 } 853 854 for (i = new_ps->num_levels; i < n_current_state_levels; i++) 855 trinity_power_level_enable_disable(rdev, i, false); 856 } 857 858 static void trinity_program_bootup_state(struct radeon_device *rdev) 859 { 860 struct trinity_power_info *pi = trinity_get_pi(rdev); 861 u32 i; 862 863 trinity_program_power_level(rdev, &pi->boot_pl, 0); 864 trinity_power_level_enable_disable(rdev, 0, true); 865 866 for (i = 1; i < 8; i++) 867 trinity_power_level_enable_disable(rdev, i, false); 868 } 869 870 static void trinity_setup_uvd_clock_table(struct radeon_device *rdev, 871 struct radeon_ps *rps) 872 { 873 struct trinity_ps *ps = trinity_get_ps(rps); 874 u32 uvdstates = (ps->vclk_low_divider | 875 ps->vclk_high_divider << 8 | 876 ps->dclk_low_divider << 16 | 877 ps->dclk_high_divider << 24); 878 879 WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates); 880 } 881 882 static void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev, 883 u32 interval) 884 { 885 u32 p, u; 886 u32 tp = RREG32_SMC(PM_TP); 887 u32 val; 888 u32 xclk = radeon_get_xclk(rdev); 889 890 r600_calculate_u_and_p(interval, xclk, 16, &p, &u); 891 892 val = (p + tp - 1) / tp; 893 894 WREG32_SMC(SMU_UVD_DPM_CNTL, val); 895 } 896 897 static bool trinity_uvd_clocks_zero(struct radeon_ps *rps) 898 { 899 if ((rps->vclk == 0) && (rps->dclk == 0)) 900 return true; 901 else 902 return false; 903 } 904 905 static bool trinity_uvd_clocks_equal(struct radeon_ps *rps1, 906 struct radeon_ps *rps2) 907 { 908 struct trinity_ps *ps1 = trinity_get_ps(rps1); 909 struct trinity_ps *ps2 = trinity_get_ps(rps2); 910 911 if ((rps1->vclk == rps2->vclk) && 912 (rps1->dclk == rps2->dclk) && 913 (ps1->vclk_low_divider == ps2->vclk_low_divider) && 914 (ps1->vclk_high_divider == ps2->vclk_high_divider) && 915 (ps1->dclk_low_divider == ps2->dclk_low_divider) && 916 (ps1->dclk_high_divider == ps2->dclk_high_divider)) 917 return true; 918 else 919 return false; 920 } 921 922 static void trinity_setup_uvd_clocks(struct radeon_device *rdev, 923 struct radeon_ps *new_rps, 924 struct radeon_ps *old_rps) 925 { 926 struct trinity_power_info *pi = trinity_get_pi(rdev); 927 928 if (pi->enable_gfx_power_gating) { 929 trinity_gfx_powergating_enable(rdev, false); 930 } 931 932 if (pi->uvd_dpm) { 933 if (trinity_uvd_clocks_zero(new_rps) && 934 !trinity_uvd_clocks_zero(old_rps)) { 935 trinity_setup_uvd_dpm_interval(rdev, 0); 936 } else if (!trinity_uvd_clocks_zero(new_rps)) { 937 trinity_setup_uvd_clock_table(rdev, new_rps); 938 939 if (trinity_uvd_clocks_zero(old_rps)) { 940 u32 tmp = RREG32(CG_MISC_REG); 941 tmp &= 0xfffffffd; 942 WREG32(CG_MISC_REG, tmp); 943 944 radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk); 945 946 trinity_setup_uvd_dpm_interval(rdev, 3000); 947 } 948 } 949 trinity_uvd_dpm_config(rdev); 950 } else { 951 if (trinity_uvd_clocks_zero(new_rps) || 952 trinity_uvd_clocks_equal(new_rps, old_rps)) 953 return; 954 955 radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk); 956 } 957 958 if (pi->enable_gfx_power_gating) { 959 trinity_gfx_powergating_enable(rdev, true); 960 } 961 } 962 963 static void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev, 964 struct radeon_ps *new_rps, 965 struct radeon_ps *old_rps) 966 { 967 struct trinity_ps *new_ps = trinity_get_ps(new_rps); 968 struct trinity_ps *current_ps = trinity_get_ps(new_rps); 969 970 if (new_ps->levels[new_ps->num_levels - 1].sclk >= 971 current_ps->levels[current_ps->num_levels - 1].sclk) 972 return; 973 974 trinity_setup_uvd_clocks(rdev, new_rps, old_rps); 975 } 976 977 static void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, 978 struct radeon_ps *new_rps, 979 struct radeon_ps *old_rps) 980 { 981 struct trinity_ps *new_ps = trinity_get_ps(new_rps); 982 struct trinity_ps *current_ps = trinity_get_ps(old_rps); 983 984 if (new_ps->levels[new_ps->num_levels - 1].sclk < 985 current_ps->levels[current_ps->num_levels - 1].sclk) 986 return; 987 988 trinity_setup_uvd_clocks(rdev, new_rps, old_rps); 989 } 990 991 static void trinity_program_ttt(struct radeon_device *rdev) 992 { 993 struct trinity_power_info *pi = trinity_get_pi(rdev); 994 u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT); 995 996 value &= ~(HT_MASK | LT_MASK); 997 value |= HT((pi->thermal_auto_throttling + 49) * 8); 998 value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8); 999 WREG32_SMC(SMU_SCLK_DPM_TTT, value); 1000 } 1001 1002 static void trinity_enable_att(struct radeon_device *rdev) 1003 { 1004 u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL); 1005 1006 value &= ~SCLK_TT_EN_MASK; 1007 value |= SCLK_TT_EN(1); 1008 WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value); 1009 } 1010 1011 static void trinity_program_sclk_dpm(struct radeon_device *rdev) 1012 { 1013 u32 p, u; 1014 u32 tp = RREG32_SMC(PM_TP); 1015 u32 ni; 1016 u32 xclk = radeon_get_xclk(rdev); 1017 u32 value; 1018 1019 r600_calculate_u_and_p(400, xclk, 16, &p, &u); 1020 1021 ni = (p + tp - 1) / tp; 1022 1023 value = RREG32_SMC(PM_I_CNTL_1); 1024 value &= ~SCLK_DPM_MASK; 1025 value |= SCLK_DPM(ni); 1026 WREG32_SMC(PM_I_CNTL_1, value); 1027 } 1028 1029 static int trinity_set_thermal_temperature_range(struct radeon_device *rdev, 1030 int min_temp, int max_temp) 1031 { 1032 int low_temp = 0 * 1000; 1033 int high_temp = 255 * 1000; 1034 1035 if (low_temp < min_temp) 1036 low_temp = min_temp; 1037 if (high_temp > max_temp) 1038 high_temp = max_temp; 1039 if (high_temp < low_temp) { 1040 DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); 1041 return -EINVAL; 1042 } 1043 1044 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK); 1045 WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK); 1046 1047 rdev->pm.dpm.thermal.min_temp = low_temp; 1048 rdev->pm.dpm.thermal.max_temp = high_temp; 1049 1050 return 0; 1051 } 1052 1053 static void trinity_update_current_ps(struct radeon_device *rdev, 1054 struct radeon_ps *rps) 1055 { 1056 struct trinity_ps *new_ps = trinity_get_ps(rps); 1057 struct trinity_power_info *pi = trinity_get_pi(rdev); 1058 1059 pi->current_rps = *rps; 1060 pi->current_ps = *new_ps; 1061 pi->current_rps.ps_priv = &pi->current_ps; 1062 } 1063 1064 static void trinity_update_requested_ps(struct radeon_device *rdev, 1065 struct radeon_ps *rps) 1066 { 1067 struct trinity_ps *new_ps = trinity_get_ps(rps); 1068 struct trinity_power_info *pi = trinity_get_pi(rdev); 1069 1070 pi->requested_rps = *rps; 1071 pi->requested_ps = *new_ps; 1072 pi->requested_rps.ps_priv = &pi->requested_ps; 1073 } 1074 1075 int trinity_dpm_enable(struct radeon_device *rdev) 1076 { 1077 struct trinity_power_info *pi = trinity_get_pi(rdev); 1078 int ret; 1079 1080 trinity_acquire_mutex(rdev); 1081 1082 if (trinity_dpm_enabled(rdev)) { 1083 trinity_release_mutex(rdev); 1084 return -EINVAL; 1085 } 1086 1087 trinity_enable_clock_power_gating(rdev); 1088 trinity_program_bootup_state(rdev); 1089 sumo_program_vc(rdev, 0x00C00033); 1090 trinity_start_am(rdev); 1091 if (pi->enable_auto_thermal_throttling) { 1092 trinity_program_ttt(rdev); 1093 trinity_enable_att(rdev); 1094 } 1095 trinity_program_sclk_dpm(rdev); 1096 trinity_start_dpm(rdev); 1097 trinity_wait_for_dpm_enabled(rdev); 1098 trinity_release_mutex(rdev); 1099 1100 if (rdev->irq.installed && 1101 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 1102 ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 1103 if (ret) { 1104 trinity_release_mutex(rdev); 1105 return ret; 1106 } 1107 rdev->irq.dpm_thermal = true; 1108 radeon_irq_set(rdev); 1109 } 1110 1111 trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 1112 1113 return 0; 1114 } 1115 1116 void trinity_dpm_disable(struct radeon_device *rdev) 1117 { 1118 trinity_acquire_mutex(rdev); 1119 if (!trinity_dpm_enabled(rdev)) { 1120 trinity_release_mutex(rdev); 1121 return; 1122 } 1123 trinity_disable_clock_power_gating(rdev); 1124 sumo_clear_vc(rdev); 1125 trinity_wait_for_level_0(rdev); 1126 trinity_stop_dpm(rdev); 1127 trinity_reset_am(rdev); 1128 trinity_release_mutex(rdev); 1129 1130 if (rdev->irq.installed && 1131 r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 1132 rdev->irq.dpm_thermal = false; 1133 radeon_irq_set(rdev); 1134 } 1135 1136 trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 1137 } 1138 1139 static void trinity_get_min_sclk_divider(struct radeon_device *rdev) 1140 { 1141 struct trinity_power_info *pi = trinity_get_pi(rdev); 1142 1143 pi->min_sclk_did = 1144 (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT; 1145 } 1146 1147 static void trinity_setup_nbp_sim(struct radeon_device *rdev, 1148 struct radeon_ps *rps) 1149 { 1150 struct trinity_power_info *pi = trinity_get_pi(rdev); 1151 struct trinity_ps *new_ps = trinity_get_ps(rps); 1152 u32 nbpsconfig; 1153 1154 if (pi->sys_info.nb_dpm_enable) { 1155 nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG); 1156 nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK); 1157 nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) | 1158 Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) | 1159 DpmXNbPsLo(new_ps->DpmXNbPsLo) | 1160 DpmXNbPsHi(new_ps->DpmXNbPsHi)); 1161 WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig); 1162 } 1163 } 1164 1165 int trinity_dpm_force_performance_level(struct radeon_device *rdev, 1166 enum radeon_dpm_forced_level level) 1167 { 1168 struct trinity_power_info *pi = trinity_get_pi(rdev); 1169 struct radeon_ps *rps = &pi->current_rps; 1170 struct trinity_ps *ps = trinity_get_ps(rps); 1171 int i, ret; 1172 1173 if (ps->num_levels <= 1) 1174 return 0; 1175 1176 if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { 1177 /* not supported by the hw */ 1178 return -EINVAL; 1179 } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { 1180 ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1); 1181 if (ret) 1182 return ret; 1183 } else { 1184 for (i = 0; i < ps->num_levels; i++) { 1185 ret = trinity_dpm_n_levels_disabled(rdev, 0); 1186 if (ret) 1187 return ret; 1188 } 1189 } 1190 1191 rdev->pm.dpm.forced_level = level; 1192 1193 return 0; 1194 } 1195 1196 int trinity_dpm_pre_set_power_state(struct radeon_device *rdev) 1197 { 1198 struct trinity_power_info *pi = trinity_get_pi(rdev); 1199 struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps; 1200 struct radeon_ps *new_ps = &requested_ps; 1201 1202 trinity_update_requested_ps(rdev, new_ps); 1203 1204 trinity_apply_state_adjust_rules(rdev, 1205 &pi->requested_rps, 1206 &pi->current_rps); 1207 1208 return 0; 1209 } 1210 1211 int trinity_dpm_set_power_state(struct radeon_device *rdev) 1212 { 1213 struct trinity_power_info *pi = trinity_get_pi(rdev); 1214 struct radeon_ps *new_ps = &pi->requested_rps; 1215 struct radeon_ps *old_ps = &pi->current_rps; 1216 1217 trinity_acquire_mutex(rdev); 1218 if (pi->enable_dpm) { 1219 trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); 1220 trinity_enable_power_level_0(rdev); 1221 trinity_force_level_0(rdev); 1222 trinity_wait_for_level_0(rdev); 1223 trinity_setup_nbp_sim(rdev, new_ps); 1224 trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps); 1225 trinity_force_level_0(rdev); 1226 trinity_unforce_levels(rdev); 1227 trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 1228 rdev->pm.dpm.forced_level = RADEON_DPM_FORCED_LEVEL_AUTO; 1229 } 1230 trinity_release_mutex(rdev); 1231 1232 return 0; 1233 } 1234 1235 void trinity_dpm_post_set_power_state(struct radeon_device *rdev) 1236 { 1237 struct trinity_power_info *pi = trinity_get_pi(rdev); 1238 struct radeon_ps *new_ps = &pi->requested_rps; 1239 1240 trinity_update_current_ps(rdev, new_ps); 1241 } 1242 1243 void trinity_dpm_setup_asic(struct radeon_device *rdev) 1244 { 1245 trinity_acquire_mutex(rdev); 1246 sumo_program_sstp(rdev); 1247 sumo_take_smu_control(rdev, true); 1248 trinity_get_min_sclk_divider(rdev); 1249 trinity_release_mutex(rdev); 1250 } 1251 1252 void trinity_dpm_reset_asic(struct radeon_device *rdev) 1253 { 1254 struct trinity_power_info *pi = trinity_get_pi(rdev); 1255 1256 trinity_acquire_mutex(rdev); 1257 if (pi->enable_dpm) { 1258 trinity_enable_power_level_0(rdev); 1259 trinity_force_level_0(rdev); 1260 trinity_wait_for_level_0(rdev); 1261 trinity_program_bootup_state(rdev); 1262 trinity_force_level_0(rdev); 1263 trinity_unforce_levels(rdev); 1264 } 1265 trinity_release_mutex(rdev); 1266 } 1267 1268 static u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev, 1269 u32 vid_2bit) 1270 { 1271 struct trinity_power_info *pi = trinity_get_pi(rdev); 1272 u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit); 1273 u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0; 1274 u32 step = (svi_mode == 0) ? 1250 : 625; 1275 u32 delta = vid_7bit * step + 50; 1276 1277 if (delta > 155000) 1278 return 0; 1279 1280 return (155000 - delta) / 100; 1281 } 1282 1283 static void trinity_patch_boot_state(struct radeon_device *rdev, 1284 struct trinity_ps *ps) 1285 { 1286 struct trinity_power_info *pi = trinity_get_pi(rdev); 1287 1288 ps->num_levels = 1; 1289 ps->nbps_flags = 0; 1290 ps->bapm_flags = 0; 1291 ps->levels[0] = pi->boot_pl; 1292 } 1293 1294 static u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk) 1295 { 1296 if (sclk < 20000) 1297 return 1; 1298 return 0; 1299 } 1300 1301 static void trinity_construct_boot_state(struct radeon_device *rdev) 1302 { 1303 struct trinity_power_info *pi = trinity_get_pi(rdev); 1304 1305 pi->boot_pl.sclk = pi->sys_info.bootup_sclk; 1306 pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; 1307 pi->boot_pl.ds_divider_index = 0; 1308 pi->boot_pl.ss_divider_index = 0; 1309 pi->boot_pl.allow_gnb_slow = 1; 1310 pi->boot_pl.force_nbp_state = 0; 1311 pi->boot_pl.display_wm = 0; 1312 pi->boot_pl.vce_wm = 0; 1313 pi->current_ps.num_levels = 1; 1314 pi->current_ps.levels[0] = pi->boot_pl; 1315 } 1316 1317 static u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev, 1318 u32 sclk, u32 min_sclk_in_sr) 1319 { 1320 struct trinity_power_info *pi = trinity_get_pi(rdev); 1321 u32 i; 1322 u32 temp; 1323 u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ? 1324 min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK; 1325 1326 if (sclk < min) 1327 return 0; 1328 1329 if (!pi->enable_sclk_ds) 1330 return 0; 1331 1332 for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { 1333 temp = sclk / sumo_get_sleep_divider_from_id(i); 1334 if (temp >= min || i == 0) 1335 break; 1336 } 1337 1338 return (u8)i; 1339 } 1340 1341 static u32 trinity_get_valid_engine_clock(struct radeon_device *rdev, 1342 u32 lower_limit) 1343 { 1344 struct trinity_power_info *pi = trinity_get_pi(rdev); 1345 u32 i; 1346 1347 for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) { 1348 if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit) 1349 return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency; 1350 } 1351 1352 if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries) 1353 DRM_ERROR("engine clock out of range!"); 1354 1355 return 0; 1356 } 1357 1358 static void trinity_patch_thermal_state(struct radeon_device *rdev, 1359 struct trinity_ps *ps, 1360 struct trinity_ps *current_ps) 1361 { 1362 struct trinity_power_info *pi = trinity_get_pi(rdev); 1363 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 1364 u32 current_vddc; 1365 u32 current_sclk; 1366 u32 current_index = 0; 1367 1368 if (current_ps) { 1369 current_vddc = current_ps->levels[current_index].vddc_index; 1370 current_sclk = current_ps->levels[current_index].sclk; 1371 } else { 1372 current_vddc = pi->boot_pl.vddc_index; 1373 current_sclk = pi->boot_pl.sclk; 1374 } 1375 1376 ps->levels[0].vddc_index = current_vddc; 1377 1378 if (ps->levels[0].sclk > current_sclk) 1379 ps->levels[0].sclk = current_sclk; 1380 1381 ps->levels[0].ds_divider_index = 1382 trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr); 1383 ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index; 1384 ps->levels[0].allow_gnb_slow = 1; 1385 ps->levels[0].force_nbp_state = 0; 1386 ps->levels[0].display_wm = 0; 1387 ps->levels[0].vce_wm = 1388 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk); 1389 } 1390 1391 static u8 trinity_calculate_display_wm(struct radeon_device *rdev, 1392 struct trinity_ps *ps, u32 index) 1393 { 1394 if (ps == NULL || ps->num_levels <= 1) 1395 return 0; 1396 else if (ps->num_levels == 2) { 1397 if (index == 0) 1398 return 0; 1399 else 1400 return 1; 1401 } else { 1402 if (index == 0) 1403 return 0; 1404 else if (ps->levels[index].sclk < 30000) 1405 return 0; 1406 else 1407 return 1; 1408 } 1409 } 1410 1411 static u32 trinity_get_uvd_clock_index(struct radeon_device *rdev, 1412 struct radeon_ps *rps) 1413 { 1414 struct trinity_power_info *pi = trinity_get_pi(rdev); 1415 u32 i = 0; 1416 1417 for (i = 0; i < 4; i++) { 1418 if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) && 1419 (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk)) 1420 break; 1421 } 1422 1423 if (i >= 4) { 1424 DRM_ERROR("UVD clock index not found!\n"); 1425 i = 3; 1426 } 1427 return i; 1428 } 1429 1430 static void trinity_adjust_uvd_state(struct radeon_device *rdev, 1431 struct radeon_ps *rps) 1432 { 1433 struct trinity_ps *ps = trinity_get_ps(rps); 1434 struct trinity_power_info *pi = trinity_get_pi(rdev); 1435 u32 high_index = 0; 1436 u32 low_index = 0; 1437 1438 if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) { 1439 high_index = trinity_get_uvd_clock_index(rdev, rps); 1440 1441 switch(high_index) { 1442 case 3: 1443 case 2: 1444 low_index = 1; 1445 break; 1446 case 1: 1447 case 0: 1448 default: 1449 low_index = 0; 1450 break; 1451 } 1452 1453 ps->vclk_low_divider = 1454 pi->sys_info.uvd_clock_table_entries[high_index].vclk_did; 1455 ps->dclk_low_divider = 1456 pi->sys_info.uvd_clock_table_entries[high_index].dclk_did; 1457 ps->vclk_high_divider = 1458 pi->sys_info.uvd_clock_table_entries[low_index].vclk_did; 1459 ps->dclk_high_divider = 1460 pi->sys_info.uvd_clock_table_entries[low_index].dclk_did; 1461 } 1462 } 1463 1464 1465 1466 static void trinity_apply_state_adjust_rules(struct radeon_device *rdev, 1467 struct radeon_ps *new_rps, 1468 struct radeon_ps *old_rps) 1469 { 1470 struct trinity_ps *ps = trinity_get_ps(new_rps); 1471 struct trinity_ps *current_ps = trinity_get_ps(old_rps); 1472 struct trinity_power_info *pi = trinity_get_pi(rdev); 1473 u32 min_voltage = 0; /* ??? */ 1474 u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */ 1475 u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 1476 u32 i; 1477 bool force_high; 1478 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 1479 1480 if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 1481 return trinity_patch_thermal_state(rdev, ps, current_ps); 1482 1483 trinity_adjust_uvd_state(rdev, new_rps); 1484 1485 for (i = 0; i < ps->num_levels; i++) { 1486 if (ps->levels[i].vddc_index < min_voltage) 1487 ps->levels[i].vddc_index = min_voltage; 1488 1489 if (ps->levels[i].sclk < min_sclk) 1490 ps->levels[i].sclk = 1491 trinity_get_valid_engine_clock(rdev, min_sclk); 1492 1493 ps->levels[i].ds_divider_index = 1494 sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr); 1495 1496 ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index; 1497 1498 ps->levels[i].allow_gnb_slow = 1; 1499 ps->levels[i].force_nbp_state = 0; 1500 ps->levels[i].display_wm = 1501 trinity_calculate_display_wm(rdev, ps, i); 1502 ps->levels[i].vce_wm = 1503 trinity_calculate_vce_wm(rdev, ps->levels[0].sclk); 1504 } 1505 1506 if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) || 1507 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) 1508 ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE; 1509 1510 if (pi->sys_info.nb_dpm_enable) { 1511 ps->Dpm0PgNbPsLo = 0x1; 1512 ps->Dpm0PgNbPsHi = 0x0; 1513 ps->DpmXNbPsLo = 0x2; 1514 ps->DpmXNbPsHi = 0x1; 1515 1516 if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) || 1517 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) { 1518 force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) || 1519 ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) && 1520 (pi->sys_info.uma_channel_number == 1))); 1521 force_high = (num_active_displays >= 3) || force_high; 1522 ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3; 1523 ps->Dpm0PgNbPsHi = 0x1; 1524 ps->DpmXNbPsLo = force_high ? 0x2 : 0x3; 1525 ps->DpmXNbPsHi = 0x2; 1526 ps->levels[ps->num_levels - 1].allow_gnb_slow = 0; 1527 } 1528 } 1529 } 1530 1531 static void trinity_cleanup_asic(struct radeon_device *rdev) 1532 { 1533 sumo_take_smu_control(rdev, false); 1534 } 1535 1536 #if 0 1537 static void trinity_pre_display_configuration_change(struct radeon_device *rdev) 1538 { 1539 struct trinity_power_info *pi = trinity_get_pi(rdev); 1540 1541 if (pi->voltage_drop_in_dce) 1542 trinity_dce_enable_voltage_adjustment(rdev, false); 1543 } 1544 #endif 1545 1546 static void trinity_add_dccac_value(struct radeon_device *rdev) 1547 { 1548 u32 gpu_cac_avrg_cntl_window_size; 1549 u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 1550 u64 disp_clk = rdev->clock.default_dispclk / 100; 1551 u32 dc_cac_value; 1552 1553 gpu_cac_avrg_cntl_window_size = 1554 (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT; 1555 1556 dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >> 1557 (32 - gpu_cac_avrg_cntl_window_size)); 1558 1559 WREG32_SMC(DC_CAC_VALUE, dc_cac_value); 1560 } 1561 1562 void trinity_dpm_display_configuration_changed(struct radeon_device *rdev) 1563 { 1564 struct trinity_power_info *pi = trinity_get_pi(rdev); 1565 1566 if (pi->voltage_drop_in_dce) 1567 trinity_dce_enable_voltage_adjustment(rdev, true); 1568 trinity_add_dccac_value(rdev); 1569 } 1570 1571 union power_info { 1572 struct _ATOM_POWERPLAY_INFO info; 1573 struct _ATOM_POWERPLAY_INFO_V2 info_2; 1574 struct _ATOM_POWERPLAY_INFO_V3 info_3; 1575 struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 1576 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 1577 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 1578 }; 1579 1580 union pplib_clock_info { 1581 struct _ATOM_PPLIB_R600_CLOCK_INFO r600; 1582 struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; 1583 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; 1584 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; 1585 }; 1586 1587 union pplib_power_state { 1588 struct _ATOM_PPLIB_STATE v1; 1589 struct _ATOM_PPLIB_STATE_V2 v2; 1590 }; 1591 1592 static void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev, 1593 struct radeon_ps *rps, 1594 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, 1595 u8 table_rev) 1596 { 1597 struct trinity_ps *ps = trinity_get_ps(rps); 1598 1599 rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); 1600 rps->class = le16_to_cpu(non_clock_info->usClassification); 1601 rps->class2 = le16_to_cpu(non_clock_info->usClassification2); 1602 1603 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { 1604 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); 1605 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); 1606 } else { 1607 rps->vclk = 0; 1608 rps->dclk = 0; 1609 } 1610 1611 if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { 1612 rdev->pm.dpm.boot_ps = rps; 1613 trinity_patch_boot_state(rdev, ps); 1614 } 1615 if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 1616 rdev->pm.dpm.uvd_ps = rps; 1617 } 1618 1619 static void trinity_parse_pplib_clock_info(struct radeon_device *rdev, 1620 struct radeon_ps *rps, int index, 1621 union pplib_clock_info *clock_info) 1622 { 1623 struct trinity_power_info *pi = trinity_get_pi(rdev); 1624 struct trinity_ps *ps = trinity_get_ps(rps); 1625 struct trinity_pl *pl = &ps->levels[index]; 1626 u32 sclk; 1627 1628 sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 1629 sclk |= clock_info->sumo.ucEngineClockHigh << 16; 1630 pl->sclk = sclk; 1631 pl->vddc_index = clock_info->sumo.vddcIndex; 1632 1633 ps->num_levels = index + 1; 1634 1635 if (pi->enable_sclk_ds) { 1636 pl->ds_divider_index = 5; 1637 pl->ss_divider_index = 5; 1638 } 1639 } 1640 1641 static int trinity_parse_power_table(struct radeon_device *rdev) 1642 { 1643 struct radeon_mode_info *mode_info = &rdev->mode_info; 1644 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 1645 union pplib_power_state *power_state; 1646 int i, j, k, non_clock_array_index, clock_array_index; 1647 union pplib_clock_info *clock_info; 1648 struct _StateArray *state_array; 1649 struct _ClockInfoArray *clock_info_array; 1650 struct _NonClockInfoArray *non_clock_info_array; 1651 union power_info *power_info; 1652 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 1653 u16 data_offset; 1654 u8 frev, crev; 1655 u8 *power_state_offset; 1656 struct sumo_ps *ps; 1657 1658 if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 1659 &frev, &crev, &data_offset)) 1660 return -EINVAL; 1661 power_info = (union power_info *)((uint8_t*)mode_info->atom_context->bios + data_offset); 1662 1663 state_array = (struct _StateArray *) 1664 ((uint8_t*)mode_info->atom_context->bios + data_offset + 1665 le16_to_cpu(power_info->pplib.usStateArrayOffset)); 1666 clock_info_array = (struct _ClockInfoArray *) 1667 ((uint8_t*)mode_info->atom_context->bios + data_offset + 1668 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); 1669 non_clock_info_array = (struct _NonClockInfoArray *) 1670 ((uint8_t*)mode_info->atom_context->bios + data_offset + 1671 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); 1672 1673 rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) * 1674 state_array->ucNumEntries, GFP_KERNEL); 1675 if (!rdev->pm.dpm.ps) 1676 return -ENOMEM; 1677 power_state_offset = (u8 *)state_array->states; 1678 rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); 1679 rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); 1680 rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); 1681 for (i = 0; i < state_array->ucNumEntries; i++) { 1682 power_state = (union pplib_power_state *)power_state_offset; 1683 non_clock_array_index = power_state->v2.nonClockInfoIndex; 1684 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 1685 &non_clock_info_array->nonClockInfo[non_clock_array_index]; 1686 if (!rdev->pm.power_state[i].clock_info) 1687 return -EINVAL; 1688 ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL); 1689 if (ps == NULL) { 1690 kfree(rdev->pm.dpm.ps); 1691 return -ENOMEM; 1692 } 1693 rdev->pm.dpm.ps[i].ps_priv = ps; 1694 k = 0; 1695 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { 1696 clock_array_index = power_state->v2.clockInfoIndex[j]; 1697 if (clock_array_index >= clock_info_array->ucNumEntries) 1698 continue; 1699 if (k >= SUMO_MAX_HARDWARE_POWERLEVELS) 1700 break; 1701 clock_info = (union pplib_clock_info *) 1702 &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; 1703 trinity_parse_pplib_clock_info(rdev, 1704 &rdev->pm.dpm.ps[i], k, 1705 clock_info); 1706 k++; 1707 } 1708 trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], 1709 non_clock_info, 1710 non_clock_info_array->ucEntrySize); 1711 power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 1712 } 1713 rdev->pm.dpm.num_ps = state_array->ucNumEntries; 1714 return 0; 1715 } 1716 1717 union igp_info { 1718 struct _ATOM_INTEGRATED_SYSTEM_INFO info; 1719 struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; 1720 struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; 1721 struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; 1722 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; 1723 }; 1724 1725 static u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did) 1726 { 1727 struct trinity_power_info *pi = trinity_get_pi(rdev); 1728 u32 divider; 1729 1730 if (did >= 8 && did <= 0x3f) 1731 divider = did * 25; 1732 else if (did > 0x3f && did <= 0x5f) 1733 divider = (did - 64) * 50 + 1600; 1734 else if (did > 0x5f && did <= 0x7e) 1735 divider = (did - 96) * 100 + 3200; 1736 else if (did == 0x7f) 1737 divider = 128 * 100; 1738 else 1739 return 10000; 1740 1741 return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider; 1742 } 1743 1744 static int trinity_parse_sys_info_table(struct radeon_device *rdev) 1745 { 1746 struct trinity_power_info *pi = trinity_get_pi(rdev); 1747 struct radeon_mode_info *mode_info = &rdev->mode_info; 1748 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 1749 union igp_info *igp_info; 1750 u8 frev, crev; 1751 u16 data_offset; 1752 int i; 1753 1754 if (atom_parse_data_header(mode_info->atom_context, index, NULL, 1755 &frev, &crev, &data_offset)) { 1756 igp_info = (union igp_info *)((uint8_t*)mode_info->atom_context->bios + 1757 data_offset); 1758 1759 if (crev != 7) { 1760 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 1761 return -EINVAL; 1762 } 1763 pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock); 1764 pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock); 1765 pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock); 1766 pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq); 1767 pi->sys_info.bootup_nb_voltage_index = 1768 le16_to_cpu(igp_info->info_7.usBootUpNBVoltage); 1769 if (igp_info->info_7.ucHtcTmpLmt == 0) 1770 pi->sys_info.htc_tmp_lmt = 203; 1771 else 1772 pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt; 1773 if (igp_info->info_7.ucHtcHystLmt == 0) 1774 pi->sys_info.htc_hyst_lmt = 5; 1775 else 1776 pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt; 1777 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { 1778 DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); 1779 } 1780 1781 if (pi->enable_nbps_policy) 1782 pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable; 1783 else 1784 pi->sys_info.nb_dpm_enable = 0; 1785 1786 for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) { 1787 pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]); 1788 pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]); 1789 } 1790 1791 pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage); 1792 pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage); 1793 pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage); 1794 pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage); 1795 1796 if (!pi->sys_info.nb_dpm_enable) { 1797 for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) { 1798 pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0]; 1799 pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0]; 1800 pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0]; 1801 } 1802 } 1803 1804 pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber; 1805 1806 sumo_construct_sclk_voltage_mapping_table(rdev, 1807 &pi->sys_info.sclk_voltage_mapping_table, 1808 igp_info->info_7.sAvail_SCLK); 1809 sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table, 1810 igp_info->info_7.sAvail_SCLK); 1811 1812 pi->sys_info.uvd_clock_table_entries[0].vclk_did = 1813 igp_info->info_7.ucDPMState0VclkFid; 1814 pi->sys_info.uvd_clock_table_entries[1].vclk_did = 1815 igp_info->info_7.ucDPMState1VclkFid; 1816 pi->sys_info.uvd_clock_table_entries[2].vclk_did = 1817 igp_info->info_7.ucDPMState2VclkFid; 1818 pi->sys_info.uvd_clock_table_entries[3].vclk_did = 1819 igp_info->info_7.ucDPMState3VclkFid; 1820 1821 pi->sys_info.uvd_clock_table_entries[0].dclk_did = 1822 igp_info->info_7.ucDPMState0DclkFid; 1823 pi->sys_info.uvd_clock_table_entries[1].dclk_did = 1824 igp_info->info_7.ucDPMState1DclkFid; 1825 pi->sys_info.uvd_clock_table_entries[2].dclk_did = 1826 igp_info->info_7.ucDPMState2DclkFid; 1827 pi->sys_info.uvd_clock_table_entries[3].dclk_did = 1828 igp_info->info_7.ucDPMState3DclkFid; 1829 1830 for (i = 0; i < 4; i++) { 1831 pi->sys_info.uvd_clock_table_entries[i].vclk = 1832 trinity_convert_did_to_freq(rdev, 1833 pi->sys_info.uvd_clock_table_entries[i].vclk_did); 1834 pi->sys_info.uvd_clock_table_entries[i].dclk = 1835 trinity_convert_did_to_freq(rdev, 1836 pi->sys_info.uvd_clock_table_entries[i].dclk_did); 1837 } 1838 1839 1840 1841 } 1842 return 0; 1843 } 1844 1845 int trinity_dpm_init(struct radeon_device *rdev) 1846 { 1847 struct trinity_power_info *pi; 1848 int ret, i; 1849 1850 pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL); 1851 if (pi == NULL) 1852 return -ENOMEM; 1853 rdev->pm.dpm.priv = pi; 1854 1855 for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) 1856 pi->at[i] = TRINITY_AT_DFLT; 1857 1858 pi->enable_nbps_policy = true; 1859 pi->enable_sclk_ds = true; 1860 pi->enable_gfx_power_gating = true; 1861 pi->enable_gfx_clock_gating = true; 1862 pi->enable_mg_clock_gating = true; 1863 pi->enable_gfx_dynamic_mgpg = true; /* ??? */ 1864 pi->override_dynamic_mgpg = true; 1865 pi->enable_auto_thermal_throttling = true; 1866 pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */ 1867 pi->uvd_dpm = true; /* ??? */ 1868 1869 ret = trinity_parse_sys_info_table(rdev); 1870 if (ret) 1871 return ret; 1872 1873 trinity_construct_boot_state(rdev); 1874 1875 ret = trinity_parse_power_table(rdev); 1876 if (ret) 1877 return ret; 1878 1879 pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt; 1880 pi->enable_dpm = true; 1881 1882 return 0; 1883 } 1884 1885 void trinity_dpm_print_power_state(struct radeon_device *rdev, 1886 struct radeon_ps *rps) 1887 { 1888 int i; 1889 struct trinity_ps *ps = trinity_get_ps(rps); 1890 1891 r600_dpm_print_class_info(rps->class, rps->class2); 1892 r600_dpm_print_cap_info(rps->caps); 1893 printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 1894 for (i = 0; i < ps->num_levels; i++) { 1895 struct trinity_pl *pl = &ps->levels[i]; 1896 printk("\t\tpower level %d sclk: %u vddc: %u\n", 1897 i, pl->sclk, 1898 trinity_convert_voltage_index_to_value(rdev, pl->vddc_index)); 1899 } 1900 r600_dpm_print_ps_status(rdev, rps); 1901 } 1902 1903 void trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 1904 struct seq_file *m) 1905 { 1906 struct radeon_ps *rps = rdev->pm.dpm.current_ps; 1907 struct trinity_ps *ps = trinity_get_ps(rps); 1908 struct trinity_pl *pl; 1909 u32 current_index = 1910 (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >> 1911 CURRENT_STATE_SHIFT; 1912 1913 if (current_index >= ps->num_levels) { 1914 seq_printf(m, "invalid dpm profile %d\n", current_index); 1915 } else { 1916 pl = &ps->levels[current_index]; 1917 seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 1918 seq_printf(m, "power level %d sclk: %u vddc: %u\n", 1919 current_index, pl->sclk, 1920 trinity_convert_voltage_index_to_value(rdev, pl->vddc_index)); 1921 } 1922 } 1923 1924 void trinity_dpm_fini(struct radeon_device *rdev) 1925 { 1926 int i; 1927 1928 trinity_cleanup_asic(rdev); /* ??? */ 1929 1930 for (i = 0; i < rdev->pm.dpm.num_ps; i++) { 1931 kfree(rdev->pm.dpm.ps[i].ps_priv); 1932 } 1933 kfree(rdev->pm.dpm.ps); 1934 kfree(rdev->pm.dpm.priv); 1935 } 1936 1937 u32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low) 1938 { 1939 struct trinity_power_info *pi = trinity_get_pi(rdev); 1940 struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps); 1941 1942 if (low) 1943 return requested_state->levels[0].sclk; 1944 else 1945 return requested_state->levels[requested_state->num_levels - 1].sclk; 1946 } 1947 1948 u32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low) 1949 { 1950 struct trinity_power_info *pi = trinity_get_pi(rdev); 1951 1952 return pi->sys_info.bootup_uma_clk; 1953 } 1954