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