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 "radeon.h" |
26 | #include "rv730d.h" |
27 | #include "r600_dpm.h" |
28 | #include "rv770.h" |
29 | #include "rv770_dpm.h" |
30 | #include "atom.h" |
31 | |
32 | #define MC_CG_ARB_FREQ_F0 0x0a |
33 | #define MC_CG_ARB_FREQ_F1 0x0b |
34 | #define MC_CG_ARB_FREQ_F2 0x0c |
35 | #define MC_CG_ARB_FREQ_F3 0x0d |
36 | |
37 | int rv730_populate_sclk_value(struct radeon_device *rdev, |
38 | u32 engine_clock, |
39 | RV770_SMC_SCLK_VALUE *sclk) |
40 | { |
41 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
42 | struct atom_clock_dividers dividers; |
43 | u32 spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl; |
44 | u32 spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2; |
45 | u32 spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3; |
46 | u32 cg_spll_spread_spectrum = pi->clk_regs.rv730.cg_spll_spread_spectrum; |
47 | u32 cg_spll_spread_spectrum_2 = pi->clk_regs.rv730.cg_spll_spread_spectrum_2; |
48 | u64 tmp; |
49 | u32 reference_clock = rdev->clock.spll.reference_freq; |
50 | u32 reference_divider, post_divider; |
51 | u32 fbdiv; |
52 | int ret; |
53 | |
54 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, |
55 | clock: engine_clock, strobe_mode: false, dividers: ÷rs); |
56 | if (ret) |
57 | return ret; |
58 | |
59 | reference_divider = 1 + dividers.ref_div; |
60 | |
61 | if (dividers.enable_post_div) |
62 | post_divider = ((dividers.post_div >> 4) & 0xf) + |
63 | (dividers.post_div & 0xf) + 2; |
64 | else |
65 | post_divider = 1; |
66 | |
67 | tmp = (u64) engine_clock * reference_divider * post_divider * 16384; |
68 | do_div(tmp, reference_clock); |
69 | fbdiv = (u32) tmp; |
70 | |
71 | /* set up registers */ |
72 | if (dividers.enable_post_div) |
73 | spll_func_cntl |= SPLL_DIVEN; |
74 | else |
75 | spll_func_cntl &= ~SPLL_DIVEN; |
76 | spll_func_cntl &= ~(SPLL_HILEN_MASK | SPLL_LOLEN_MASK | SPLL_REF_DIV_MASK); |
77 | spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); |
78 | spll_func_cntl |= SPLL_HILEN((dividers.post_div >> 4) & 0xf); |
79 | spll_func_cntl |= SPLL_LOLEN(dividers.post_div & 0xf); |
80 | |
81 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; |
82 | spll_func_cntl_2 |= SCLK_MUX_SEL(2); |
83 | |
84 | spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; |
85 | spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); |
86 | spll_func_cntl_3 |= SPLL_DITHEN; |
87 | |
88 | if (pi->sclk_ss) { |
89 | struct radeon_atom_ss ss; |
90 | u32 vco_freq = engine_clock * post_divider; |
91 | |
92 | if (radeon_atombios_get_asic_ss_info(rdev, ss: &ss, |
93 | ASIC_INTERNAL_ENGINE_SS, clock: vco_freq)) { |
94 | u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); |
95 | u32 clk_v = ss.percentage * fbdiv / (clk_s * 10000); |
96 | |
97 | cg_spll_spread_spectrum &= ~CLK_S_MASK; |
98 | cg_spll_spread_spectrum |= CLK_S(clk_s); |
99 | cg_spll_spread_spectrum |= SSEN; |
100 | |
101 | cg_spll_spread_spectrum_2 &= ~CLK_V_MASK; |
102 | cg_spll_spread_spectrum_2 |= CLK_V(clk_v); |
103 | } |
104 | } |
105 | |
106 | sclk->sclk_value = cpu_to_be32(engine_clock); |
107 | sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); |
108 | sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); |
109 | sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); |
110 | sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(cg_spll_spread_spectrum); |
111 | sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(cg_spll_spread_spectrum_2); |
112 | |
113 | return 0; |
114 | } |
115 | |
116 | int rv730_populate_mclk_value(struct radeon_device *rdev, |
117 | u32 engine_clock, u32 memory_clock, |
118 | LPRV7XX_SMC_MCLK_VALUE mclk) |
119 | { |
120 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
121 | u32 mclk_pwrmgt_cntl = pi->clk_regs.rv730.mclk_pwrmgt_cntl; |
122 | u32 dll_cntl = pi->clk_regs.rv730.dll_cntl; |
123 | u32 mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl; |
124 | u32 mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2; |
125 | u32 mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3; |
126 | u32 mpll_ss = pi->clk_regs.rv730.mpll_ss; |
127 | u32 mpll_ss2 = pi->clk_regs.rv730.mpll_ss2; |
128 | struct atom_clock_dividers dividers; |
129 | u32 post_divider, reference_divider; |
130 | int ret; |
131 | |
132 | ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_MEMORY_PLL_PARAM, |
133 | clock: memory_clock, strobe_mode: false, dividers: ÷rs); |
134 | if (ret) |
135 | return ret; |
136 | |
137 | reference_divider = dividers.ref_div + 1; |
138 | |
139 | if (dividers.enable_post_div) |
140 | post_divider = ((dividers.post_div >> 4) & 0xf) + |
141 | (dividers.post_div & 0xf) + 2; |
142 | else |
143 | post_divider = 1; |
144 | |
145 | /* setup the registers */ |
146 | if (dividers.enable_post_div) |
147 | mpll_func_cntl |= MPLL_DIVEN; |
148 | else |
149 | mpll_func_cntl &= ~MPLL_DIVEN; |
150 | |
151 | mpll_func_cntl &= ~(MPLL_REF_DIV_MASK | MPLL_HILEN_MASK | MPLL_LOLEN_MASK); |
152 | mpll_func_cntl |= MPLL_REF_DIV(dividers.ref_div); |
153 | mpll_func_cntl |= MPLL_HILEN((dividers.post_div >> 4) & 0xf); |
154 | mpll_func_cntl |= MPLL_LOLEN(dividers.post_div & 0xf); |
155 | |
156 | mpll_func_cntl_3 &= ~MPLL_FB_DIV_MASK; |
157 | mpll_func_cntl_3 |= MPLL_FB_DIV(dividers.fb_div); |
158 | if (dividers.enable_dithen) |
159 | mpll_func_cntl_3 |= MPLL_DITHEN; |
160 | else |
161 | mpll_func_cntl_3 &= ~MPLL_DITHEN; |
162 | |
163 | if (pi->mclk_ss) { |
164 | struct radeon_atom_ss ss; |
165 | u32 vco_freq = memory_clock * post_divider; |
166 | |
167 | if (radeon_atombios_get_asic_ss_info(rdev, ss: &ss, |
168 | ASIC_INTERNAL_MEMORY_SS, clock: vco_freq)) { |
169 | u32 reference_clock = rdev->clock.mpll.reference_freq; |
170 | u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); |
171 | u32 clk_v = ss.percentage * dividers.fb_div / (clk_s * 10000); |
172 | |
173 | mpll_ss &= ~CLK_S_MASK; |
174 | mpll_ss |= CLK_S(clk_s); |
175 | mpll_ss |= SSEN; |
176 | |
177 | mpll_ss2 &= ~CLK_V_MASK; |
178 | mpll_ss |= CLK_V(clk_v); |
179 | } |
180 | } |
181 | |
182 | |
183 | mclk->mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); |
184 | mclk->mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl); |
185 | mclk->mclk730.mclk_value = cpu_to_be32(memory_clock); |
186 | mclk->mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); |
187 | mclk->mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2); |
188 | mclk->mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3); |
189 | mclk->mclk730.vMPLL_SS = cpu_to_be32(mpll_ss); |
190 | mclk->mclk730.vMPLL_SS2 = cpu_to_be32(mpll_ss2); |
191 | |
192 | return 0; |
193 | } |
194 | |
195 | void rv730_read_clock_registers(struct radeon_device *rdev) |
196 | { |
197 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
198 | |
199 | pi->clk_regs.rv730.cg_spll_func_cntl = |
200 | RREG32(CG_SPLL_FUNC_CNTL); |
201 | pi->clk_regs.rv730.cg_spll_func_cntl_2 = |
202 | RREG32(CG_SPLL_FUNC_CNTL_2); |
203 | pi->clk_regs.rv730.cg_spll_func_cntl_3 = |
204 | RREG32(CG_SPLL_FUNC_CNTL_3); |
205 | pi->clk_regs.rv730.cg_spll_spread_spectrum = |
206 | RREG32(CG_SPLL_SPREAD_SPECTRUM); |
207 | pi->clk_regs.rv730.cg_spll_spread_spectrum_2 = |
208 | RREG32(CG_SPLL_SPREAD_SPECTRUM_2); |
209 | |
210 | pi->clk_regs.rv730.mclk_pwrmgt_cntl = |
211 | RREG32(TCI_MCLK_PWRMGT_CNTL); |
212 | pi->clk_regs.rv730.dll_cntl = |
213 | RREG32(TCI_DLL_CNTL); |
214 | pi->clk_regs.rv730.mpll_func_cntl = |
215 | RREG32(CG_MPLL_FUNC_CNTL); |
216 | pi->clk_regs.rv730.mpll_func_cntl2 = |
217 | RREG32(CG_MPLL_FUNC_CNTL_2); |
218 | pi->clk_regs.rv730.mpll_func_cntl3 = |
219 | RREG32(CG_MPLL_FUNC_CNTL_3); |
220 | pi->clk_regs.rv730.mpll_ss = |
221 | RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM); |
222 | pi->clk_regs.rv730.mpll_ss2 = |
223 | RREG32(CG_TCI_MPLL_SPREAD_SPECTRUM_2); |
224 | } |
225 | |
226 | int rv730_populate_smc_acpi_state(struct radeon_device *rdev, |
227 | RV770_SMC_STATETABLE *table) |
228 | { |
229 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
230 | u32 mpll_func_cntl = 0; |
231 | u32 mpll_func_cntl_2 = 0 ; |
232 | u32 mpll_func_cntl_3 = 0; |
233 | u32 mclk_pwrmgt_cntl; |
234 | u32 dll_cntl; |
235 | u32 spll_func_cntl; |
236 | u32 spll_func_cntl_2; |
237 | u32 spll_func_cntl_3; |
238 | |
239 | table->ACPIState = table->initialState; |
240 | table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; |
241 | |
242 | if (pi->acpi_vddc) { |
243 | rv770_populate_vddc_value(rdev, vddc: pi->acpi_vddc, |
244 | voltage: &table->ACPIState.levels[0].vddc); |
245 | table->ACPIState.levels[0].gen2PCIE = pi->pcie_gen2 ? |
246 | pi->acpi_pcie_gen2 : 0; |
247 | table->ACPIState.levels[0].gen2XSP = |
248 | pi->acpi_pcie_gen2; |
249 | } else { |
250 | rv770_populate_vddc_value(rdev, vddc: pi->min_vddc_in_table, |
251 | voltage: &table->ACPIState.levels[0].vddc); |
252 | table->ACPIState.levels[0].gen2PCIE = 0; |
253 | } |
254 | |
255 | mpll_func_cntl = pi->clk_regs.rv730.mpll_func_cntl; |
256 | mpll_func_cntl_2 = pi->clk_regs.rv730.mpll_func_cntl2; |
257 | mpll_func_cntl_3 = pi->clk_regs.rv730.mpll_func_cntl3; |
258 | |
259 | mpll_func_cntl |= MPLL_RESET | MPLL_BYPASS_EN; |
260 | mpll_func_cntl &= ~MPLL_SLEEP; |
261 | |
262 | mpll_func_cntl_2 &= ~MCLK_MUX_SEL_MASK; |
263 | mpll_func_cntl_2 |= MCLK_MUX_SEL(1); |
264 | |
265 | mclk_pwrmgt_cntl = (MRDCKA_RESET | |
266 | MRDCKB_RESET | |
267 | MRDCKC_RESET | |
268 | MRDCKD_RESET | |
269 | MRDCKE_RESET | |
270 | MRDCKF_RESET | |
271 | MRDCKG_RESET | |
272 | MRDCKH_RESET | |
273 | MRDCKA_SLEEP | |
274 | MRDCKB_SLEEP | |
275 | MRDCKC_SLEEP | |
276 | MRDCKD_SLEEP | |
277 | MRDCKE_SLEEP | |
278 | MRDCKF_SLEEP | |
279 | MRDCKG_SLEEP | |
280 | MRDCKH_SLEEP); |
281 | |
282 | dll_cntl = 0xff000000; |
283 | |
284 | spll_func_cntl = pi->clk_regs.rv730.cg_spll_func_cntl; |
285 | spll_func_cntl_2 = pi->clk_regs.rv730.cg_spll_func_cntl_2; |
286 | spll_func_cntl_3 = pi->clk_regs.rv730.cg_spll_func_cntl_3; |
287 | |
288 | spll_func_cntl |= SPLL_RESET | SPLL_BYPASS_EN; |
289 | spll_func_cntl &= ~SPLL_SLEEP; |
290 | |
291 | spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; |
292 | spll_func_cntl_2 |= SCLK_MUX_SEL(4); |
293 | |
294 | table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); |
295 | table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = cpu_to_be32(mpll_func_cntl_2); |
296 | table->ACPIState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = cpu_to_be32(mpll_func_cntl_3); |
297 | table->ACPIState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); |
298 | table->ACPIState.levels[0].mclk.mclk730.vDLL_CNTL = cpu_to_be32(dll_cntl); |
299 | |
300 | table->ACPIState.levels[0].mclk.mclk730.mclk_value = 0; |
301 | |
302 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = cpu_to_be32(spll_func_cntl); |
303 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(spll_func_cntl_2); |
304 | table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(spll_func_cntl_3); |
305 | |
306 | table->ACPIState.levels[0].sclk.sclk_value = 0; |
307 | |
308 | rv770_populate_mvdd_value(rdev, mclk: 0, voltage: &table->ACPIState.levels[0].mvdd); |
309 | |
310 | table->ACPIState.levels[1] = table->ACPIState.levels[0]; |
311 | table->ACPIState.levels[2] = table->ACPIState.levels[0]; |
312 | |
313 | return 0; |
314 | } |
315 | |
316 | int rv730_populate_smc_initial_state(struct radeon_device *rdev, |
317 | struct radeon_ps *radeon_state, |
318 | RV770_SMC_STATETABLE *table) |
319 | { |
320 | struct rv7xx_ps *initial_state = rv770_get_ps(rps: radeon_state); |
321 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
322 | u32 a_t; |
323 | |
324 | table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL = |
325 | cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl); |
326 | table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL2 = |
327 | cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl2); |
328 | table->initialState.levels[0].mclk.mclk730.vMPLL_FUNC_CNTL3 = |
329 | cpu_to_be32(pi->clk_regs.rv730.mpll_func_cntl3); |
330 | table->initialState.levels[0].mclk.mclk730.vMCLK_PWRMGT_CNTL = |
331 | cpu_to_be32(pi->clk_regs.rv730.mclk_pwrmgt_cntl); |
332 | table->initialState.levels[0].mclk.mclk730.vDLL_CNTL = |
333 | cpu_to_be32(pi->clk_regs.rv730.dll_cntl); |
334 | table->initialState.levels[0].mclk.mclk730.vMPLL_SS = |
335 | cpu_to_be32(pi->clk_regs.rv730.mpll_ss); |
336 | table->initialState.levels[0].mclk.mclk730.vMPLL_SS2 = |
337 | cpu_to_be32(pi->clk_regs.rv730.mpll_ss2); |
338 | |
339 | table->initialState.levels[0].mclk.mclk730.mclk_value = |
340 | cpu_to_be32(initial_state->low.mclk); |
341 | |
342 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = |
343 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl); |
344 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = |
345 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_2); |
346 | table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = |
347 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_func_cntl_3); |
348 | table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM = |
349 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum); |
350 | table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 = |
351 | cpu_to_be32(pi->clk_regs.rv730.cg_spll_spread_spectrum_2); |
352 | |
353 | table->initialState.levels[0].sclk.sclk_value = |
354 | cpu_to_be32(initial_state->low.sclk); |
355 | |
356 | table->initialState.levels[0].arbValue = MC_CG_ARB_FREQ_F0; |
357 | |
358 | table->initialState.levels[0].seqValue = |
359 | rv770_get_seq_value(rdev, pl: &initial_state->low); |
360 | |
361 | rv770_populate_vddc_value(rdev, |
362 | vddc: initial_state->low.vddc, |
363 | voltage: &table->initialState.levels[0].vddc); |
364 | rv770_populate_initial_mvdd_value(rdev, |
365 | voltage: &table->initialState.levels[0].mvdd); |
366 | |
367 | a_t = CG_R(0xffff) | CG_L(0); |
368 | |
369 | table->initialState.levels[0].aT = cpu_to_be32(a_t); |
370 | |
371 | table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); |
372 | |
373 | if (pi->boot_in_gen2) |
374 | table->initialState.levels[0].gen2PCIE = 1; |
375 | else |
376 | table->initialState.levels[0].gen2PCIE = 0; |
377 | if (initial_state->low.flags & ATOM_PPLIB_R600_FLAGS_PCIEGEN2) |
378 | table->initialState.levels[0].gen2XSP = 1; |
379 | else |
380 | table->initialState.levels[0].gen2XSP = 0; |
381 | |
382 | table->initialState.levels[1] = table->initialState.levels[0]; |
383 | table->initialState.levels[2] = table->initialState.levels[0]; |
384 | |
385 | table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC; |
386 | |
387 | return 0; |
388 | } |
389 | |
390 | void rv730_program_memory_timing_parameters(struct radeon_device *rdev, |
391 | struct radeon_ps *radeon_state) |
392 | { |
393 | struct rv7xx_ps *state = rv770_get_ps(rps: radeon_state); |
394 | u32 arb_refresh_rate = 0; |
395 | u32 dram_timing = 0; |
396 | u32 dram_timing2 = 0; |
397 | u32 old_dram_timing = 0; |
398 | u32 old_dram_timing2 = 0; |
399 | |
400 | arb_refresh_rate = RREG32(MC_ARB_RFSH_RATE) & |
401 | ~(POWERMODE1_MASK | POWERMODE2_MASK | POWERMODE3_MASK); |
402 | arb_refresh_rate |= |
403 | (POWERMODE1(rv770_calculate_memory_refresh_rate(rdev, state->low.sclk)) | |
404 | POWERMODE2(rv770_calculate_memory_refresh_rate(rdev, state->medium.sclk)) | |
405 | POWERMODE3(rv770_calculate_memory_refresh_rate(rdev, state->high.sclk))); |
406 | WREG32(MC_ARB_RFSH_RATE, arb_refresh_rate); |
407 | |
408 | /* save the boot dram timings */ |
409 | old_dram_timing = RREG32(MC_ARB_DRAM_TIMING); |
410 | old_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); |
411 | |
412 | radeon_atom_set_engine_dram_timings(rdev, |
413 | eng_clock: state->high.sclk, |
414 | mem_clock: state->high.mclk); |
415 | |
416 | dram_timing = RREG32(MC_ARB_DRAM_TIMING); |
417 | dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); |
418 | |
419 | WREG32(MC_ARB_DRAM_TIMING_3, dram_timing); |
420 | WREG32(MC_ARB_DRAM_TIMING2_3, dram_timing2); |
421 | |
422 | radeon_atom_set_engine_dram_timings(rdev, |
423 | eng_clock: state->medium.sclk, |
424 | mem_clock: state->medium.mclk); |
425 | |
426 | dram_timing = RREG32(MC_ARB_DRAM_TIMING); |
427 | dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); |
428 | |
429 | WREG32(MC_ARB_DRAM_TIMING_2, dram_timing); |
430 | WREG32(MC_ARB_DRAM_TIMING2_2, dram_timing2); |
431 | |
432 | radeon_atom_set_engine_dram_timings(rdev, |
433 | eng_clock: state->low.sclk, |
434 | mem_clock: state->low.mclk); |
435 | |
436 | dram_timing = RREG32(MC_ARB_DRAM_TIMING); |
437 | dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); |
438 | |
439 | WREG32(MC_ARB_DRAM_TIMING_1, dram_timing); |
440 | WREG32(MC_ARB_DRAM_TIMING2_1, dram_timing2); |
441 | |
442 | /* restore the boot dram timings */ |
443 | WREG32(MC_ARB_DRAM_TIMING, old_dram_timing); |
444 | WREG32(MC_ARB_DRAM_TIMING2, old_dram_timing2); |
445 | |
446 | } |
447 | |
448 | void rv730_start_dpm(struct radeon_device *rdev) |
449 | { |
450 | WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); |
451 | |
452 | WREG32_P(TCI_MCLK_PWRMGT_CNTL, 0, ~MPLL_PWRMGT_OFF); |
453 | |
454 | WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); |
455 | } |
456 | |
457 | void rv730_stop_dpm(struct radeon_device *rdev) |
458 | { |
459 | PPSMC_Result result; |
460 | |
461 | result = rv770_send_msg_to_smc(rdev, PPSMC_MSG_TwoLevelsDisabled); |
462 | |
463 | if (result != PPSMC_Result_OK) |
464 | DRM_DEBUG("Could not force DPM to low\n" ); |
465 | |
466 | WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); |
467 | |
468 | WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); |
469 | |
470 | WREG32_P(TCI_MCLK_PWRMGT_CNTL, MPLL_PWRMGT_OFF, ~MPLL_PWRMGT_OFF); |
471 | } |
472 | |
473 | void rv730_program_dcodt(struct radeon_device *rdev, bool use_dcodt) |
474 | { |
475 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
476 | u32 i = use_dcodt ? 0 : 1; |
477 | u32 mc4_io_pad_cntl; |
478 | |
479 | mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0); |
480 | mc4_io_pad_cntl &= 0xFFFFFF00; |
481 | mc4_io_pad_cntl |= pi->odt_value_0[i]; |
482 | WREG32(MC4_IO_DQ_PAD_CNTL_D0_I0, mc4_io_pad_cntl); |
483 | WREG32(MC4_IO_DQ_PAD_CNTL_D0_I1, mc4_io_pad_cntl); |
484 | |
485 | mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0); |
486 | mc4_io_pad_cntl &= 0xFFFFFF00; |
487 | mc4_io_pad_cntl |= pi->odt_value_1[i]; |
488 | WREG32(MC4_IO_QS_PAD_CNTL_D0_I0, mc4_io_pad_cntl); |
489 | WREG32(MC4_IO_QS_PAD_CNTL_D0_I1, mc4_io_pad_cntl); |
490 | } |
491 | |
492 | void rv730_get_odt_values(struct radeon_device *rdev) |
493 | { |
494 | struct rv7xx_power_info *pi = rv770_get_pi(rdev); |
495 | u32 mc4_io_pad_cntl; |
496 | |
497 | pi->odt_value_0[0] = (u8)0; |
498 | pi->odt_value_1[0] = (u8)0x80; |
499 | |
500 | mc4_io_pad_cntl = RREG32(MC4_IO_DQ_PAD_CNTL_D0_I0); |
501 | pi->odt_value_0[1] = (u8)(mc4_io_pad_cntl & 0xff); |
502 | |
503 | mc4_io_pad_cntl = RREG32(MC4_IO_QS_PAD_CNTL_D0_I0); |
504 | pi->odt_value_1[1] = (u8)(mc4_io_pad_cntl & 0xff); |
505 | } |
506 | |