Line data Source code
1 : /*
2 : * Copyright 2011 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 : * Authors: Alex Deucher
23 : */
24 :
25 : #include <dev/pci/drm/drmP.h>
26 : #include "radeon.h"
27 : #include "radeon_asic.h"
28 : #include "rv770d.h"
29 : #include "r600_dpm.h"
30 : #include "rv770_dpm.h"
31 : #include "cypress_dpm.h"
32 : #include "atom.h"
33 :
34 : #define MC_CG_ARB_FREQ_F0 0x0a
35 : #define MC_CG_ARB_FREQ_F1 0x0b
36 : #define MC_CG_ARB_FREQ_F2 0x0c
37 : #define MC_CG_ARB_FREQ_F3 0x0d
38 :
39 : #define MC_CG_SEQ_DRAMCONF_S0 0x05
40 : #define MC_CG_SEQ_DRAMCONF_S1 0x06
41 :
42 : #define PCIE_BUS_CLK 10000
43 : #define TCLK (PCIE_BUS_CLK / 10)
44 :
45 : #define SMC_RAM_END 0xC000
46 :
47 0 : struct rv7xx_ps *rv770_get_ps(struct radeon_ps *rps)
48 : {
49 0 : struct rv7xx_ps *ps = rps->ps_priv;
50 :
51 0 : return ps;
52 : }
53 :
54 0 : struct rv7xx_power_info *rv770_get_pi(struct radeon_device *rdev)
55 : {
56 0 : struct rv7xx_power_info *pi = rdev->pm.dpm.priv;
57 :
58 0 : return pi;
59 : }
60 :
61 0 : struct evergreen_power_info *evergreen_get_pi(struct radeon_device *rdev)
62 : {
63 0 : struct evergreen_power_info *pi = rdev->pm.dpm.priv;
64 :
65 0 : return pi;
66 : }
67 :
68 0 : static void rv770_enable_bif_dynamic_pcie_gen2(struct radeon_device *rdev,
69 : bool enable)
70 : {
71 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
72 : u32 tmp;
73 :
74 0 : tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
75 0 : if (enable) {
76 0 : tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
77 0 : tmp |= LC_HW_VOLTAGE_IF_CONTROL(1);
78 0 : tmp |= LC_GEN2_EN_STRAP;
79 0 : } else {
80 0 : if (!pi->boot_in_gen2) {
81 0 : tmp &= ~LC_HW_VOLTAGE_IF_CONTROL_MASK;
82 0 : tmp &= ~LC_GEN2_EN_STRAP;
83 0 : }
84 : }
85 0 : if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) ||
86 0 : (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
87 0 : WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, tmp);
88 :
89 0 : }
90 :
91 0 : static void rv770_enable_l0s(struct radeon_device *rdev)
92 : {
93 : u32 tmp;
94 :
95 0 : tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL) & ~LC_L0S_INACTIVITY_MASK;
96 0 : tmp |= LC_L0S_INACTIVITY(3);
97 0 : WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp);
98 0 : }
99 :
100 0 : static void rv770_enable_l1(struct radeon_device *rdev)
101 : {
102 : u32 tmp;
103 :
104 0 : tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL);
105 0 : tmp &= ~LC_L1_INACTIVITY_MASK;
106 0 : tmp |= LC_L1_INACTIVITY(4);
107 0 : tmp &= ~LC_PMI_TO_L1_DIS;
108 0 : tmp &= ~LC_ASPM_TO_L1_DIS;
109 0 : WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp);
110 0 : }
111 :
112 0 : static void rv770_enable_pll_sleep_in_l1(struct radeon_device *rdev)
113 : {
114 : u32 tmp;
115 :
116 0 : tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL) & ~LC_L1_INACTIVITY_MASK;
117 0 : tmp |= LC_L1_INACTIVITY(8);
118 0 : WREG32_PCIE_PORT(PCIE_LC_CNTL, tmp);
119 :
120 : /* NOTE, this is a PCIE indirect reg, not PCIE PORT */
121 0 : tmp = RREG32_PCIE(PCIE_P_CNTL);
122 0 : tmp |= P_PLL_PWRDN_IN_L1L23;
123 0 : tmp &= ~P_PLL_BUF_PDNB;
124 0 : tmp &= ~P_PLL_PDNB;
125 0 : tmp |= P_ALLOW_PRX_FRONTEND_SHUTOFF;
126 0 : WREG32_PCIE(PCIE_P_CNTL, tmp);
127 0 : }
128 :
129 0 : static void rv770_gfx_clock_gating_enable(struct radeon_device *rdev,
130 : bool enable)
131 : {
132 0 : if (enable)
133 0 : WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
134 : else {
135 0 : WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
136 0 : WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
137 0 : WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
138 0 : RREG32(GB_TILING_CONFIG);
139 : }
140 0 : }
141 :
142 0 : static void rv770_mg_clock_gating_enable(struct radeon_device *rdev,
143 : bool enable)
144 : {
145 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
146 :
147 0 : if (enable) {
148 : u32 mgcg_cgtt_local0;
149 :
150 0 : if (rdev->family == CHIP_RV770)
151 0 : mgcg_cgtt_local0 = RV770_MGCGTTLOCAL0_DFLT;
152 : else
153 : mgcg_cgtt_local0 = RV7XX_MGCGTTLOCAL0_DFLT;
154 :
155 0 : WREG32(CG_CGTT_LOCAL_0, mgcg_cgtt_local0);
156 0 : WREG32(CG_CGTT_LOCAL_1, (RV770_MGCGTTLOCAL1_DFLT & 0xFFFFCFFF));
157 :
158 0 : if (pi->mgcgtssm)
159 0 : WREG32(CGTS_SM_CTRL_REG, RV770_MGCGCGTSSMCTRL_DFLT);
160 0 : } else {
161 0 : WREG32(CG_CGTT_LOCAL_0, 0xFFFFFFFF);
162 0 : WREG32(CG_CGTT_LOCAL_1, 0xFFFFCFFF);
163 : }
164 0 : }
165 :
166 0 : void rv770_restore_cgcg(struct radeon_device *rdev)
167 : {
168 : bool dpm_en = false, cg_en = false;
169 :
170 0 : if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN)
171 0 : dpm_en = true;
172 0 : if (RREG32(SCLK_PWRMGT_CNTL) & DYN_GFX_CLK_OFF_EN)
173 0 : cg_en = true;
174 :
175 0 : if (dpm_en && !cg_en)
176 0 : WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
177 0 : }
178 :
179 0 : static void rv770_start_dpm(struct radeon_device *rdev)
180 : {
181 0 : WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF);
182 :
183 0 : WREG32_P(MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF);
184 :
185 0 : WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN);
186 0 : }
187 :
188 0 : void rv770_stop_dpm(struct radeon_device *rdev)
189 : {
190 : PPSMC_Result result;
191 :
192 0 : result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled);
193 :
194 0 : if (result != PPSMC_Result_OK)
195 : DRM_DEBUG("Could not force DPM to low.\n");
196 :
197 0 : WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN);
198 :
199 0 : WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF);
200 :
201 0 : WREG32_P(MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF);
202 0 : }
203 :
204 0 : bool rv770_dpm_enabled(struct radeon_device *rdev)
205 : {
206 0 : if (RREG32(GENERAL_PWRMGT) & GLOBAL_PWRMGT_EN)
207 0 : return true;
208 : else
209 0 : return false;
210 0 : }
211 :
212 0 : void rv770_enable_thermal_protection(struct radeon_device *rdev,
213 : bool enable)
214 : {
215 0 : if (enable)
216 0 : WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
217 : else
218 0 : WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
219 0 : }
220 :
221 0 : void rv770_enable_acpi_pm(struct radeon_device *rdev)
222 : {
223 0 : WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN);
224 0 : }
225 :
226 0 : u8 rv770_get_seq_value(struct radeon_device *rdev,
227 : struct rv7xx_pl *pl)
228 : {
229 0 : return (pl->flags & ATOM_PPLIB_R600_FLAGS_LOWPOWER) ?
230 : MC_CG_SEQ_DRAMCONF_S0 : MC_CG_SEQ_DRAMCONF_S1;
231 : }
232 :
233 : #if 0
234 : int rv770_read_smc_soft_register(struct radeon_device *rdev,
235 : u16 reg_offset, u32 *value)
236 : {
237 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
238 :
239 : return rv770_read_smc_sram_dword(rdev,
240 : pi->soft_regs_start + reg_offset,
241 : value, pi->sram_end);
242 : }
243 : #endif
244 :
245 0 : int rv770_write_smc_soft_register(struct radeon_device *rdev,
246 : u16 reg_offset, u32 value)
247 : {
248 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
249 :
250 0 : return rv770_write_smc_sram_dword(rdev,
251 0 : pi->soft_regs_start + reg_offset,
252 0 : value, pi->sram_end);
253 : }
254 :
255 0 : int rv770_populate_smc_t(struct radeon_device *rdev,
256 : struct radeon_ps *radeon_state,
257 : RV770_SMC_SWSTATE *smc_state)
258 : {
259 0 : struct rv7xx_ps *state = rv770_get_ps(radeon_state);
260 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
261 : int i;
262 : int a_n;
263 : int a_d;
264 0 : u8 l[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE];
265 0 : u8 r[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE];
266 : u32 a_t;
267 :
268 0 : l[0] = 0;
269 0 : r[2] = 100;
270 :
271 0 : a_n = (int)state->medium.sclk * pi->lmp +
272 0 : (int)state->low.sclk * (R600_AH_DFLT - pi->rlp);
273 0 : a_d = (int)state->low.sclk * (100 - (int)pi->rlp) +
274 : (int)state->medium.sclk * pi->lmp;
275 :
276 0 : l[1] = (u8)(pi->lmp - (int)pi->lmp * a_n / a_d);
277 0 : r[0] = (u8)(pi->rlp + (100 - (int)pi->rlp) * a_n / a_d);
278 :
279 0 : a_n = (int)state->high.sclk * pi->lhp + (int)state->medium.sclk *
280 0 : (R600_AH_DFLT - pi->rmp);
281 0 : a_d = (int)state->medium.sclk * (100 - (int)pi->rmp) +
282 : (int)state->high.sclk * pi->lhp;
283 :
284 0 : l[2] = (u8)(pi->lhp - (int)pi->lhp * a_n / a_d);
285 0 : r[1] = (u8)(pi->rmp + (100 - (int)pi->rmp) * a_n / a_d);
286 :
287 0 : for (i = 0; i < (RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1); i++) {
288 0 : a_t = CG_R(r[i] * pi->bsp / 200) | CG_L(l[i] * pi->bsp / 200);
289 0 : smc_state->levels[i].aT = cpu_to_be32(a_t);
290 : }
291 :
292 0 : a_t = CG_R(r[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1] * pi->pbsp / 200) |
293 0 : CG_L(l[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1] * pi->pbsp / 200);
294 :
295 0 : smc_state->levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1].aT =
296 0 : cpu_to_be32(a_t);
297 :
298 0 : return 0;
299 0 : }
300 :
301 0 : int rv770_populate_smc_sp(struct radeon_device *rdev,
302 : struct radeon_ps *radeon_state,
303 : RV770_SMC_SWSTATE *smc_state)
304 : {
305 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
306 : int i;
307 :
308 0 : for (i = 0; i < (RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1); i++)
309 0 : smc_state->levels[i].bSP = cpu_to_be32(pi->dsp);
310 :
311 0 : smc_state->levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1].bSP =
312 0 : cpu_to_be32(pi->psp);
313 :
314 0 : return 0;
315 : }
316 :
317 0 : static void rv770_calculate_fractional_mpll_feedback_divider(u32 memory_clock,
318 : u32 reference_clock,
319 : bool gddr5,
320 : struct atom_clock_dividers *dividers,
321 : u32 *clkf,
322 : u32 *clkfrac)
323 : {
324 : u32 post_divider, reference_divider, feedback_divider8;
325 : u32 fyclk;
326 :
327 0 : if (gddr5)
328 0 : fyclk = (memory_clock * 8) / 2;
329 : else
330 0 : fyclk = (memory_clock * 4) / 2;
331 :
332 0 : post_divider = dividers->post_div;
333 0 : reference_divider = dividers->ref_div;
334 :
335 : feedback_divider8 =
336 0 : (8 * fyclk * reference_divider * post_divider) / reference_clock;
337 :
338 0 : *clkf = feedback_divider8 / 8;
339 0 : *clkfrac = feedback_divider8 % 8;
340 0 : }
341 :
342 0 : static int rv770_encode_yclk_post_div(u32 postdiv, u32 *encoded_postdiv)
343 : {
344 : int ret = 0;
345 :
346 0 : switch (postdiv) {
347 : case 1:
348 0 : *encoded_postdiv = 0;
349 0 : break;
350 : case 2:
351 0 : *encoded_postdiv = 1;
352 0 : break;
353 : case 4:
354 0 : *encoded_postdiv = 2;
355 0 : break;
356 : case 8:
357 0 : *encoded_postdiv = 3;
358 0 : break;
359 : case 16:
360 0 : *encoded_postdiv = 4;
361 0 : break;
362 : default:
363 : ret = -EINVAL;
364 0 : break;
365 : }
366 :
367 0 : return ret;
368 : }
369 :
370 0 : u32 rv770_map_clkf_to_ibias(struct radeon_device *rdev, u32 clkf)
371 : {
372 0 : if (clkf <= 0x10)
373 0 : return 0x4B;
374 0 : if (clkf <= 0x19)
375 0 : return 0x5B;
376 0 : if (clkf <= 0x21)
377 0 : return 0x2B;
378 0 : if (clkf <= 0x27)
379 0 : return 0x6C;
380 0 : if (clkf <= 0x31)
381 0 : return 0x9D;
382 0 : return 0xC6;
383 0 : }
384 :
385 0 : static int rv770_populate_mclk_value(struct radeon_device *rdev,
386 : u32 engine_clock, u32 memory_clock,
387 : RV7XX_SMC_MCLK_VALUE *mclk)
388 : {
389 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
390 0 : u8 encoded_reference_dividers[] = { 0, 16, 17, 20, 21 };
391 : u32 mpll_ad_func_cntl =
392 0 : pi->clk_regs.rv770.mpll_ad_func_cntl;
393 : u32 mpll_ad_func_cntl_2 =
394 0 : pi->clk_regs.rv770.mpll_ad_func_cntl_2;
395 : u32 mpll_dq_func_cntl =
396 0 : pi->clk_regs.rv770.mpll_dq_func_cntl;
397 : u32 mpll_dq_func_cntl_2 =
398 0 : pi->clk_regs.rv770.mpll_dq_func_cntl_2;
399 : u32 mclk_pwrmgt_cntl =
400 0 : pi->clk_regs.rv770.mclk_pwrmgt_cntl;
401 0 : u32 dll_cntl = pi->clk_regs.rv770.dll_cntl;
402 0 : struct atom_clock_dividers dividers;
403 0 : u32 reference_clock = rdev->clock.mpll.reference_freq;
404 0 : u32 clkf, clkfrac;
405 0 : u32 postdiv_yclk;
406 : u32 ibias;
407 : int ret;
408 :
409 0 : ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM,
410 : memory_clock, false, ÷rs);
411 0 : if (ret)
412 0 : return ret;
413 :
414 0 : if ((dividers.ref_div < 1) || (dividers.ref_div > 5))
415 0 : return -EINVAL;
416 :
417 0 : rv770_calculate_fractional_mpll_feedback_divider(memory_clock, reference_clock,
418 0 : pi->mem_gddr5,
419 : ÷rs, &clkf, &clkfrac);
420 :
421 0 : ret = rv770_encode_yclk_post_div(dividers.post_div, &postdiv_yclk);
422 0 : if (ret)
423 0 : return ret;
424 :
425 0 : ibias = rv770_map_clkf_to_ibias(rdev, clkf);
426 :
427 0 : mpll_ad_func_cntl &= ~(CLKR_MASK |
428 : YCLK_POST_DIV_MASK |
429 : CLKF_MASK |
430 : CLKFRAC_MASK |
431 : IBIAS_MASK);
432 0 : mpll_ad_func_cntl |= CLKR(encoded_reference_dividers[dividers.ref_div - 1]);
433 0 : mpll_ad_func_cntl |= YCLK_POST_DIV(postdiv_yclk);
434 0 : mpll_ad_func_cntl |= CLKF(clkf);
435 0 : mpll_ad_func_cntl |= CLKFRAC(clkfrac);
436 0 : mpll_ad_func_cntl |= IBIAS(ibias);
437 :
438 0 : if (dividers.vco_mode)
439 0 : mpll_ad_func_cntl_2 |= VCO_MODE;
440 : else
441 0 : mpll_ad_func_cntl_2 &= ~VCO_MODE;
442 :
443 0 : if (pi->mem_gddr5) {
444 0 : rv770_calculate_fractional_mpll_feedback_divider(memory_clock,
445 : reference_clock,
446 : pi->mem_gddr5,
447 : ÷rs, &clkf, &clkfrac);
448 :
449 0 : ibias = rv770_map_clkf_to_ibias(rdev, clkf);
450 :
451 0 : ret = rv770_encode_yclk_post_div(dividers.post_div, &postdiv_yclk);
452 0 : if (ret)
453 0 : return ret;
454 :
455 0 : mpll_dq_func_cntl &= ~(CLKR_MASK |
456 : YCLK_POST_DIV_MASK |
457 : CLKF_MASK |
458 : CLKFRAC_MASK |
459 : IBIAS_MASK);
460 0 : mpll_dq_func_cntl |= CLKR(encoded_reference_dividers[dividers.ref_div - 1]);
461 0 : mpll_dq_func_cntl |= YCLK_POST_DIV(postdiv_yclk);
462 0 : mpll_dq_func_cntl |= CLKF(clkf);
463 0 : mpll_dq_func_cntl |= CLKFRAC(clkfrac);
464 0 : mpll_dq_func_cntl |= IBIAS(ibias);
465 :
466 0 : if (dividers.vco_mode)
467 0 : mpll_dq_func_cntl_2 |= VCO_MODE;
468 : else
469 0 : mpll_dq_func_cntl_2 &= ~VCO_MODE;
470 : }
471 :
472 0 : mclk->mclk770.mclk_value = cpu_to_be32(memory_clock);
473 0 : mclk->mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
474 0 : mclk->mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
475 0 : mclk->mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
476 0 : mclk->mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
477 0 : mclk->mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
478 0 : mclk->mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
479 :
480 0 : return 0;
481 0 : }
482 :
483 0 : static int rv770_populate_sclk_value(struct radeon_device *rdev,
484 : u32 engine_clock,
485 : RV770_SMC_SCLK_VALUE *sclk)
486 : {
487 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
488 0 : struct atom_clock_dividers dividers;
489 : u32 spll_func_cntl =
490 0 : pi->clk_regs.rv770.cg_spll_func_cntl;
491 : u32 spll_func_cntl_2 =
492 0 : pi->clk_regs.rv770.cg_spll_func_cntl_2;
493 : u32 spll_func_cntl_3 =
494 0 : pi->clk_regs.rv770.cg_spll_func_cntl_3;
495 : u32 cg_spll_spread_spectrum =
496 0 : pi->clk_regs.rv770.cg_spll_spread_spectrum;
497 : u32 cg_spll_spread_spectrum_2 =
498 0 : pi->clk_regs.rv770.cg_spll_spread_spectrum_2;
499 : u64 tmp;
500 0 : u32 reference_clock = rdev->clock.spll.reference_freq;
501 : u32 reference_divider, post_divider;
502 : u32 fbdiv;
503 : int ret;
504 :
505 0 : ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
506 : engine_clock, false, ÷rs);
507 0 : if (ret)
508 0 : return ret;
509 :
510 0 : reference_divider = 1 + dividers.ref_div;
511 :
512 0 : if (dividers.enable_post_div)
513 0 : post_divider = (0x0f & (dividers.post_div >> 4)) + (0x0f & dividers.post_div) + 2;
514 : else
515 : post_divider = 1;
516 :
517 0 : tmp = (u64) engine_clock * reference_divider * post_divider * 16384;
518 0 : do_div(tmp, reference_clock);
519 0 : fbdiv = (u32) tmp;
520 :
521 0 : if (dividers.enable_post_div)
522 0 : spll_func_cntl |= SPLL_DIVEN;
523 : else
524 0 : spll_func_cntl &= ~SPLL_DIVEN;
525 0 : spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK);
526 0 : spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div);
527 0 : spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf);
528 0 : spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf);
529 :
530 0 : spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
531 0 : spll_func_cntl_2 |= SCLK_MUX_SEL(2);
532 :
533 0 : spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK;
534 0 : spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv);
535 0 : spll_func_cntl_3 |= SPLL_DITHEN;
536 :
537 0 : if (pi->sclk_ss) {
538 0 : struct radeon_atom_ss ss;
539 0 : u32 vco_freq = engine_clock * post_divider;
540 :
541 0 : if (radeon_atombios_get_asic_ss_info(rdev, &ss,
542 : ASIC_INTERNAL_ENGINE_SS, vco_freq)) {
543 0 : u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate);
544 0 : u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000);
545 :
546 0 : cg_spll_spread_spectrum &= ~CLKS_MASK;
547 0 : cg_spll_spread_spectrum |= CLKS(clk_s);
548 0 : cg_spll_spread_spectrum |= SSEN;
549 :
550 0 : cg_spll_spread_spectrum_2 &= ~CLKV_MASK;
551 0 : cg_spll_spread_spectrum_2 |= CLKV(clk_v);
552 0 : }
553 0 : }
554 :
555 0 : sclk->sclk_value = cpu_to_be32(engine_clock);
556 0 : sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
557 0 : sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
558 0 : sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
559 0 : sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum);
560 0 : sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2);
561 :
562 0 : return 0;
563 0 : }
564 :
565 0 : int rv770_populate_vddc_value(struct radeon_device *rdev, u16 vddc,
566 : RV770_SMC_VOLTAGE_VALUE *voltage)
567 : {
568 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
569 : int i;
570 :
571 0 : if (!pi->voltage_control) {
572 0 : voltage->index = 0;
573 0 : voltage->value = 0;
574 0 : return 0;
575 : }
576 :
577 0 : for (i = 0; i < pi->valid_vddc_entries; i++) {
578 0 : if (vddc <= pi->vddc_table[i].vddc) {
579 0 : voltage->index = pi->vddc_table[i].vddc_index;
580 0 : voltage->value = cpu_to_be16(vddc);
581 0 : break;
582 : }
583 : }
584 :
585 0 : if (i == pi->valid_vddc_entries)
586 0 : return -EINVAL;
587 :
588 0 : return 0;
589 0 : }
590 :
591 0 : int rv770_populate_mvdd_value(struct radeon_device *rdev, u32 mclk,
592 : RV770_SMC_VOLTAGE_VALUE *voltage)
593 : {
594 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
595 :
596 0 : if (!pi->mvdd_control) {
597 0 : voltage->index = MVDD_HIGH_INDEX;
598 0 : voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
599 0 : return 0;
600 : }
601 :
602 0 : if (mclk <= pi->mvdd_split_frequency) {
603 0 : voltage->index = MVDD_LOW_INDEX;
604 0 : voltage->value = cpu_to_be16(MVDD_LOW_VALUE);
605 0 : } else {
606 0 : voltage->index = MVDD_HIGH_INDEX;
607 0 : voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
608 : }
609 :
610 0 : return 0;
611 0 : }
612 :
613 0 : static int rv770_convert_power_level_to_smc(struct radeon_device *rdev,
614 : struct rv7xx_pl *pl,
615 : RV770_SMC_HW_PERFORMANCE_LEVEL *level,
616 : u8 watermark_level)
617 : {
618 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
619 : int ret;
620 :
621 0 : level->gen2PCIE = pi->pcie_gen2 ?
622 0 : ((pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0) : 0;
623 0 : level->gen2XSP = (pl->flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) ? 1 : 0;
624 0 : level->backbias = (pl->flags & ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE) ? 1 : 0;
625 0 : level->displayWatermark = watermark_level;
626 :
627 0 : if (rdev->family == CHIP_RV740)
628 0 : ret = rv740_populate_sclk_value(rdev, pl->sclk,
629 0 : &level->sclk);
630 0 : else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
631 0 : ret = rv730_populate_sclk_value(rdev, pl->sclk,
632 0 : &level->sclk);
633 : else
634 0 : ret = rv770_populate_sclk_value(rdev, pl->sclk,
635 0 : &level->sclk);
636 0 : if (ret)
637 0 : return ret;
638 :
639 0 : if (rdev->family == CHIP_RV740) {
640 0 : if (pi->mem_gddr5) {
641 0 : if (pl->mclk <= pi->mclk_strobe_mode_threshold)
642 0 : level->strobeMode =
643 0 : rv740_get_mclk_frequency_ratio(pl->mclk) | 0x10;
644 : else
645 0 : level->strobeMode = 0;
646 :
647 0 : if (pl->mclk > pi->mclk_edc_enable_threshold)
648 0 : level->mcFlags = SMC_MC_EDC_RD_FLAG | SMC_MC_EDC_WR_FLAG;
649 : else
650 0 : level->mcFlags = 0;
651 : }
652 0 : ret = rv740_populate_mclk_value(rdev, pl->sclk,
653 0 : pl->mclk, &level->mclk);
654 0 : } else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
655 0 : ret = rv730_populate_mclk_value(rdev, pl->sclk,
656 0 : pl->mclk, &level->mclk);
657 : else
658 0 : ret = rv770_populate_mclk_value(rdev, pl->sclk,
659 0 : pl->mclk, &level->mclk);
660 0 : if (ret)
661 0 : return ret;
662 :
663 0 : ret = rv770_populate_vddc_value(rdev, pl->vddc,
664 0 : &level->vddc);
665 0 : if (ret)
666 0 : return ret;
667 :
668 0 : ret = rv770_populate_mvdd_value(rdev, pl->mclk, &level->mvdd);
669 :
670 0 : return ret;
671 0 : }
672 :
673 0 : static int rv770_convert_power_state_to_smc(struct radeon_device *rdev,
674 : struct radeon_ps *radeon_state,
675 : RV770_SMC_SWSTATE *smc_state)
676 : {
677 0 : struct rv7xx_ps *state = rv770_get_ps(radeon_state);
678 : int ret;
679 :
680 0 : if (!(radeon_state->caps & ATOM_PPLIB_DISALLOW_ON_DC))
681 0 : smc_state->flags |= PPSMC_SWSTATE_FLAG_DC;
682 :
683 0 : ret = rv770_convert_power_level_to_smc(rdev,
684 0 : &state->low,
685 0 : &smc_state->levels[0],
686 : PPSMC_DISPLAY_WATERMARK_LOW);
687 0 : if (ret)
688 0 : return ret;
689 :
690 0 : ret = rv770_convert_power_level_to_smc(rdev,
691 0 : &state->medium,
692 0 : &smc_state->levels[1],
693 : PPSMC_DISPLAY_WATERMARK_LOW);
694 0 : if (ret)
695 0 : return ret;
696 :
697 0 : ret = rv770_convert_power_level_to_smc(rdev,
698 0 : &state->high,
699 0 : &smc_state->levels[2],
700 : PPSMC_DISPLAY_WATERMARK_HIGH);
701 0 : if (ret)
702 0 : return ret;
703 :
704 0 : smc_state->levels[0].arbValue = MC_CG_ARB_FREQ_F1;
705 0 : smc_state->levels[1].arbValue = MC_CG_ARB_FREQ_F2;
706 0 : smc_state->levels[2].arbValue = MC_CG_ARB_FREQ_F3;
707 :
708 0 : smc_state->levels[0].seqValue = rv770_get_seq_value(rdev,
709 : &state->low);
710 0 : smc_state->levels[1].seqValue = rv770_get_seq_value(rdev,
711 : &state->medium);
712 0 : smc_state->levels[2].seqValue = rv770_get_seq_value(rdev,
713 : &state->high);
714 :
715 0 : rv770_populate_smc_sp(rdev, radeon_state, smc_state);
716 :
717 0 : return rv770_populate_smc_t(rdev, radeon_state, smc_state);
718 :
719 0 : }
720 :
721 0 : u32 rv770_calculate_memory_refresh_rate(struct radeon_device *rdev,
722 : u32 engine_clock)
723 : {
724 : u32 dram_rows;
725 : u32 dram_refresh_rate;
726 : u32 mc_arb_rfsh_rate;
727 : u32 tmp;
728 :
729 0 : tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT;
730 0 : dram_rows = 1 << (tmp + 10);
731 0 : tmp = RREG32(MC_SEQ_MISC0) & 3;
732 0 : dram_refresh_rate = 1 << (tmp + 3);
733 0 : mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64;
734 :
735 0 : return mc_arb_rfsh_rate;
736 : }
737 :
738 0 : static void rv770_program_memory_timing_parameters(struct radeon_device *rdev,
739 : struct radeon_ps *radeon_state)
740 : {
741 0 : struct rv7xx_ps *state = rv770_get_ps(radeon_state);
742 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
743 : u32 sqm_ratio;
744 : u32 arb_refresh_rate;
745 : u32 high_clock;
746 :
747 0 : if (state->high.sclk < (state->low.sclk * 0xFF / 0x40))
748 0 : high_clock = state->high.sclk;
749 : else
750 : high_clock = (state->low.sclk * 0xFF / 0x40);
751 :
752 0 : radeon_atom_set_engine_dram_timings(rdev, high_clock,
753 0 : state->high.mclk);
754 :
755 : sqm_ratio =
756 0 : STATE0(64 * high_clock / pi->boot_sclk) |
757 0 : STATE1(64 * high_clock / state->low.sclk) |
758 0 : STATE2(64 * high_clock / state->medium.sclk) |
759 0 : STATE3(64 * high_clock / state->high.sclk);
760 0 : WREG32(MC_ARB_SQM_RATIO, sqm_ratio);
761 :
762 : arb_refresh_rate =
763 0 : POWERMODE0(rv770_calculate_memory_refresh_rate(rdev, pi->boot_sclk)) |
764 0 : POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) |
765 0 : POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) |
766 0 : POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk));
767 0 : WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate);
768 0 : }
769 :
770 0 : void rv770_enable_backbias(struct radeon_device *rdev,
771 : bool enable)
772 : {
773 0 : if (enable)
774 0 : WREG32_P(GENERAL_PWRMGT, BACKBIAS_PAD_EN, ~BACKBIAS_PAD_EN);
775 : else
776 0 : WREG32_P(GENERAL_PWRMGT, 0, ~(BACKBIAS_VALUE | BACKBIAS_PAD_EN));
777 0 : }
778 :
779 0 : static void rv770_enable_spread_spectrum(struct radeon_device *rdev,
780 : bool enable)
781 : {
782 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
783 :
784 0 : if (enable) {
785 0 : if (pi->sclk_ss)
786 0 : WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN);
787 :
788 0 : if (pi->mclk_ss) {
789 0 : if (rdev->family == CHIP_RV740)
790 0 : rv740_enable_mclk_spread_spectrum(rdev, true);
791 : }
792 : } else {
793 0 : WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN);
794 :
795 0 : WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN);
796 :
797 0 : WREG32_P(CG_MPLL_SPREAD_SPECTRUM, 0, ~SSEN);
798 :
799 0 : if (rdev->family == CHIP_RV740)
800 0 : rv740_enable_mclk_spread_spectrum(rdev, false);
801 : }
802 0 : }
803 :
804 0 : static void rv770_program_mpll_timing_parameters(struct radeon_device *rdev)
805 : {
806 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
807 :
808 0 : if ((rdev->family == CHIP_RV770) && !pi->mem_gddr5) {
809 0 : WREG32(MPLL_TIME,
810 : (MPLL_LOCK_TIME(R600_MPLLLOCKTIME_DFLT * pi->ref_div) |
811 : MPLL_RESET_TIME(R600_MPLLRESETTIME_DFLT)));
812 0 : }
813 0 : }
814 :
815 0 : void rv770_setup_bsp(struct radeon_device *rdev)
816 : {
817 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
818 0 : u32 xclk = radeon_get_xclk(rdev);
819 :
820 0 : r600_calculate_u_and_p(pi->asi,
821 : xclk,
822 : 16,
823 0 : &pi->bsp,
824 0 : &pi->bsu);
825 :
826 0 : r600_calculate_u_and_p(pi->pasi,
827 : xclk,
828 : 16,
829 0 : &pi->pbsp,
830 0 : &pi->pbsu);
831 :
832 0 : pi->dsp = BSP(pi->bsp) | BSU(pi->bsu);
833 0 : pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu);
834 :
835 0 : WREG32(CG_BSP, pi->dsp);
836 :
837 0 : }
838 :
839 0 : void rv770_program_git(struct radeon_device *rdev)
840 : {
841 0 : WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK);
842 0 : }
843 :
844 0 : void rv770_program_tp(struct radeon_device *rdev)
845 : {
846 : int i;
847 : enum r600_td td = R600_TD_DFLT;
848 :
849 0 : for (i = 0; i < R600_PM_NUMBER_OF_TC; i++)
850 0 : WREG32(CG_FFCT_0 + (i * 4), (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i])));
851 :
852 0 : if (td == R600_TD_AUTO)
853 0 : WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL);
854 : else
855 0 : WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL);
856 0 : if (td == R600_TD_UP)
857 0 : WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE);
858 0 : if (td == R600_TD_DOWN)
859 0 : WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE);
860 0 : }
861 :
862 0 : void rv770_program_tpp(struct radeon_device *rdev)
863 : {
864 0 : WREG32(CG_TPC, R600_TPC_DFLT);
865 0 : }
866 :
867 0 : void rv770_program_sstp(struct radeon_device *rdev)
868 : {
869 0 : WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT)));
870 0 : }
871 :
872 0 : void rv770_program_engine_speed_parameters(struct radeon_device *rdev)
873 : {
874 0 : WREG32_P(SPLL_CNTL_MODE, SPLL_DIV_SYNC, ~SPLL_DIV_SYNC);
875 0 : }
876 :
877 0 : static void rv770_enable_display_gap(struct radeon_device *rdev)
878 : {
879 0 : u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
880 :
881 0 : tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
882 0 : tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE) |
883 : DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE));
884 0 : WREG32(CG_DISPLAY_GAP_CNTL, tmp);
885 0 : }
886 :
887 0 : void rv770_program_vc(struct radeon_device *rdev)
888 : {
889 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
890 :
891 0 : WREG32(CG_FTV, pi->vrc);
892 0 : }
893 :
894 0 : void rv770_clear_vc(struct radeon_device *rdev)
895 : {
896 0 : WREG32(CG_FTV, 0);
897 0 : }
898 :
899 0 : int rv770_upload_firmware(struct radeon_device *rdev)
900 : {
901 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
902 : int ret;
903 :
904 0 : rv770_reset_smc(rdev);
905 0 : rv770_stop_smc_clock(rdev);
906 :
907 0 : ret = rv770_load_smc_ucode(rdev, pi->sram_end);
908 0 : if (ret)
909 0 : return ret;
910 :
911 0 : return 0;
912 0 : }
913 :
914 0 : static int rv770_populate_smc_acpi_state(struct radeon_device *rdev,
915 : RV770_SMC_STATETABLE *table)
916 : {
917 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
918 :
919 : u32 mpll_ad_func_cntl =
920 0 : pi->clk_regs.rv770.mpll_ad_func_cntl;
921 : u32 mpll_ad_func_cntl_2 =
922 0 : pi->clk_regs.rv770.mpll_ad_func_cntl_2;
923 : u32 mpll_dq_func_cntl =
924 0 : pi->clk_regs.rv770.mpll_dq_func_cntl;
925 : u32 mpll_dq_func_cntl_2 =
926 0 : pi->clk_regs.rv770.mpll_dq_func_cntl_2;
927 : u32 spll_func_cntl =
928 0 : pi->clk_regs.rv770.cg_spll_func_cntl;
929 : u32 spll_func_cntl_2 =
930 0 : pi->clk_regs.rv770.cg_spll_func_cntl_2;
931 : u32 spll_func_cntl_3 =
932 0 : pi->clk_regs.rv770.cg_spll_func_cntl_3;
933 : u32 mclk_pwrmgt_cntl;
934 : u32 dll_cntl;
935 :
936 0 : table->ACPIState = table->initialState;
937 :
938 0 : table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC;
939 :
940 0 : if (pi->acpi_vddc) {
941 0 : rv770_populate_vddc_value(rdev, pi->acpi_vddc,
942 0 : &table->ACPIState.levels[0].vddc);
943 0 : if (pi->pcie_gen2) {
944 0 : if (pi->acpi_pcie_gen2)
945 0 : table->ACPIState.levels[0].gen2PCIE = 1;
946 : else
947 0 : table->ACPIState.levels[0].gen2PCIE = 0;
948 : } else
949 0 : table->ACPIState.levels[0].gen2PCIE = 0;
950 0 : if (pi->acpi_pcie_gen2)
951 0 : table->ACPIState.levels[0].gen2XSP = 1;
952 : else
953 0 : table->ACPIState.levels[0].gen2XSP = 0;
954 : } else {
955 0 : rv770_populate_vddc_value(rdev, pi->min_vddc_in_table,
956 0 : &table->ACPIState.levels[0].vddc);
957 0 : table->ACPIState.levels[0].gen2PCIE = 0;
958 : }
959 :
960 :
961 0 : mpll_ad_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
962 :
963 0 : mpll_dq_func_cntl_2 |= BIAS_GEN_PDNB | RESET_EN;
964 :
965 : mclk_pwrmgt_cntl = (MRDCKA0_RESET |
966 : MRDCKA1_RESET |
967 : MRDCKB0_RESET |
968 : MRDCKB1_RESET |
969 : MRDCKC0_RESET |
970 : MRDCKC1_RESET |
971 : MRDCKD0_RESET |
972 : MRDCKD1_RESET);
973 :
974 : dll_cntl = 0xff000000;
975 :
976 0 : spll_func_cntl |= SPLL_RESET | SPLL_SLEEP | SPLL_BYPASS_EN;
977 :
978 0 : spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK;
979 0 : spll_func_cntl_2 |= SCLK_MUX_SEL(4);
980 :
981 0 : table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl);
982 0 : table->ACPIState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 = cpu_to_be32(mpll_ad_func_cntl_2);
983 0 : table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl);
984 0 : table->ACPIState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 = cpu_to_be32(mpll_dq_func_cntl_2);
985 :
986 0 : table->ACPIState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl);
987 0 : table->ACPIState.levels[0].mclk.mclk770.vDLL_CNTL = cpu_to_be32(dll_cntl);
988 :
989 0 : table->ACPIState.levels[0].mclk.mclk770.mclk_value = 0;
990 :
991 0 : table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl);
992 0 : table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2);
993 0 : table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3);
994 :
995 0 : table->ACPIState.levels[0].sclk.sclk_value = 0;
996 :
997 0 : rv770_populate_mvdd_value(rdev, 0, &table->ACPIState.levels[0].mvdd);
998 :
999 0 : table->ACPIState.levels[1] = table->ACPIState.levels[0];
1000 0 : table->ACPIState.levels[2] = table->ACPIState.levels[0];
1001 :
1002 0 : return 0;
1003 : }
1004 :
1005 0 : int rv770_populate_initial_mvdd_value(struct radeon_device *rdev,
1006 : RV770_SMC_VOLTAGE_VALUE *voltage)
1007 : {
1008 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1009 :
1010 0 : if ((pi->s0_vid_lower_smio_cntl & pi->mvdd_mask_low) ==
1011 0 : (pi->mvdd_low_smio[MVDD_LOW_INDEX] & pi->mvdd_mask_low) ) {
1012 0 : voltage->index = MVDD_LOW_INDEX;
1013 0 : voltage->value = cpu_to_be16(MVDD_LOW_VALUE);
1014 0 : } else {
1015 0 : voltage->index = MVDD_HIGH_INDEX;
1016 0 : voltage->value = cpu_to_be16(MVDD_HIGH_VALUE);
1017 : }
1018 :
1019 0 : return 0;
1020 : }
1021 :
1022 0 : static int rv770_populate_smc_initial_state(struct radeon_device *rdev,
1023 : struct radeon_ps *radeon_state,
1024 : RV770_SMC_STATETABLE *table)
1025 : {
1026 0 : struct rv7xx_ps *initial_state = rv770_get_ps(radeon_state);
1027 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1028 : u32 a_t;
1029 :
1030 0 : table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL =
1031 0 : cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl);
1032 0 : table->initialState.levels[0].mclk.mclk770.vMPLL_AD_FUNC_CNTL_2 =
1033 0 : cpu_to_be32(pi->clk_regs.rv770.mpll_ad_func_cntl_2);
1034 0 : table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL =
1035 0 : cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl);
1036 0 : table->initialState.levels[0].mclk.mclk770.vMPLL_DQ_FUNC_CNTL_2 =
1037 0 : cpu_to_be32(pi->clk_regs.rv770.mpll_dq_func_cntl_2);
1038 0 : table->initialState.levels[0].mclk.mclk770.vMCLK_PWRMGT_CNTL =
1039 0 : cpu_to_be32(pi->clk_regs.rv770.mclk_pwrmgt_cntl);
1040 0 : table->initialState.levels[0].mclk.mclk770.vDLL_CNTL =
1041 0 : cpu_to_be32(pi->clk_regs.rv770.dll_cntl);
1042 :
1043 0 : table->initialState.levels[0].mclk.mclk770.vMPLL_SS =
1044 0 : cpu_to_be32(pi->clk_regs.rv770.mpll_ss1);
1045 0 : table->initialState.levels[0].mclk.mclk770.vMPLL_SS2 =
1046 0 : cpu_to_be32(pi->clk_regs.rv770.mpll_ss2);
1047 :
1048 0 : table->initialState.levels[0].mclk.mclk770.mclk_value =
1049 0 : cpu_to_be32(initial_state->low.mclk);
1050 :
1051 0 : table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL =
1052 0 : cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl);
1053 0 : table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 =
1054 0 : cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_2);
1055 0 : table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 =
1056 0 : cpu_to_be32(pi->clk_regs.rv770.cg_spll_func_cntl_3);
1057 0 : table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM =
1058 0 : cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum);
1059 0 : table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 =
1060 0 : cpu_to_be32(pi->clk_regs.rv770.cg_spll_spread_spectrum_2);
1061 :
1062 0 : table->initialState.levels[0].sclk.sclk_value =
1063 0 : cpu_to_be32(initial_state->low.sclk);
1064 :
1065 0 : table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0;
1066 :
1067 0 : table->initialState.levels[0].seqValue =
1068 0 : rv770_get_seq_value(rdev, &initial_state->low);
1069 :
1070 0 : rv770_populate_vddc_value(rdev,
1071 0 : initial_state->low.vddc,
1072 0 : &table->initialState.levels[0].vddc);
1073 0 : rv770_populate_initial_mvdd_value(rdev,
1074 0 : &table->initialState.levels[0].mvdd);
1075 :
1076 : a_t = CG_R(0xffff) | CG_L(0);
1077 0 : table->initialState.levels[0].aT = cpu_to_be32(a_t);
1078 :
1079 0 : table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp);
1080 :
1081 0 : if (pi->boot_in_gen2)
1082 0 : table->initialState.levels[0].gen2PCIE = 1;
1083 : else
1084 0 : table->initialState.levels[0].gen2PCIE = 0;
1085 0 : if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
1086 0 : table->initialState.levels[0].gen2XSP = 1;
1087 : else
1088 0 : table->initialState.levels[0].gen2XSP = 0;
1089 :
1090 0 : if (rdev->family == CHIP_RV740) {
1091 0 : if (pi->mem_gddr5) {
1092 0 : if (initial_state->low.mclk <= pi->mclk_strobe_mode_threshold)
1093 0 : table->initialState.levels[0].strobeMode =
1094 0 : rv740_get_mclk_frequency_ratio(initial_state->low.mclk) | 0x10;
1095 : else
1096 0 : table->initialState.levels[0].strobeMode = 0;
1097 :
1098 0 : if (initial_state->low.mclk >= pi->mclk_edc_enable_threshold)
1099 0 : table->initialState.levels[0].mcFlags = SMC_MC_EDC_RD_FLAG | SMC_MC_EDC_WR_FLAG;
1100 : else
1101 0 : table->initialState.levels[0].mcFlags = 0;
1102 : }
1103 : }
1104 :
1105 0 : table->initialState.levels[1] = table->initialState.levels[0];
1106 0 : table->initialState.levels[2] = table->initialState.levels[0];
1107 :
1108 0 : table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC;
1109 :
1110 0 : return 0;
1111 : }
1112 :
1113 0 : static int rv770_populate_smc_vddc_table(struct radeon_device *rdev,
1114 : RV770_SMC_STATETABLE *table)
1115 : {
1116 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1117 : int i;
1118 :
1119 0 : for (i = 0; i < pi->valid_vddc_entries; i++) {
1120 0 : table->highSMIO[pi->vddc_table[i].vddc_index] =
1121 0 : pi->vddc_table[i].high_smio;
1122 0 : table->lowSMIO[pi->vddc_table[i].vddc_index] =
1123 0 : cpu_to_be32(pi->vddc_table[i].low_smio);
1124 : }
1125 :
1126 0 : table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_VDDC] = 0;
1127 0 : table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_VDDC] =
1128 0 : cpu_to_be32(pi->vddc_mask_low);
1129 :
1130 0 : for (i = 0;
1131 0 : ((i < pi->valid_vddc_entries) &&
1132 0 : (pi->max_vddc_in_table >
1133 0 : pi->vddc_table[i].vddc));
1134 0 : i++);
1135 :
1136 0 : table->maxVDDCIndexInPPTable =
1137 0 : pi->vddc_table[i].vddc_index;
1138 :
1139 0 : return 0;
1140 : }
1141 :
1142 0 : static int rv770_populate_smc_mvdd_table(struct radeon_device *rdev,
1143 : RV770_SMC_STATETABLE *table)
1144 : {
1145 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1146 :
1147 0 : if (pi->mvdd_control) {
1148 0 : table->lowSMIO[MVDD_HIGH_INDEX] |=
1149 0 : cpu_to_be32(pi->mvdd_low_smio[MVDD_HIGH_INDEX]);
1150 0 : table->lowSMIO[MVDD_LOW_INDEX] |=
1151 0 : cpu_to_be32(pi->mvdd_low_smio[MVDD_LOW_INDEX]);
1152 :
1153 0 : table->voltageMaskTable.highMask[RV770_SMC_VOLTAGEMASK_MVDD] = 0;
1154 0 : table->voltageMaskTable.lowMask[RV770_SMC_VOLTAGEMASK_MVDD] =
1155 0 : cpu_to_be32(pi->mvdd_mask_low);
1156 0 : }
1157 :
1158 0 : return 0;
1159 : }
1160 :
1161 0 : static int rv770_init_smc_table(struct radeon_device *rdev,
1162 : struct radeon_ps *radeon_boot_state)
1163 : {
1164 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1165 0 : struct rv7xx_ps *boot_state = rv770_get_ps(radeon_boot_state);
1166 0 : RV770_SMC_STATETABLE *table = &pi->smc_statetable;
1167 : int ret;
1168 :
1169 0 : memset(table, 0, sizeof(RV770_SMC_STATETABLE));
1170 :
1171 0 : pi->boot_sclk = boot_state->low.sclk;
1172 :
1173 0 : rv770_populate_smc_vddc_table(rdev, table);
1174 0 : rv770_populate_smc_mvdd_table(rdev, table);
1175 :
1176 0 : switch (rdev->pm.int_thermal_type) {
1177 : case THERMAL_TYPE_RV770:
1178 : case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
1179 0 : table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL;
1180 0 : break;
1181 : case THERMAL_TYPE_NONE:
1182 0 : table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE;
1183 0 : break;
1184 : case THERMAL_TYPE_EXTERNAL_GPIO:
1185 : default:
1186 0 : table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL;
1187 0 : break;
1188 : }
1189 :
1190 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC) {
1191 0 : table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC;
1192 :
1193 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT)
1194 0 : table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK;
1195 :
1196 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT)
1197 0 : table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE;
1198 : }
1199 :
1200 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC)
1201 0 : table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC;
1202 :
1203 0 : if (pi->mem_gddr5)
1204 0 : table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5;
1205 :
1206 0 : if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
1207 0 : ret = rv730_populate_smc_initial_state(rdev, radeon_boot_state, table);
1208 : else
1209 0 : ret = rv770_populate_smc_initial_state(rdev, radeon_boot_state, table);
1210 0 : if (ret)
1211 0 : return ret;
1212 :
1213 0 : if (rdev->family == CHIP_RV740)
1214 0 : ret = rv740_populate_smc_acpi_state(rdev, table);
1215 0 : else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
1216 0 : ret = rv730_populate_smc_acpi_state(rdev, table);
1217 : else
1218 0 : ret = rv770_populate_smc_acpi_state(rdev, table);
1219 0 : if (ret)
1220 0 : return ret;
1221 :
1222 0 : table->driverState = table->initialState;
1223 :
1224 0 : return rv770_copy_bytes_to_smc(rdev,
1225 0 : pi->state_table_start,
1226 : (const u8 *)table,
1227 : sizeof(RV770_SMC_STATETABLE),
1228 0 : pi->sram_end);
1229 0 : }
1230 :
1231 0 : static int rv770_construct_vddc_table(struct radeon_device *rdev)
1232 : {
1233 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1234 0 : u16 min, max, step;
1235 : u32 steps = 0;
1236 : u8 vddc_index = 0;
1237 : u32 i;
1238 :
1239 0 : radeon_atom_get_min_voltage(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &min);
1240 0 : radeon_atom_get_max_voltage(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &max);
1241 0 : radeon_atom_get_voltage_step(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, &step);
1242 :
1243 0 : steps = (max - min) / step + 1;
1244 :
1245 0 : if (steps > MAX_NO_VREG_STEPS)
1246 0 : return -EINVAL;
1247 :
1248 0 : for (i = 0; i < steps; i++) {
1249 0 : u32 gpio_pins, gpio_mask;
1250 :
1251 0 : pi->vddc_table[i].vddc = (u16)(min + i * step);
1252 0 : radeon_atom_get_voltage_gpio_settings(rdev,
1253 : pi->vddc_table[i].vddc,
1254 : SET_VOLTAGE_TYPE_ASIC_VDDC,
1255 : &gpio_pins, &gpio_mask);
1256 0 : pi->vddc_table[i].low_smio = gpio_pins & gpio_mask;
1257 0 : pi->vddc_table[i].high_smio = 0;
1258 0 : pi->vddc_mask_low = gpio_mask;
1259 0 : if (i > 0) {
1260 0 : if ((pi->vddc_table[i].low_smio !=
1261 0 : pi->vddc_table[i - 1].low_smio ) ||
1262 0 : (pi->vddc_table[i].high_smio !=
1263 0 : pi->vddc_table[i - 1].high_smio))
1264 0 : vddc_index++;
1265 : }
1266 0 : pi->vddc_table[i].vddc_index = vddc_index;
1267 0 : }
1268 :
1269 0 : pi->valid_vddc_entries = (u8)steps;
1270 :
1271 0 : return 0;
1272 0 : }
1273 :
1274 0 : static u32 rv770_get_mclk_split_point(struct atom_memory_info *memory_info)
1275 : {
1276 0 : if (memory_info->mem_type == MEM_TYPE_GDDR3)
1277 0 : return 30000;
1278 :
1279 0 : return 0;
1280 0 : }
1281 :
1282 0 : static int rv770_get_mvdd_pin_configuration(struct radeon_device *rdev)
1283 : {
1284 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1285 0 : u32 gpio_pins, gpio_mask;
1286 :
1287 0 : radeon_atom_get_voltage_gpio_settings(rdev,
1288 : MVDD_HIGH_VALUE, SET_VOLTAGE_TYPE_ASIC_MVDDC,
1289 : &gpio_pins, &gpio_mask);
1290 0 : pi->mvdd_mask_low = gpio_mask;
1291 0 : pi->mvdd_low_smio[MVDD_HIGH_INDEX] =
1292 0 : gpio_pins & gpio_mask;
1293 :
1294 0 : radeon_atom_get_voltage_gpio_settings(rdev,
1295 : MVDD_LOW_VALUE, SET_VOLTAGE_TYPE_ASIC_MVDDC,
1296 : &gpio_pins, &gpio_mask);
1297 0 : pi->mvdd_low_smio[MVDD_LOW_INDEX] =
1298 0 : gpio_pins & gpio_mask;
1299 :
1300 0 : return 0;
1301 0 : }
1302 :
1303 0 : u8 rv770_get_memory_module_index(struct radeon_device *rdev)
1304 : {
1305 0 : return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff);
1306 : }
1307 :
1308 0 : static int rv770_get_mvdd_configuration(struct radeon_device *rdev)
1309 : {
1310 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1311 : u8 memory_module_index;
1312 0 : struct atom_memory_info memory_info;
1313 :
1314 0 : memory_module_index = rv770_get_memory_module_index(rdev);
1315 :
1316 0 : if (radeon_atom_get_memory_info(rdev, memory_module_index, &memory_info)) {
1317 0 : pi->mvdd_control = false;
1318 0 : return 0;
1319 : }
1320 :
1321 0 : pi->mvdd_split_frequency =
1322 0 : rv770_get_mclk_split_point(&memory_info);
1323 :
1324 0 : if (pi->mvdd_split_frequency == 0) {
1325 0 : pi->mvdd_control = false;
1326 0 : return 0;
1327 : }
1328 :
1329 0 : return rv770_get_mvdd_pin_configuration(rdev);
1330 0 : }
1331 :
1332 0 : void rv770_enable_voltage_control(struct radeon_device *rdev,
1333 : bool enable)
1334 : {
1335 0 : if (enable)
1336 0 : WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN);
1337 : else
1338 0 : WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN);
1339 0 : }
1340 :
1341 0 : static void rv770_program_display_gap(struct radeon_device *rdev)
1342 : {
1343 0 : u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL);
1344 :
1345 0 : tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK);
1346 0 : if (rdev->pm.dpm.new_active_crtcs & 1) {
1347 0 : tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
1348 0 : tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
1349 0 : } else if (rdev->pm.dpm.new_active_crtcs & 2) {
1350 : tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
1351 0 : tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK);
1352 0 : } else {
1353 : tmp |= DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
1354 0 : tmp |= DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE);
1355 : }
1356 0 : WREG32(CG_DISPLAY_GAP_CNTL, tmp);
1357 0 : }
1358 :
1359 0 : static void rv770_enable_dynamic_pcie_gen2(struct radeon_device *rdev,
1360 : bool enable)
1361 : {
1362 0 : rv770_enable_bif_dynamic_pcie_gen2(rdev, enable);
1363 :
1364 0 : if (enable)
1365 0 : WREG32_P(GENERAL_PWRMGT, ENABLE_GEN2PCIE, ~ENABLE_GEN2PCIE);
1366 : else
1367 0 : WREG32_P(GENERAL_PWRMGT, 0, ~ENABLE_GEN2PCIE);
1368 0 : }
1369 :
1370 0 : static void r7xx_program_memory_timing_parameters(struct radeon_device *rdev,
1371 : struct radeon_ps *radeon_new_state)
1372 : {
1373 0 : if ((rdev->family == CHIP_RV730) ||
1374 0 : (rdev->family == CHIP_RV710) ||
1375 0 : (rdev->family == CHIP_RV740))
1376 0 : rv730_program_memory_timing_parameters(rdev, radeon_new_state);
1377 : else
1378 0 : rv770_program_memory_timing_parameters(rdev, radeon_new_state);
1379 0 : }
1380 :
1381 0 : static int rv770_upload_sw_state(struct radeon_device *rdev,
1382 : struct radeon_ps *radeon_new_state)
1383 : {
1384 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1385 0 : u16 address = pi->state_table_start +
1386 : offsetof(RV770_SMC_STATETABLE, driverState);
1387 0 : RV770_SMC_SWSTATE state = { 0 };
1388 : int ret;
1389 :
1390 0 : ret = rv770_convert_power_state_to_smc(rdev, radeon_new_state, &state);
1391 0 : if (ret)
1392 0 : return ret;
1393 :
1394 0 : return rv770_copy_bytes_to_smc(rdev, address, (const u8 *)&state,
1395 : sizeof(RV770_SMC_SWSTATE),
1396 0 : pi->sram_end);
1397 0 : }
1398 :
1399 0 : int rv770_halt_smc(struct radeon_device *rdev)
1400 : {
1401 0 : if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_Halt) != PPSMC_Result_OK)
1402 0 : return -EINVAL;
1403 :
1404 0 : if (rv770_wait_for_smc_inactive(rdev) != PPSMC_Result_OK)
1405 0 : return -EINVAL;
1406 :
1407 0 : return 0;
1408 0 : }
1409 :
1410 0 : int rv770_resume_smc(struct radeon_device *rdev)
1411 : {
1412 0 : if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_Resume) != PPSMC_Result_OK)
1413 0 : return -EINVAL;
1414 0 : return 0;
1415 0 : }
1416 :
1417 0 : int rv770_set_sw_state(struct radeon_device *rdev)
1418 : {
1419 0 : if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToSwState) != PPSMC_Result_OK)
1420 : DRM_DEBUG("rv770_set_sw_state failed\n");
1421 0 : return 0;
1422 : }
1423 :
1424 0 : int rv770_set_boot_state(struct radeon_device *rdev)
1425 : {
1426 0 : if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_SwitchToInitialState) != PPSMC_Result_OK)
1427 0 : return -EINVAL;
1428 0 : return 0;
1429 0 : }
1430 :
1431 0 : void rv770_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev,
1432 : struct radeon_ps *new_ps,
1433 : struct radeon_ps *old_ps)
1434 : {
1435 0 : struct rv7xx_ps *new_state = rv770_get_ps(new_ps);
1436 0 : struct rv7xx_ps *current_state = rv770_get_ps(old_ps);
1437 :
1438 0 : if ((new_ps->vclk == old_ps->vclk) &&
1439 0 : (new_ps->dclk == old_ps->dclk))
1440 0 : return;
1441 :
1442 0 : if (new_state->high.sclk >= current_state->high.sclk)
1443 0 : return;
1444 :
1445 0 : radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
1446 0 : }
1447 :
1448 0 : void rv770_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev,
1449 : struct radeon_ps *new_ps,
1450 : struct radeon_ps *old_ps)
1451 : {
1452 0 : struct rv7xx_ps *new_state = rv770_get_ps(new_ps);
1453 0 : struct rv7xx_ps *current_state = rv770_get_ps(old_ps);
1454 :
1455 0 : if ((new_ps->vclk == old_ps->vclk) &&
1456 0 : (new_ps->dclk == old_ps->dclk))
1457 0 : return;
1458 :
1459 0 : if (new_state->high.sclk < current_state->high.sclk)
1460 0 : return;
1461 :
1462 0 : radeon_set_uvd_clocks(rdev, new_ps->vclk, new_ps->dclk);
1463 0 : }
1464 :
1465 0 : int rv770_restrict_performance_levels_before_switch(struct radeon_device *rdev)
1466 : {
1467 0 : if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_NoForcedLevel)) != PPSMC_Result_OK)
1468 0 : return -EINVAL;
1469 :
1470 0 : if (rv770_send_msg_to_smc(rdev, (PPSMC_Msg)(PPSMC_MSG_TwoLevelsDisabled)) != PPSMC_Result_OK)
1471 0 : return -EINVAL;
1472 :
1473 0 : return 0;
1474 0 : }
1475 :
1476 0 : int rv770_dpm_force_performance_level(struct radeon_device *rdev,
1477 : enum radeon_dpm_forced_level level)
1478 : {
1479 : PPSMC_Msg msg;
1480 :
1481 0 : if (level == RADEON_DPM_FORCED_LEVEL_HIGH) {
1482 0 : if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_ZeroLevelsDisabled) != PPSMC_Result_OK)
1483 0 : return -EINVAL;
1484 : msg = PPSMC_MSG_ForceHigh;
1485 0 : } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) {
1486 0 : if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
1487 0 : return -EINVAL;
1488 : msg = (PPSMC_Msg)(PPSMC_MSG_TwoLevelsDisabled);
1489 0 : } else {
1490 0 : if (rv770_send_msg_to_smc(rdev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK)
1491 0 : return -EINVAL;
1492 : msg = (PPSMC_Msg)(PPSMC_MSG_ZeroLevelsDisabled);
1493 : }
1494 :
1495 0 : if (rv770_send_msg_to_smc(rdev, msg) != PPSMC_Result_OK)
1496 0 : return -EINVAL;
1497 :
1498 0 : rdev->pm.dpm.forced_level = level;
1499 :
1500 0 : return 0;
1501 0 : }
1502 :
1503 0 : void r7xx_start_smc(struct radeon_device *rdev)
1504 : {
1505 0 : rv770_start_smc(rdev);
1506 0 : rv770_start_smc_clock(rdev);
1507 0 : }
1508 :
1509 :
1510 0 : void r7xx_stop_smc(struct radeon_device *rdev)
1511 : {
1512 0 : rv770_reset_smc(rdev);
1513 0 : rv770_stop_smc_clock(rdev);
1514 0 : }
1515 :
1516 0 : static void rv770_read_clock_registers(struct radeon_device *rdev)
1517 : {
1518 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1519 :
1520 0 : pi->clk_regs.rv770.cg_spll_func_cntl =
1521 0 : RREG32(CG_SPLL_FUNC_CNTL);
1522 0 : pi->clk_regs.rv770.cg_spll_func_cntl_2 =
1523 0 : RREG32(CG_SPLL_FUNC_CNTL_2);
1524 0 : pi->clk_regs.rv770.cg_spll_func_cntl_3 =
1525 0 : RREG32(CG_SPLL_FUNC_CNTL_3);
1526 0 : pi->clk_regs.rv770.cg_spll_spread_spectrum =
1527 0 : RREG32(CG_SPLL_SPREAD_SPECTRUM);
1528 0 : pi->clk_regs.rv770.cg_spll_spread_spectrum_2 =
1529 0 : RREG32(CG_SPLL_SPREAD_SPECTRUM_2);
1530 0 : pi->clk_regs.rv770.mpll_ad_func_cntl =
1531 0 : RREG32(MPLL_AD_FUNC_CNTL);
1532 0 : pi->clk_regs.rv770.mpll_ad_func_cntl_2 =
1533 0 : RREG32(MPLL_AD_FUNC_CNTL_2);
1534 0 : pi->clk_regs.rv770.mpll_dq_func_cntl =
1535 0 : RREG32(MPLL_DQ_FUNC_CNTL);
1536 0 : pi->clk_regs.rv770.mpll_dq_func_cntl_2 =
1537 0 : RREG32(MPLL_DQ_FUNC_CNTL_2);
1538 0 : pi->clk_regs.rv770.mclk_pwrmgt_cntl =
1539 0 : RREG32(MCLK_PWRMGT_CNTL);
1540 0 : pi->clk_regs.rv770.dll_cntl = RREG32(DLL_CNTL);
1541 0 : }
1542 :
1543 0 : static void r7xx_read_clock_registers(struct radeon_device *rdev)
1544 : {
1545 0 : if (rdev->family == CHIP_RV740)
1546 0 : rv740_read_clock_registers(rdev);
1547 0 : else if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
1548 0 : rv730_read_clock_registers(rdev);
1549 : else
1550 0 : rv770_read_clock_registers(rdev);
1551 0 : }
1552 :
1553 0 : void rv770_read_voltage_smio_registers(struct radeon_device *rdev)
1554 : {
1555 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1556 :
1557 0 : pi->s0_vid_lower_smio_cntl =
1558 0 : RREG32(S0_VID_LOWER_SMIO_CNTL);
1559 0 : }
1560 :
1561 0 : void rv770_reset_smio_status(struct radeon_device *rdev)
1562 : {
1563 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1564 : u32 sw_smio_index, vid_smio_cntl;
1565 :
1566 : sw_smio_index =
1567 0 : (RREG32(GENERAL_PWRMGT) & SW_SMIO_INDEX_MASK) >> SW_SMIO_INDEX_SHIFT;
1568 0 : switch (sw_smio_index) {
1569 : case 3:
1570 0 : vid_smio_cntl = RREG32(S3_VID_LOWER_SMIO_CNTL);
1571 0 : break;
1572 : case 2:
1573 0 : vid_smio_cntl = RREG32(S2_VID_LOWER_SMIO_CNTL);
1574 0 : break;
1575 : case 1:
1576 0 : vid_smio_cntl = RREG32(S1_VID_LOWER_SMIO_CNTL);
1577 0 : break;
1578 : case 0:
1579 0 : return;
1580 : default:
1581 0 : vid_smio_cntl = pi->s0_vid_lower_smio_cntl;
1582 0 : break;
1583 : }
1584 :
1585 0 : WREG32(S0_VID_LOWER_SMIO_CNTL, vid_smio_cntl);
1586 0 : WREG32_P(GENERAL_PWRMGT, SW_SMIO_INDEX(0), ~SW_SMIO_INDEX_MASK);
1587 0 : }
1588 :
1589 0 : void rv770_get_memory_type(struct radeon_device *rdev)
1590 : {
1591 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1592 : u32 tmp;
1593 :
1594 0 : tmp = RREG32(MC_SEQ_MISC0);
1595 :
1596 0 : if (((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT) ==
1597 : MC_SEQ_MISC0_GDDR5_VALUE)
1598 0 : pi->mem_gddr5 = true;
1599 : else
1600 0 : pi->mem_gddr5 = false;
1601 :
1602 0 : }
1603 :
1604 0 : void rv770_get_pcie_gen2_status(struct radeon_device *rdev)
1605 : {
1606 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1607 : u32 tmp;
1608 :
1609 0 : tmp = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
1610 :
1611 0 : if ((tmp & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
1612 0 : (tmp & LC_OTHER_SIDE_SUPPORTS_GEN2))
1613 0 : pi->pcie_gen2 = true;
1614 : else
1615 0 : pi->pcie_gen2 = false;
1616 :
1617 0 : if (pi->pcie_gen2) {
1618 0 : if (tmp & LC_CURRENT_DATA_RATE)
1619 0 : pi->boot_in_gen2 = true;
1620 : else
1621 0 : pi->boot_in_gen2 = false;
1622 : } else
1623 0 : pi->boot_in_gen2 = false;
1624 0 : }
1625 :
1626 : #if 0
1627 : static int rv770_enter_ulp_state(struct radeon_device *rdev)
1628 : {
1629 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1630 :
1631 : if (pi->gfx_clock_gating) {
1632 : WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN);
1633 : WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON);
1634 : WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON);
1635 : RREG32(GB_TILING_CONFIG);
1636 : }
1637 :
1638 : WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_SwitchToMinimumPower),
1639 : ~HOST_SMC_MSG_MASK);
1640 :
1641 : udelay(7000);
1642 :
1643 : return 0;
1644 : }
1645 :
1646 : static int rv770_exit_ulp_state(struct radeon_device *rdev)
1647 : {
1648 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1649 : int i;
1650 :
1651 : WREG32_P(SMC_MSG, HOST_SMC_MSG(PPSMC_MSG_ResumeFromMinimumPower),
1652 : ~HOST_SMC_MSG_MASK);
1653 :
1654 : udelay(7000);
1655 :
1656 : for (i = 0; i < rdev->usec_timeout; i++) {
1657 : if (((RREG32(SMC_MSG) & HOST_SMC_RESP_MASK) >> HOST_SMC_RESP_SHIFT) == 1)
1658 : break;
1659 : udelay(1000);
1660 : }
1661 :
1662 : if (pi->gfx_clock_gating)
1663 : WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN);
1664 :
1665 : return 0;
1666 : }
1667 : #endif
1668 :
1669 0 : static void rv770_get_mclk_odt_threshold(struct radeon_device *rdev)
1670 : {
1671 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1672 : u8 memory_module_index;
1673 0 : struct atom_memory_info memory_info;
1674 :
1675 0 : pi->mclk_odt_threshold = 0;
1676 :
1677 0 : if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710)) {
1678 0 : memory_module_index = rv770_get_memory_module_index(rdev);
1679 :
1680 0 : if (radeon_atom_get_memory_info(rdev, memory_module_index, &memory_info))
1681 0 : return;
1682 :
1683 0 : if (memory_info.mem_type == MEM_TYPE_DDR2 ||
1684 0 : memory_info.mem_type == MEM_TYPE_DDR3)
1685 0 : pi->mclk_odt_threshold = 30000;
1686 : }
1687 0 : }
1688 :
1689 0 : void rv770_get_max_vddc(struct radeon_device *rdev)
1690 : {
1691 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1692 0 : u16 vddc;
1693 :
1694 0 : if (radeon_atom_get_max_vddc(rdev, 0, 0, &vddc))
1695 0 : pi->max_vddc = 0;
1696 : else
1697 0 : pi->max_vddc = vddc;
1698 0 : }
1699 :
1700 0 : void rv770_program_response_times(struct radeon_device *rdev)
1701 : {
1702 : u32 voltage_response_time, backbias_response_time;
1703 : u32 acpi_delay_time, vbi_time_out;
1704 : u32 vddc_dly, bb_dly, acpi_dly, vbi_dly;
1705 : u32 reference_clock;
1706 :
1707 0 : voltage_response_time = (u32)rdev->pm.dpm.voltage_response_time;
1708 0 : backbias_response_time = (u32)rdev->pm.dpm.backbias_response_time;
1709 :
1710 0 : if (voltage_response_time == 0)
1711 0 : voltage_response_time = 1000;
1712 :
1713 0 : if (backbias_response_time == 0)
1714 0 : backbias_response_time = 1000;
1715 :
1716 : acpi_delay_time = 15000;
1717 : vbi_time_out = 100000;
1718 :
1719 0 : reference_clock = radeon_get_xclk(rdev);
1720 :
1721 0 : vddc_dly = (voltage_response_time * reference_clock) / 1600;
1722 0 : bb_dly = (backbias_response_time * reference_clock) / 1600;
1723 0 : acpi_dly = (acpi_delay_time * reference_clock) / 1600;
1724 0 : vbi_dly = (vbi_time_out * reference_clock) / 1600;
1725 :
1726 0 : rv770_write_smc_soft_register(rdev,
1727 : RV770_SMC_SOFT_REGISTER_delay_vreg, vddc_dly);
1728 0 : rv770_write_smc_soft_register(rdev,
1729 : RV770_SMC_SOFT_REGISTER_delay_bbias, bb_dly);
1730 0 : rv770_write_smc_soft_register(rdev,
1731 : RV770_SMC_SOFT_REGISTER_delay_acpi, acpi_dly);
1732 0 : rv770_write_smc_soft_register(rdev,
1733 : RV770_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly);
1734 : #if 0
1735 : /* XXX look up hw revision */
1736 : if (WEKIVA_A21)
1737 : rv770_write_smc_soft_register(rdev,
1738 : RV770_SMC_SOFT_REGISTER_baby_step_timer,
1739 : 0x10);
1740 : #endif
1741 0 : }
1742 :
1743 0 : static void rv770_program_dcodt_before_state_switch(struct radeon_device *rdev,
1744 : struct radeon_ps *radeon_new_state,
1745 : struct radeon_ps *radeon_current_state)
1746 : {
1747 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1748 0 : struct rv7xx_ps *new_state = rv770_get_ps(radeon_new_state);
1749 0 : struct rv7xx_ps *current_state = rv770_get_ps(radeon_current_state);
1750 : bool current_use_dc = false;
1751 : bool new_use_dc = false;
1752 :
1753 0 : if (pi->mclk_odt_threshold == 0)
1754 0 : return;
1755 :
1756 0 : if (current_state->high.mclk <= pi->mclk_odt_threshold)
1757 0 : current_use_dc = true;
1758 :
1759 0 : if (new_state->high.mclk <= pi->mclk_odt_threshold)
1760 0 : new_use_dc = true;
1761 :
1762 0 : if (current_use_dc == new_use_dc)
1763 0 : return;
1764 :
1765 0 : if (!current_use_dc && new_use_dc)
1766 0 : return;
1767 :
1768 0 : if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
1769 0 : rv730_program_dcodt(rdev, new_use_dc);
1770 0 : }
1771 :
1772 0 : static void rv770_program_dcodt_after_state_switch(struct radeon_device *rdev,
1773 : struct radeon_ps *radeon_new_state,
1774 : struct radeon_ps *radeon_current_state)
1775 : {
1776 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1777 0 : struct rv7xx_ps *new_state = rv770_get_ps(radeon_new_state);
1778 0 : struct rv7xx_ps *current_state = rv770_get_ps(radeon_current_state);
1779 : bool current_use_dc = false;
1780 : bool new_use_dc = false;
1781 :
1782 0 : if (pi->mclk_odt_threshold == 0)
1783 0 : return;
1784 :
1785 0 : if (current_state->high.mclk <= pi->mclk_odt_threshold)
1786 0 : current_use_dc = true;
1787 :
1788 0 : if (new_state->high.mclk <= pi->mclk_odt_threshold)
1789 0 : new_use_dc = true;
1790 :
1791 0 : if (current_use_dc == new_use_dc)
1792 0 : return;
1793 :
1794 0 : if (current_use_dc && !new_use_dc)
1795 0 : return;
1796 :
1797 0 : if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
1798 0 : rv730_program_dcodt(rdev, new_use_dc);
1799 0 : }
1800 :
1801 0 : static void rv770_retrieve_odt_values(struct radeon_device *rdev)
1802 : {
1803 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1804 :
1805 0 : if (pi->mclk_odt_threshold == 0)
1806 0 : return;
1807 :
1808 0 : if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
1809 0 : rv730_get_odt_values(rdev);
1810 0 : }
1811 :
1812 0 : static void rv770_set_dpm_event_sources(struct radeon_device *rdev, u32 sources)
1813 : {
1814 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1815 : bool want_thermal_protection;
1816 : enum radeon_dpm_event_src dpm_event_src;
1817 :
1818 0 : switch (sources) {
1819 : case 0:
1820 : default:
1821 : want_thermal_protection = false;
1822 0 : break;
1823 : case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL):
1824 : want_thermal_protection = true;
1825 : dpm_event_src = RADEON_DPM_EVENT_SRC_DIGITAL;
1826 0 : break;
1827 :
1828 : case (1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL):
1829 : want_thermal_protection = true;
1830 : dpm_event_src = RADEON_DPM_EVENT_SRC_EXTERNAL;
1831 0 : break;
1832 :
1833 : case ((1 << RADEON_DPM_AUTO_THROTTLE_SRC_EXTERNAL) |
1834 : (1 << RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL)):
1835 : want_thermal_protection = true;
1836 : dpm_event_src = RADEON_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL;
1837 0 : break;
1838 : }
1839 :
1840 0 : if (want_thermal_protection) {
1841 0 : WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK);
1842 0 : if (pi->thermal_protection)
1843 0 : WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS);
1844 : } else {
1845 0 : WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS);
1846 : }
1847 0 : }
1848 :
1849 0 : void rv770_enable_auto_throttle_source(struct radeon_device *rdev,
1850 : enum radeon_dpm_auto_throttle_src source,
1851 : bool enable)
1852 : {
1853 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1854 :
1855 0 : if (enable) {
1856 0 : if (!(pi->active_auto_throttle_sources & (1 << source))) {
1857 0 : pi->active_auto_throttle_sources |= 1 << source;
1858 0 : rv770_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources);
1859 0 : }
1860 : } else {
1861 0 : if (pi->active_auto_throttle_sources & (1 << source)) {
1862 0 : pi->active_auto_throttle_sources &= ~(1 << source);
1863 0 : rv770_set_dpm_event_sources(rdev, pi->active_auto_throttle_sources);
1864 0 : }
1865 : }
1866 0 : }
1867 :
1868 0 : static int rv770_set_thermal_temperature_range(struct radeon_device *rdev,
1869 : int min_temp, int max_temp)
1870 : {
1871 : int low_temp = 0 * 1000;
1872 : int high_temp = 255 * 1000;
1873 :
1874 0 : if (low_temp < min_temp)
1875 0 : low_temp = min_temp;
1876 0 : if (high_temp > max_temp)
1877 0 : high_temp = max_temp;
1878 0 : if (high_temp < low_temp) {
1879 0 : DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp);
1880 0 : return -EINVAL;
1881 : }
1882 :
1883 0 : WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK);
1884 0 : WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK);
1885 0 : WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK);
1886 :
1887 0 : rdev->pm.dpm.thermal.min_temp = low_temp;
1888 0 : rdev->pm.dpm.thermal.max_temp = high_temp;
1889 :
1890 0 : return 0;
1891 0 : }
1892 :
1893 0 : int rv770_dpm_enable(struct radeon_device *rdev)
1894 : {
1895 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
1896 0 : struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
1897 : int ret;
1898 :
1899 0 : if (pi->gfx_clock_gating)
1900 0 : rv770_restore_cgcg(rdev);
1901 :
1902 0 : if (rv770_dpm_enabled(rdev))
1903 0 : return -EINVAL;
1904 :
1905 0 : if (pi->voltage_control) {
1906 0 : rv770_enable_voltage_control(rdev, true);
1907 0 : ret = rv770_construct_vddc_table(rdev);
1908 0 : if (ret) {
1909 0 : DRM_ERROR("rv770_construct_vddc_table failed\n");
1910 0 : return ret;
1911 : }
1912 : }
1913 :
1914 0 : if (pi->dcodt)
1915 0 : rv770_retrieve_odt_values(rdev);
1916 :
1917 0 : if (pi->mvdd_control) {
1918 0 : ret = rv770_get_mvdd_configuration(rdev);
1919 0 : if (ret) {
1920 0 : DRM_ERROR("rv770_get_mvdd_configuration failed\n");
1921 0 : return ret;
1922 : }
1923 : }
1924 :
1925 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS)
1926 0 : rv770_enable_backbias(rdev, true);
1927 :
1928 0 : rv770_enable_spread_spectrum(rdev, true);
1929 :
1930 0 : if (pi->thermal_protection)
1931 0 : rv770_enable_thermal_protection(rdev, true);
1932 :
1933 0 : rv770_program_mpll_timing_parameters(rdev);
1934 0 : rv770_setup_bsp(rdev);
1935 0 : rv770_program_git(rdev);
1936 0 : rv770_program_tp(rdev);
1937 0 : rv770_program_tpp(rdev);
1938 0 : rv770_program_sstp(rdev);
1939 0 : rv770_program_engine_speed_parameters(rdev);
1940 0 : rv770_enable_display_gap(rdev);
1941 0 : rv770_program_vc(rdev);
1942 :
1943 0 : if (pi->dynamic_pcie_gen2)
1944 0 : rv770_enable_dynamic_pcie_gen2(rdev, true);
1945 :
1946 0 : ret = rv770_upload_firmware(rdev);
1947 0 : if (ret) {
1948 0 : DRM_ERROR("rv770_upload_firmware failed\n");
1949 0 : return ret;
1950 : }
1951 0 : ret = rv770_init_smc_table(rdev, boot_ps);
1952 0 : if (ret) {
1953 0 : DRM_ERROR("rv770_init_smc_table failed\n");
1954 0 : return ret;
1955 : }
1956 :
1957 0 : rv770_program_response_times(rdev);
1958 0 : r7xx_start_smc(rdev);
1959 :
1960 0 : if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
1961 0 : rv730_start_dpm(rdev);
1962 : else
1963 0 : rv770_start_dpm(rdev);
1964 :
1965 0 : if (pi->gfx_clock_gating)
1966 0 : rv770_gfx_clock_gating_enable(rdev, true);
1967 :
1968 0 : if (pi->mg_clock_gating)
1969 0 : rv770_mg_clock_gating_enable(rdev, true);
1970 :
1971 0 : rv770_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true);
1972 :
1973 0 : return 0;
1974 0 : }
1975 :
1976 0 : int rv770_dpm_late_enable(struct radeon_device *rdev)
1977 : {
1978 : int ret;
1979 :
1980 0 : if (rdev->irq.installed &&
1981 0 : r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
1982 : PPSMC_Result result;
1983 :
1984 0 : ret = rv770_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
1985 0 : if (ret)
1986 0 : return ret;
1987 0 : rdev->irq.dpm_thermal = true;
1988 0 : radeon_irq_set(rdev);
1989 0 : result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_EnableThermalInterrupt);
1990 :
1991 0 : if (result != PPSMC_Result_OK)
1992 : DRM_DEBUG_KMS("Could not enable thermal interrupts.\n");
1993 0 : }
1994 :
1995 0 : return 0;
1996 0 : }
1997 :
1998 0 : void rv770_dpm_disable(struct radeon_device *rdev)
1999 : {
2000 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
2001 :
2002 0 : if (!rv770_dpm_enabled(rdev))
2003 0 : return;
2004 :
2005 0 : rv770_clear_vc(rdev);
2006 :
2007 0 : if (pi->thermal_protection)
2008 0 : rv770_enable_thermal_protection(rdev, false);
2009 :
2010 0 : rv770_enable_spread_spectrum(rdev, false);
2011 :
2012 0 : if (pi->dynamic_pcie_gen2)
2013 0 : rv770_enable_dynamic_pcie_gen2(rdev, false);
2014 :
2015 0 : if (rdev->irq.installed &&
2016 0 : r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
2017 0 : rdev->irq.dpm_thermal = false;
2018 0 : radeon_irq_set(rdev);
2019 0 : }
2020 :
2021 0 : if (pi->gfx_clock_gating)
2022 0 : rv770_gfx_clock_gating_enable(rdev, false);
2023 :
2024 0 : if (pi->mg_clock_gating)
2025 0 : rv770_mg_clock_gating_enable(rdev, false);
2026 :
2027 0 : if ((rdev->family == CHIP_RV730) || (rdev->family == CHIP_RV710))
2028 0 : rv730_stop_dpm(rdev);
2029 : else
2030 0 : rv770_stop_dpm(rdev);
2031 :
2032 0 : r7xx_stop_smc(rdev);
2033 0 : rv770_reset_smio_status(rdev);
2034 0 : }
2035 :
2036 0 : int rv770_dpm_set_power_state(struct radeon_device *rdev)
2037 : {
2038 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
2039 0 : struct radeon_ps *new_ps = rdev->pm.dpm.requested_ps;
2040 0 : struct radeon_ps *old_ps = rdev->pm.dpm.current_ps;
2041 : int ret;
2042 :
2043 0 : ret = rv770_restrict_performance_levels_before_switch(rdev);
2044 0 : if (ret) {
2045 0 : DRM_ERROR("rv770_restrict_performance_levels_before_switch failed\n");
2046 0 : return ret;
2047 : }
2048 0 : rv770_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps);
2049 0 : ret = rv770_halt_smc(rdev);
2050 0 : if (ret) {
2051 0 : DRM_ERROR("rv770_halt_smc failed\n");
2052 0 : return ret;
2053 : }
2054 0 : ret = rv770_upload_sw_state(rdev, new_ps);
2055 0 : if (ret) {
2056 0 : DRM_ERROR("rv770_upload_sw_state failed\n");
2057 0 : return ret;
2058 : }
2059 0 : r7xx_program_memory_timing_parameters(rdev, new_ps);
2060 0 : if (pi->dcodt)
2061 0 : rv770_program_dcodt_before_state_switch(rdev, new_ps, old_ps);
2062 0 : ret = rv770_resume_smc(rdev);
2063 0 : if (ret) {
2064 0 : DRM_ERROR("rv770_resume_smc failed\n");
2065 0 : return ret;
2066 : }
2067 0 : ret = rv770_set_sw_state(rdev);
2068 0 : if (ret) {
2069 0 : DRM_ERROR("rv770_set_sw_state failed\n");
2070 0 : return ret;
2071 : }
2072 0 : if (pi->dcodt)
2073 0 : rv770_program_dcodt_after_state_switch(rdev, new_ps, old_ps);
2074 0 : rv770_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps);
2075 :
2076 0 : return 0;
2077 0 : }
2078 :
2079 : #if 0
2080 : void rv770_dpm_reset_asic(struct radeon_device *rdev)
2081 : {
2082 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
2083 : struct radeon_ps *boot_ps = rdev->pm.dpm.boot_ps;
2084 :
2085 : rv770_restrict_performance_levels_before_switch(rdev);
2086 : if (pi->dcodt)
2087 : rv770_program_dcodt_before_state_switch(rdev, boot_ps, boot_ps);
2088 : rv770_set_boot_state(rdev);
2089 : if (pi->dcodt)
2090 : rv770_program_dcodt_after_state_switch(rdev, boot_ps, boot_ps);
2091 : }
2092 : #endif
2093 :
2094 0 : void rv770_dpm_setup_asic(struct radeon_device *rdev)
2095 : {
2096 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
2097 :
2098 0 : r7xx_read_clock_registers(rdev);
2099 0 : rv770_read_voltage_smio_registers(rdev);
2100 0 : rv770_get_memory_type(rdev);
2101 0 : if (pi->dcodt)
2102 0 : rv770_get_mclk_odt_threshold(rdev);
2103 0 : rv770_get_pcie_gen2_status(rdev);
2104 :
2105 0 : rv770_enable_acpi_pm(rdev);
2106 :
2107 0 : if (radeon_aspm != 0) {
2108 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s)
2109 0 : rv770_enable_l0s(rdev);
2110 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1)
2111 0 : rv770_enable_l1(rdev);
2112 0 : if (rdev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1)
2113 0 : rv770_enable_pll_sleep_in_l1(rdev);
2114 : }
2115 0 : }
2116 :
2117 0 : void rv770_dpm_display_configuration_changed(struct radeon_device *rdev)
2118 : {
2119 0 : rv770_program_display_gap(rdev);
2120 0 : }
2121 :
2122 : union power_info {
2123 : struct _ATOM_POWERPLAY_INFO info;
2124 : struct _ATOM_POWERPLAY_INFO_V2 info_2;
2125 : struct _ATOM_POWERPLAY_INFO_V3 info_3;
2126 : struct _ATOM_PPLIB_POWERPLAYTABLE pplib;
2127 : struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2;
2128 : struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3;
2129 : };
2130 :
2131 : union pplib_clock_info {
2132 : struct _ATOM_PPLIB_R600_CLOCK_INFO r600;
2133 : struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780;
2134 : struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen;
2135 : struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo;
2136 : };
2137 :
2138 : union pplib_power_state {
2139 : struct _ATOM_PPLIB_STATE v1;
2140 : struct _ATOM_PPLIB_STATE_V2 v2;
2141 : };
2142 :
2143 0 : static void rv7xx_parse_pplib_non_clock_info(struct radeon_device *rdev,
2144 : struct radeon_ps *rps,
2145 : struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info,
2146 : u8 table_rev)
2147 : {
2148 0 : rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings);
2149 0 : rps->class = le16_to_cpu(non_clock_info->usClassification);
2150 0 : rps->class2 = le16_to_cpu(non_clock_info->usClassification2);
2151 :
2152 0 : if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) {
2153 0 : rps->vclk = le32_to_cpu(non_clock_info->ulVCLK);
2154 0 : rps->dclk = le32_to_cpu(non_clock_info->ulDCLK);
2155 0 : } else {
2156 0 : rps->vclk = 0;
2157 0 : rps->dclk = 0;
2158 : }
2159 :
2160 0 : if (r600_is_uvd_state(rps->class, rps->class2)) {
2161 0 : if ((rps->vclk == 0) || (rps->dclk == 0)) {
2162 0 : rps->vclk = RV770_DEFAULT_VCLK_FREQ;
2163 0 : rps->dclk = RV770_DEFAULT_DCLK_FREQ;
2164 0 : }
2165 : }
2166 :
2167 0 : if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT)
2168 0 : rdev->pm.dpm.boot_ps = rps;
2169 0 : if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)
2170 0 : rdev->pm.dpm.uvd_ps = rps;
2171 0 : }
2172 :
2173 0 : static void rv7xx_parse_pplib_clock_info(struct radeon_device *rdev,
2174 : struct radeon_ps *rps, int index,
2175 : union pplib_clock_info *clock_info)
2176 : {
2177 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
2178 0 : struct evergreen_power_info *eg_pi = evergreen_get_pi(rdev);
2179 0 : struct rv7xx_ps *ps = rv770_get_ps(rps);
2180 : u32 sclk, mclk;
2181 : struct rv7xx_pl *pl;
2182 :
2183 0 : switch (index) {
2184 : case 0:
2185 0 : pl = &ps->low;
2186 0 : break;
2187 : case 1:
2188 0 : pl = &ps->medium;
2189 0 : break;
2190 : case 2:
2191 : default:
2192 0 : pl = &ps->high;
2193 0 : break;
2194 : }
2195 :
2196 0 : if (rdev->family >= CHIP_CEDAR) {
2197 0 : sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
2198 0 : sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
2199 0 : mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
2200 0 : mclk |= clock_info->evergreen.ucMemoryClockHigh << 16;
2201 :
2202 0 : pl->vddc = le16_to_cpu(clock_info->evergreen.usVDDC);
2203 0 : pl->vddci = le16_to_cpu(clock_info->evergreen.usVDDCI);
2204 0 : pl->flags = le32_to_cpu(clock_info->evergreen.ulFlags);
2205 0 : } else {
2206 0 : sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
2207 0 : sclk |= clock_info->r600.ucEngineClockHigh << 16;
2208 0 : mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow);
2209 0 : mclk |= clock_info->r600.ucMemoryClockHigh << 16;
2210 :
2211 0 : pl->vddc = le16_to_cpu(clock_info->r600.usVDDC);
2212 0 : pl->flags = le32_to_cpu(clock_info->r600.ulFlags);
2213 : }
2214 :
2215 0 : pl->mclk = mclk;
2216 0 : pl->sclk = sclk;
2217 :
2218 : /* patch up vddc if necessary */
2219 0 : if (pl->vddc == 0xff01) {
2220 0 : if (pi->max_vddc)
2221 0 : pl->vddc = pi->max_vddc;
2222 : }
2223 :
2224 0 : if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) {
2225 0 : pi->acpi_vddc = pl->vddc;
2226 0 : if (rdev->family >= CHIP_CEDAR)
2227 0 : eg_pi->acpi_vddci = pl->vddci;
2228 0 : if (ps->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2)
2229 0 : pi->acpi_pcie_gen2 = true;
2230 : else
2231 0 : pi->acpi_pcie_gen2 = false;
2232 : }
2233 :
2234 0 : if (rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) {
2235 0 : if (rdev->family >= CHIP_BARTS) {
2236 0 : eg_pi->ulv.supported = true;
2237 0 : eg_pi->ulv.pl = pl;
2238 0 : }
2239 : }
2240 :
2241 0 : if (pi->min_vddc_in_table > pl->vddc)
2242 0 : pi->min_vddc_in_table = pl->vddc;
2243 :
2244 0 : if (pi->max_vddc_in_table < pl->vddc)
2245 0 : pi->max_vddc_in_table = pl->vddc;
2246 :
2247 : /* patch up boot state */
2248 0 : if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) {
2249 0 : u16 vddc, vddci, mvdd;
2250 0 : radeon_atombios_get_default_voltages(rdev, &vddc, &vddci, &mvdd);
2251 0 : pl->mclk = rdev->clock.default_mclk;
2252 0 : pl->sclk = rdev->clock.default_sclk;
2253 0 : pl->vddc = vddc;
2254 0 : pl->vddci = vddci;
2255 0 : }
2256 :
2257 0 : if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) ==
2258 : ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) {
2259 0 : rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk;
2260 0 : rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk;
2261 0 : rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc;
2262 0 : rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci;
2263 0 : }
2264 0 : }
2265 :
2266 0 : int rv7xx_parse_power_table(struct radeon_device *rdev)
2267 : {
2268 0 : struct radeon_mode_info *mode_info = &rdev->mode_info;
2269 : struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info;
2270 : union pplib_power_state *power_state;
2271 : int i, j;
2272 : union pplib_clock_info *clock_info;
2273 : union power_info *power_info;
2274 : int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
2275 0 : u16 data_offset;
2276 0 : u8 frev, crev;
2277 : struct rv7xx_ps *ps;
2278 :
2279 0 : if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
2280 : &frev, &crev, &data_offset))
2281 0 : return -EINVAL;
2282 0 : power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
2283 :
2284 0 : rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
2285 0 : power_info->pplib.ucNumStates, GFP_KERNEL);
2286 0 : if (!rdev->pm.dpm.ps)
2287 0 : return -ENOMEM;
2288 :
2289 0 : for (i = 0; i < power_info->pplib.ucNumStates; i++) {
2290 0 : power_state = (union pplib_power_state *)
2291 0 : (mode_info->atom_context->bios + data_offset +
2292 0 : le16_to_cpu(power_info->pplib.usStateArrayOffset) +
2293 0 : i * power_info->pplib.ucStateEntrySize);
2294 0 : non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
2295 0 : (mode_info->atom_context->bios + data_offset +
2296 0 : le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
2297 0 : (power_state->v1.ucNonClockStateIndex *
2298 0 : power_info->pplib.ucNonClockSize));
2299 0 : if (power_info->pplib.ucStateEntrySize - 1) {
2300 : u8 *idx;
2301 0 : ps = kzalloc(sizeof(struct rv7xx_ps), GFP_KERNEL);
2302 0 : if (ps == NULL) {
2303 0 : kfree(rdev->pm.dpm.ps);
2304 0 : return -ENOMEM;
2305 : }
2306 0 : rdev->pm.dpm.ps[i].ps_priv = ps;
2307 0 : rv7xx_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
2308 : non_clock_info,
2309 0 : power_info->pplib.ucNonClockSize);
2310 0 : idx = (u8 *)&power_state->v1.ucClockStateIndices[0];
2311 0 : for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
2312 0 : clock_info = (union pplib_clock_info *)
2313 0 : (mode_info->atom_context->bios + data_offset +
2314 0 : le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
2315 0 : (idx[j] * power_info->pplib.ucClockInfoSize));
2316 0 : rv7xx_parse_pplib_clock_info(rdev,
2317 0 : &rdev->pm.dpm.ps[i], j,
2318 : clock_info);
2319 : }
2320 0 : }
2321 : }
2322 0 : rdev->pm.dpm.num_ps = power_info->pplib.ucNumStates;
2323 0 : return 0;
2324 0 : }
2325 :
2326 0 : void rv770_get_engine_memory_ss(struct radeon_device *rdev)
2327 : {
2328 0 : struct rv7xx_power_info *pi = rv770_get_pi(rdev);
2329 0 : struct radeon_atom_ss ss;
2330 :
2331 0 : pi->sclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
2332 : ASIC_INTERNAL_ENGINE_SS, 0);
2333 0 : pi->mclk_ss = radeon_atombios_get_asic_ss_info(rdev, &ss,
2334 : ASIC_INTERNAL_MEMORY_SS, 0);
2335 :
2336 0 : if (pi->sclk_ss || pi->mclk_ss)
2337 0 : pi->dynamic_ss = true;
2338 : else
2339 0 : pi->dynamic_ss = false;
2340 0 : }
2341 :
2342 0 : int rv770_dpm_init(struct radeon_device *rdev)
2343 : {
2344 : struct rv7xx_power_info *pi;
2345 0 : struct atom_clock_dividers dividers;
2346 : int ret;
2347 :
2348 0 : pi = kzalloc(sizeof(struct rv7xx_power_info), GFP_KERNEL);
2349 0 : if (pi == NULL)
2350 0 : return -ENOMEM;
2351 0 : rdev->pm.dpm.priv = pi;
2352 :
2353 0 : rv770_get_max_vddc(rdev);
2354 :
2355 0 : pi->acpi_vddc = 0;
2356 0 : pi->min_vddc_in_table = 0;
2357 0 : pi->max_vddc_in_table = 0;
2358 :
2359 0 : ret = r600_get_platform_caps(rdev);
2360 0 : if (ret)
2361 0 : return ret;
2362 :
2363 0 : ret = rv7xx_parse_power_table(rdev);
2364 0 : if (ret)
2365 0 : return ret;
2366 :
2367 0 : if (rdev->pm.dpm.voltage_response_time == 0)
2368 0 : rdev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT;
2369 0 : if (rdev->pm.dpm.backbias_response_time == 0)
2370 0 : rdev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT;
2371 :
2372 0 : ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
2373 : 0, false, ÷rs);
2374 0 : if (ret)
2375 0 : pi->ref_div = dividers.ref_div + 1;
2376 : else
2377 0 : pi->ref_div = R600_REFERENCEDIVIDER_DFLT;
2378 :
2379 0 : pi->mclk_strobe_mode_threshold = 30000;
2380 0 : pi->mclk_edc_enable_threshold = 30000;
2381 :
2382 0 : pi->rlp = RV770_RLP_DFLT;
2383 0 : pi->rmp = RV770_RMP_DFLT;
2384 0 : pi->lhp = RV770_LHP_DFLT;
2385 0 : pi->lmp = RV770_LMP_DFLT;
2386 :
2387 0 : pi->voltage_control =
2388 0 : radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_VDDC, 0);
2389 :
2390 0 : pi->mvdd_control =
2391 0 : radeon_atom_is_voltage_gpio(rdev, SET_VOLTAGE_TYPE_ASIC_MVDDC, 0);
2392 :
2393 0 : rv770_get_engine_memory_ss(rdev);
2394 :
2395 0 : pi->asi = RV770_ASI_DFLT;
2396 0 : pi->pasi = RV770_HASI_DFLT;
2397 0 : pi->vrc = RV770_VRC_DFLT;
2398 :
2399 0 : pi->power_gating = false;
2400 :
2401 0 : pi->gfx_clock_gating = true;
2402 :
2403 0 : pi->mg_clock_gating = true;
2404 0 : pi->mgcgtssm = true;
2405 :
2406 0 : pi->dynamic_pcie_gen2 = true;
2407 :
2408 0 : if (rdev->pm.int_thermal_type != THERMAL_TYPE_NONE)
2409 0 : pi->thermal_protection = true;
2410 : else
2411 0 : pi->thermal_protection = false;
2412 :
2413 0 : pi->display_gap = true;
2414 :
2415 0 : if (rdev->flags & RADEON_IS_MOBILITY)
2416 0 : pi->dcodt = true;
2417 : else
2418 0 : pi->dcodt = false;
2419 :
2420 0 : pi->ulps = true;
2421 :
2422 0 : pi->mclk_stutter_mode_threshold = 0;
2423 :
2424 0 : pi->sram_end = SMC_RAM_END;
2425 0 : pi->state_table_start = RV770_SMC_TABLE_ADDRESS;
2426 0 : pi->soft_regs_start = RV770_SMC_SOFT_REGISTERS_START;
2427 :
2428 0 : return 0;
2429 0 : }
2430 :
2431 0 : void rv770_dpm_print_power_state(struct radeon_device *rdev,
2432 : struct radeon_ps *rps)
2433 : {
2434 0 : struct rv7xx_ps *ps = rv770_get_ps(rps);
2435 : struct rv7xx_pl *pl;
2436 :
2437 0 : r600_dpm_print_class_info(rps->class, rps->class2);
2438 0 : r600_dpm_print_cap_info(rps->caps);
2439 0 : printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
2440 0 : if (rdev->family >= CHIP_CEDAR) {
2441 : pl = &ps->low;
2442 0 : printk("\t\tpower level 0 sclk: %u mclk: %u vddc: %u vddci: %u\n",
2443 : pl->sclk, pl->mclk, pl->vddc, pl->vddci);
2444 0 : pl = &ps->medium;
2445 0 : printk("\t\tpower level 1 sclk: %u mclk: %u vddc: %u vddci: %u\n",
2446 : pl->sclk, pl->mclk, pl->vddc, pl->vddci);
2447 0 : pl = &ps->high;
2448 0 : printk("\t\tpower level 2 sclk: %u mclk: %u vddc: %u vddci: %u\n",
2449 : pl->sclk, pl->mclk, pl->vddc, pl->vddci);
2450 0 : } else {
2451 : pl = &ps->low;
2452 0 : printk("\t\tpower level 0 sclk: %u mclk: %u vddc: %u\n",
2453 : pl->sclk, pl->mclk, pl->vddc);
2454 0 : pl = &ps->medium;
2455 0 : printk("\t\tpower level 1 sclk: %u mclk: %u vddc: %u\n",
2456 : pl->sclk, pl->mclk, pl->vddc);
2457 0 : pl = &ps->high;
2458 0 : printk("\t\tpower level 2 sclk: %u mclk: %u vddc: %u\n",
2459 : pl->sclk, pl->mclk, pl->vddc);
2460 : }
2461 0 : r600_dpm_print_ps_status(rdev, rps);
2462 0 : }
2463 :
2464 0 : void rv770_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev,
2465 : struct seq_file *m)
2466 : {
2467 0 : struct radeon_ps *rps = rdev->pm.dpm.current_ps;
2468 0 : struct rv7xx_ps *ps = rv770_get_ps(rps);
2469 : struct rv7xx_pl *pl;
2470 : u32 current_index =
2471 0 : (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
2472 : CURRENT_PROFILE_INDEX_SHIFT;
2473 :
2474 0 : if (current_index > 2) {
2475 0 : seq_printf(m, "invalid dpm profile %d\n", current_index);
2476 0 : } else {
2477 0 : if (current_index == 0)
2478 0 : pl = &ps->low;
2479 0 : else if (current_index == 1)
2480 0 : pl = &ps->medium;
2481 : else /* current_index == 2 */
2482 0 : pl = &ps->high;
2483 0 : seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk);
2484 0 : if (rdev->family >= CHIP_CEDAR) {
2485 0 : seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u\n",
2486 0 : current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci);
2487 0 : } else {
2488 0 : seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u\n",
2489 : current_index, pl->sclk, pl->mclk, pl->vddc);
2490 : }
2491 : }
2492 0 : }
2493 :
2494 0 : u32 rv770_dpm_get_current_sclk(struct radeon_device *rdev)
2495 : {
2496 0 : struct radeon_ps *rps = rdev->pm.dpm.current_ps;
2497 0 : struct rv7xx_ps *ps = rv770_get_ps(rps);
2498 : struct rv7xx_pl *pl;
2499 : u32 current_index =
2500 0 : (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
2501 : CURRENT_PROFILE_INDEX_SHIFT;
2502 :
2503 0 : if (current_index > 2) {
2504 0 : return 0;
2505 : } else {
2506 0 : if (current_index == 0)
2507 0 : pl = &ps->low;
2508 0 : else if (current_index == 1)
2509 0 : pl = &ps->medium;
2510 : else /* current_index == 2 */
2511 0 : pl = &ps->high;
2512 0 : return pl->sclk;
2513 : }
2514 0 : }
2515 :
2516 0 : u32 rv770_dpm_get_current_mclk(struct radeon_device *rdev)
2517 : {
2518 0 : struct radeon_ps *rps = rdev->pm.dpm.current_ps;
2519 0 : struct rv7xx_ps *ps = rv770_get_ps(rps);
2520 : struct rv7xx_pl *pl;
2521 : u32 current_index =
2522 0 : (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_PROFILE_INDEX_MASK) >>
2523 : CURRENT_PROFILE_INDEX_SHIFT;
2524 :
2525 0 : if (current_index > 2) {
2526 0 : return 0;
2527 : } else {
2528 0 : if (current_index == 0)
2529 0 : pl = &ps->low;
2530 0 : else if (current_index == 1)
2531 0 : pl = &ps->medium;
2532 : else /* current_index == 2 */
2533 0 : pl = &ps->high;
2534 0 : return pl->mclk;
2535 : }
2536 0 : }
2537 :
2538 0 : void rv770_dpm_fini(struct radeon_device *rdev)
2539 : {
2540 : int i;
2541 :
2542 0 : for (i = 0; i < rdev->pm.dpm.num_ps; i++) {
2543 0 : kfree(rdev->pm.dpm.ps[i].ps_priv);
2544 : }
2545 0 : kfree(rdev->pm.dpm.ps);
2546 0 : kfree(rdev->pm.dpm.priv);
2547 0 : }
2548 :
2549 0 : u32 rv770_dpm_get_sclk(struct radeon_device *rdev, bool low)
2550 : {
2551 0 : struct rv7xx_ps *requested_state = rv770_get_ps(rdev->pm.dpm.requested_ps);
2552 :
2553 0 : if (low)
2554 0 : return requested_state->low.sclk;
2555 : else
2556 0 : return requested_state->high.sclk;
2557 0 : }
2558 :
2559 0 : u32 rv770_dpm_get_mclk(struct radeon_device *rdev, bool low)
2560 : {
2561 0 : struct rv7xx_ps *requested_state = rv770_get_ps(rdev->pm.dpm.requested_ps);
2562 :
2563 0 : if (low)
2564 0 : return requested_state->low.mclk;
2565 : else
2566 0 : return requested_state->high.mclk;
2567 0 : }
2568 :
2569 0 : bool rv770_dpm_vblank_too_short(struct radeon_device *rdev)
2570 : {
2571 0 : u32 vblank_time = r600_dpm_get_vblank_time(rdev);
2572 : u32 switch_limit = 200; /* 300 */
2573 :
2574 : /* RV770 */
2575 : /* mclk switching doesn't seem to work reliably on desktop RV770s */
2576 0 : if ((rdev->family == CHIP_RV770) &&
2577 0 : !(rdev->flags & RADEON_IS_MOBILITY))
2578 0 : switch_limit = 0xffffffff; /* disable mclk switching */
2579 :
2580 0 : if (vblank_time < switch_limit)
2581 0 : return true;
2582 : else
2583 0 : return false;
2584 :
2585 0 : }
|