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