1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * drivers/video/aty/radeon_pm.c |
4 | * |
5 | * Copyright 2003,2004 Ben. Herrenschmidt <benh@kernel.crashing.org> |
6 | * Copyright 2004 Paul Mackerras <paulus@samba.org> |
7 | * |
8 | * This is the power management code for ATI radeon chipsets. It contains |
9 | * some dynamic clock PM enable/disable code similar to what X.org does, |
10 | * some D2-state (APM-style) sleep/wakeup code for use on some PowerMacs, |
11 | * and the necessary bits to re-initialize from scratch a few chips found |
12 | * on PowerMacs as well. The later could be extended to more platforms |
13 | * provided the memory controller configuration code be made more generic, |
14 | * and you can get the proper mode register commands for your RAMs. |
15 | * Those things may be found in the BIOS image... |
16 | */ |
17 | |
18 | #include "radeonfb.h" |
19 | |
20 | #include <linux/console.h> |
21 | #include <linux/agp_backend.h> |
22 | |
23 | #ifdef CONFIG_PPC_PMAC |
24 | #include <asm/machdep.h> |
25 | #include <asm/pmac_feature.h> |
26 | #endif |
27 | |
28 | #include "ati_ids.h" |
29 | |
30 | /* |
31 | * Workarounds for bugs in PC laptops: |
32 | * - enable D2 sleep in some IBM Thinkpads |
33 | * - special case for Samsung P35 |
34 | * |
35 | * Whitelist by subsystem vendor/device because |
36 | * its the subsystem vendor's fault! |
37 | */ |
38 | |
39 | #if defined(CONFIG_PM) && defined(CONFIG_X86) |
40 | static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); |
41 | |
42 | struct radeon_device_id { |
43 | const char *ident; /* (arbitrary) Name */ |
44 | const unsigned short subsystem_vendor; /* Subsystem Vendor ID */ |
45 | const unsigned short subsystem_device; /* Subsystem Device ID */ |
46 | const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */ |
47 | const reinit_function_ptr new_reinit_func; /* changed reinit_func */ |
48 | }; |
49 | |
50 | #define BUGFIX(model, sv, sd, pm, fn) { \ |
51 | .ident = model, \ |
52 | .subsystem_vendor = sv, \ |
53 | .subsystem_device = sd, \ |
54 | .pm_mode_modifier = pm, \ |
55 | .new_reinit_func = fn \ |
56 | } |
57 | |
58 | static struct radeon_device_id radeon_workaround_list[] = { |
59 | BUGFIX("IBM Thinkpad R32" , |
60 | PCI_VENDOR_ID_IBM, 0x1905, |
61 | radeon_pm_d2, NULL), |
62 | BUGFIX("IBM Thinkpad R40" , |
63 | PCI_VENDOR_ID_IBM, 0x0526, |
64 | radeon_pm_d2, NULL), |
65 | BUGFIX("IBM Thinkpad R40" , |
66 | PCI_VENDOR_ID_IBM, 0x0527, |
67 | radeon_pm_d2, NULL), |
68 | BUGFIX("IBM Thinkpad R50/R51/T40/T41" , |
69 | PCI_VENDOR_ID_IBM, 0x0531, |
70 | radeon_pm_d2, NULL), |
71 | BUGFIX("IBM Thinkpad R51/T40/T41/T42" , |
72 | PCI_VENDOR_ID_IBM, 0x0530, |
73 | radeon_pm_d2, NULL), |
74 | BUGFIX("IBM Thinkpad T30" , |
75 | PCI_VENDOR_ID_IBM, 0x0517, |
76 | radeon_pm_d2, NULL), |
77 | BUGFIX("IBM Thinkpad T40p" , |
78 | PCI_VENDOR_ID_IBM, 0x054d, |
79 | radeon_pm_d2, NULL), |
80 | BUGFIX("IBM Thinkpad T42" , |
81 | PCI_VENDOR_ID_IBM, 0x0550, |
82 | radeon_pm_d2, NULL), |
83 | BUGFIX("IBM Thinkpad X31/X32" , |
84 | PCI_VENDOR_ID_IBM, 0x052f, |
85 | radeon_pm_d2, NULL), |
86 | BUGFIX("Samsung P35" , |
87 | PCI_VENDOR_ID_SAMSUNG, 0xc00c, |
88 | radeon_pm_off, radeon_reinitialize_M10), |
89 | BUGFIX("Acer Aspire 2010" , |
90 | PCI_VENDOR_ID_AI, 0x0061, |
91 | radeon_pm_off, radeon_reinitialize_M10), |
92 | BUGFIX("Acer Travelmate 290D/292LMi" , |
93 | PCI_VENDOR_ID_AI, 0x005a, |
94 | radeon_pm_off, radeon_reinitialize_M10), |
95 | { .ident = NULL } |
96 | }; |
97 | |
98 | static int radeon_apply_workarounds(struct radeonfb_info *rinfo) |
99 | { |
100 | struct radeon_device_id *id; |
101 | |
102 | for (id = radeon_workaround_list; id->ident != NULL; id++ ) |
103 | if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) && |
104 | (id->subsystem_device == rinfo->pdev->subsystem_device )) { |
105 | |
106 | /* we found a device that requires workaround */ |
107 | printk(KERN_DEBUG "radeonfb: %s detected" |
108 | ", enabling workaround\n" , id->ident); |
109 | |
110 | rinfo->pm_mode |= id->pm_mode_modifier; |
111 | |
112 | if (id->new_reinit_func != NULL) |
113 | rinfo->reinit_func = id->new_reinit_func; |
114 | |
115 | return 1; |
116 | } |
117 | return 0; /* not found */ |
118 | } |
119 | |
120 | #else /* defined(CONFIG_PM) && defined(CONFIG_X86) */ |
121 | static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo) |
122 | { |
123 | return 0; |
124 | } |
125 | #endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */ |
126 | |
127 | |
128 | |
129 | static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) |
130 | { |
131 | u32 tmp; |
132 | |
133 | /* RV100 */ |
134 | if ((rinfo->family == CHIP_FAMILY_RV100) && (!rinfo->is_mobility)) { |
135 | if (rinfo->has_CRTC2) { |
136 | tmp = INPLL(pllSCLK_CNTL); |
137 | tmp &= ~SCLK_CNTL__DYN_STOP_LAT_MASK; |
138 | tmp |= SCLK_CNTL__CP_MAX_DYN_STOP_LAT | SCLK_CNTL__FORCEON_MASK; |
139 | OUTPLL(pllSCLK_CNTL, tmp); |
140 | } |
141 | tmp = INPLL(pllMCLK_CNTL); |
142 | tmp |= (MCLK_CNTL__FORCE_MCLKA | |
143 | MCLK_CNTL__FORCE_MCLKB | |
144 | MCLK_CNTL__FORCE_YCLKA | |
145 | MCLK_CNTL__FORCE_YCLKB | |
146 | MCLK_CNTL__FORCE_AIC | |
147 | MCLK_CNTL__FORCE_MC); |
148 | OUTPLL(pllMCLK_CNTL, tmp); |
149 | return; |
150 | } |
151 | /* R100 */ |
152 | if (!rinfo->has_CRTC2) { |
153 | tmp = INPLL(pllSCLK_CNTL); |
154 | tmp |= (SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_HDP | |
155 | SCLK_CNTL__FORCE_DISP1 | SCLK_CNTL__FORCE_TOP | |
156 | SCLK_CNTL__FORCE_E2 | SCLK_CNTL__FORCE_SE | |
157 | SCLK_CNTL__FORCE_IDCT | SCLK_CNTL__FORCE_VIP | |
158 | SCLK_CNTL__FORCE_RE | SCLK_CNTL__FORCE_PB | |
159 | SCLK_CNTL__FORCE_TAM | SCLK_CNTL__FORCE_TDM | |
160 | SCLK_CNTL__FORCE_RB); |
161 | OUTPLL(pllSCLK_CNTL, tmp); |
162 | return; |
163 | } |
164 | /* RV350 (M10/M11) */ |
165 | if (rinfo->family == CHIP_FAMILY_RV350) { |
166 | /* for RV350/M10/M11, no delays are required. */ |
167 | tmp = INPLL(pllSCLK_CNTL2); |
168 | tmp |= (SCLK_CNTL2__R300_FORCE_TCL | |
169 | SCLK_CNTL2__R300_FORCE_GA | |
170 | SCLK_CNTL2__R300_FORCE_CBA); |
171 | OUTPLL(pllSCLK_CNTL2, tmp); |
172 | |
173 | tmp = INPLL(pllSCLK_CNTL); |
174 | tmp |= (SCLK_CNTL__FORCE_DISP2 | SCLK_CNTL__FORCE_CP | |
175 | SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 | |
176 | SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_E2 | |
177 | SCLK_CNTL__R300_FORCE_VAP | SCLK_CNTL__FORCE_IDCT | |
178 | SCLK_CNTL__FORCE_VIP | SCLK_CNTL__R300_FORCE_SR | |
179 | SCLK_CNTL__R300_FORCE_PX | SCLK_CNTL__R300_FORCE_TX | |
180 | SCLK_CNTL__R300_FORCE_US | SCLK_CNTL__FORCE_TV_SCLK | |
181 | SCLK_CNTL__R300_FORCE_SU | SCLK_CNTL__FORCE_OV0); |
182 | OUTPLL(pllSCLK_CNTL, tmp); |
183 | |
184 | tmp = INPLL(pllSCLK_MORE_CNTL); |
185 | tmp |= (SCLK_MORE_CNTL__FORCE_DISPREGS | SCLK_MORE_CNTL__FORCE_MC_GUI | |
186 | SCLK_MORE_CNTL__FORCE_MC_HOST); |
187 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
188 | |
189 | tmp = INPLL(pllMCLK_CNTL); |
190 | tmp |= (MCLK_CNTL__FORCE_MCLKA | |
191 | MCLK_CNTL__FORCE_MCLKB | |
192 | MCLK_CNTL__FORCE_YCLKA | |
193 | MCLK_CNTL__FORCE_YCLKB | |
194 | MCLK_CNTL__FORCE_MC); |
195 | OUTPLL(pllMCLK_CNTL, tmp); |
196 | |
197 | tmp = INPLL(pllVCLK_ECP_CNTL); |
198 | tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | |
199 | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb | |
200 | VCLK_ECP_CNTL__R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); |
201 | OUTPLL(pllVCLK_ECP_CNTL, tmp); |
202 | |
203 | tmp = INPLL(pllPIXCLKS_CNTL); |
204 | tmp &= ~(PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb | |
205 | PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb | |
206 | PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | |
207 | PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb | |
208 | PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb | |
209 | PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | |
210 | PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb | |
211 | PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb | |
212 | PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb | |
213 | PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb | |
214 | PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb | |
215 | PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb | |
216 | PIXCLKS_CNTL__R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); |
217 | OUTPLL(pllPIXCLKS_CNTL, tmp); |
218 | |
219 | return; |
220 | } |
221 | |
222 | /* Default */ |
223 | |
224 | /* Force Core Clocks */ |
225 | tmp = INPLL(pllSCLK_CNTL); |
226 | tmp |= (SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_E2); |
227 | |
228 | /* XFree doesn't do that case, but we had this code from Apple and it |
229 | * seem necessary for proper suspend/resume operations |
230 | */ |
231 | if (rinfo->is_mobility) { |
232 | tmp |= SCLK_CNTL__FORCE_HDP| |
233 | SCLK_CNTL__FORCE_DISP1| |
234 | SCLK_CNTL__FORCE_DISP2| |
235 | SCLK_CNTL__FORCE_TOP| |
236 | SCLK_CNTL__FORCE_SE| |
237 | SCLK_CNTL__FORCE_IDCT| |
238 | SCLK_CNTL__FORCE_VIP| |
239 | SCLK_CNTL__FORCE_PB| |
240 | SCLK_CNTL__FORCE_RE| |
241 | SCLK_CNTL__FORCE_TAM| |
242 | SCLK_CNTL__FORCE_TDM| |
243 | SCLK_CNTL__FORCE_RB| |
244 | SCLK_CNTL__FORCE_TV_SCLK| |
245 | SCLK_CNTL__FORCE_SUBPIC| |
246 | SCLK_CNTL__FORCE_OV0; |
247 | } |
248 | else if (rinfo->family == CHIP_FAMILY_R300 || |
249 | rinfo->family == CHIP_FAMILY_R350) { |
250 | tmp |= SCLK_CNTL__FORCE_HDP | |
251 | SCLK_CNTL__FORCE_DISP1 | |
252 | SCLK_CNTL__FORCE_DISP2 | |
253 | SCLK_CNTL__FORCE_TOP | |
254 | SCLK_CNTL__FORCE_IDCT | |
255 | SCLK_CNTL__FORCE_VIP; |
256 | } |
257 | OUTPLL(pllSCLK_CNTL, tmp); |
258 | radeon_msleep(16); |
259 | |
260 | if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) { |
261 | tmp = INPLL(pllSCLK_CNTL2); |
262 | tmp |= SCLK_CNTL2__R300_FORCE_TCL | |
263 | SCLK_CNTL2__R300_FORCE_GA | |
264 | SCLK_CNTL2__R300_FORCE_CBA; |
265 | OUTPLL(pllSCLK_CNTL2, tmp); |
266 | radeon_msleep(16); |
267 | } |
268 | |
269 | tmp = INPLL(pllCLK_PIN_CNTL); |
270 | tmp &= ~CLK_PIN_CNTL__SCLK_DYN_START_CNTL; |
271 | OUTPLL(pllCLK_PIN_CNTL, tmp); |
272 | radeon_msleep(15); |
273 | |
274 | if (rinfo->is_IGP) { |
275 | /* Weird ... X is _un_ forcing clocks here, I think it's |
276 | * doing backward. Imitate it for now... |
277 | */ |
278 | tmp = INPLL(pllMCLK_CNTL); |
279 | tmp &= ~(MCLK_CNTL__FORCE_MCLKA | |
280 | MCLK_CNTL__FORCE_YCLKA); |
281 | OUTPLL(pllMCLK_CNTL, tmp); |
282 | radeon_msleep(16); |
283 | } |
284 | /* Hrm... same shit, X doesn't do that but I have to */ |
285 | else if (rinfo->is_mobility) { |
286 | tmp = INPLL(pllMCLK_CNTL); |
287 | tmp |= (MCLK_CNTL__FORCE_MCLKA | |
288 | MCLK_CNTL__FORCE_MCLKB | |
289 | MCLK_CNTL__FORCE_YCLKA | |
290 | MCLK_CNTL__FORCE_YCLKB); |
291 | OUTPLL(pllMCLK_CNTL, tmp); |
292 | radeon_msleep(16); |
293 | |
294 | tmp = INPLL(pllMCLK_MISC); |
295 | tmp &= ~(MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT| |
296 | MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT| |
297 | MCLK_MISC__MC_MCLK_DYN_ENABLE| |
298 | MCLK_MISC__IO_MCLK_DYN_ENABLE); |
299 | OUTPLL(pllMCLK_MISC, tmp); |
300 | radeon_msleep(15); |
301 | } |
302 | |
303 | if (rinfo->is_mobility) { |
304 | tmp = INPLL(pllSCLK_MORE_CNTL); |
305 | tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS| |
306 | SCLK_MORE_CNTL__FORCE_MC_GUI| |
307 | SCLK_MORE_CNTL__FORCE_MC_HOST; |
308 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
309 | radeon_msleep(16); |
310 | } |
311 | |
312 | tmp = INPLL(pllPIXCLKS_CNTL); |
313 | tmp &= ~(PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | |
314 | PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb| |
315 | PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb | |
316 | PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb| |
317 | PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb| |
318 | PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb| |
319 | PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb); |
320 | OUTPLL(pllPIXCLKS_CNTL, tmp); |
321 | radeon_msleep(16); |
322 | |
323 | tmp = INPLL( pllVCLK_ECP_CNTL); |
324 | tmp &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | |
325 | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb); |
326 | OUTPLL( pllVCLK_ECP_CNTL, tmp); |
327 | radeon_msleep(16); |
328 | } |
329 | |
330 | static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) |
331 | { |
332 | u32 tmp; |
333 | |
334 | /* R100 */ |
335 | if (!rinfo->has_CRTC2) { |
336 | tmp = INPLL(pllSCLK_CNTL); |
337 | |
338 | if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13) |
339 | tmp &= ~(SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_RB); |
340 | tmp &= ~(SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 | |
341 | SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_SE | |
342 | SCLK_CNTL__FORCE_IDCT | SCLK_CNTL__FORCE_RE | |
343 | SCLK_CNTL__FORCE_PB | SCLK_CNTL__FORCE_TAM | |
344 | SCLK_CNTL__FORCE_TDM); |
345 | OUTPLL(pllSCLK_CNTL, tmp); |
346 | return; |
347 | } |
348 | |
349 | /* M10/M11 */ |
350 | if (rinfo->family == CHIP_FAMILY_RV350) { |
351 | tmp = INPLL(pllSCLK_CNTL2); |
352 | tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL | |
353 | SCLK_CNTL2__R300_FORCE_GA | |
354 | SCLK_CNTL2__R300_FORCE_CBA); |
355 | tmp |= (SCLK_CNTL2__R300_TCL_MAX_DYN_STOP_LAT | |
356 | SCLK_CNTL2__R300_GA_MAX_DYN_STOP_LAT | |
357 | SCLK_CNTL2__R300_CBA_MAX_DYN_STOP_LAT); |
358 | OUTPLL(pllSCLK_CNTL2, tmp); |
359 | |
360 | tmp = INPLL(pllSCLK_CNTL); |
361 | tmp &= ~(SCLK_CNTL__FORCE_DISP2 | SCLK_CNTL__FORCE_CP | |
362 | SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 | |
363 | SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_E2 | |
364 | SCLK_CNTL__R300_FORCE_VAP | SCLK_CNTL__FORCE_IDCT | |
365 | SCLK_CNTL__FORCE_VIP | SCLK_CNTL__R300_FORCE_SR | |
366 | SCLK_CNTL__R300_FORCE_PX | SCLK_CNTL__R300_FORCE_TX | |
367 | SCLK_CNTL__R300_FORCE_US | SCLK_CNTL__FORCE_TV_SCLK | |
368 | SCLK_CNTL__R300_FORCE_SU | SCLK_CNTL__FORCE_OV0); |
369 | tmp |= SCLK_CNTL__DYN_STOP_LAT_MASK; |
370 | OUTPLL(pllSCLK_CNTL, tmp); |
371 | |
372 | tmp = INPLL(pllSCLK_MORE_CNTL); |
373 | tmp &= ~SCLK_MORE_CNTL__FORCEON; |
374 | tmp |= SCLK_MORE_CNTL__DISPREGS_MAX_DYN_STOP_LAT | |
375 | SCLK_MORE_CNTL__MC_GUI_MAX_DYN_STOP_LAT | |
376 | SCLK_MORE_CNTL__MC_HOST_MAX_DYN_STOP_LAT; |
377 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
378 | |
379 | tmp = INPLL(pllVCLK_ECP_CNTL); |
380 | tmp |= (VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | |
381 | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb); |
382 | OUTPLL(pllVCLK_ECP_CNTL, tmp); |
383 | |
384 | tmp = INPLL(pllPIXCLKS_CNTL); |
385 | tmp |= (PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb | |
386 | PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb | |
387 | PIXCLKS_CNTL__DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | |
388 | PIXCLKS_CNTL__R300_DVOCLK_ALWAYS_ONb | |
389 | PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb | |
390 | PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | |
391 | PIXCLKS_CNTL__R300_PIXCLK_DVO_ALWAYS_ONb | |
392 | PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb | |
393 | PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb | |
394 | PIXCLKS_CNTL__R300_PIXCLK_TRANS_ALWAYS_ONb | |
395 | PIXCLKS_CNTL__R300_PIXCLK_TVO_ALWAYS_ONb | |
396 | PIXCLKS_CNTL__R300_P2G2CLK_ALWAYS_ONb | |
397 | PIXCLKS_CNTL__R300_P2G2CLK_DAC_ALWAYS_ONb); |
398 | OUTPLL(pllPIXCLKS_CNTL, tmp); |
399 | |
400 | tmp = INPLL(pllMCLK_MISC); |
401 | tmp |= (MCLK_MISC__MC_MCLK_DYN_ENABLE | |
402 | MCLK_MISC__IO_MCLK_DYN_ENABLE); |
403 | OUTPLL(pllMCLK_MISC, tmp); |
404 | |
405 | tmp = INPLL(pllMCLK_CNTL); |
406 | tmp |= (MCLK_CNTL__FORCE_MCLKA | MCLK_CNTL__FORCE_MCLKB); |
407 | tmp &= ~(MCLK_CNTL__FORCE_YCLKA | |
408 | MCLK_CNTL__FORCE_YCLKB | |
409 | MCLK_CNTL__FORCE_MC); |
410 | |
411 | /* Some releases of vbios have set DISABLE_MC_MCLKA |
412 | * and DISABLE_MC_MCLKB bits in the vbios table. Setting these |
413 | * bits will cause H/W hang when reading video memory with dynamic |
414 | * clocking enabled. |
415 | */ |
416 | if ((tmp & MCLK_CNTL__R300_DISABLE_MC_MCLKA) && |
417 | (tmp & MCLK_CNTL__R300_DISABLE_MC_MCLKB)) { |
418 | /* If both bits are set, then check the active channels */ |
419 | tmp = INPLL(pllMCLK_CNTL); |
420 | if (rinfo->vram_width == 64) { |
421 | if (INREG(MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY) |
422 | tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKB; |
423 | else |
424 | tmp &= ~MCLK_CNTL__R300_DISABLE_MC_MCLKA; |
425 | } else { |
426 | tmp &= ~(MCLK_CNTL__R300_DISABLE_MC_MCLKA | |
427 | MCLK_CNTL__R300_DISABLE_MC_MCLKB); |
428 | } |
429 | } |
430 | OUTPLL(pllMCLK_CNTL, tmp); |
431 | return; |
432 | } |
433 | |
434 | /* R300 */ |
435 | if (rinfo->family == CHIP_FAMILY_R300 || rinfo->family == CHIP_FAMILY_R350) { |
436 | tmp = INPLL(pllSCLK_CNTL); |
437 | tmp &= ~(SCLK_CNTL__R300_FORCE_VAP); |
438 | tmp |= SCLK_CNTL__FORCE_CP; |
439 | OUTPLL(pllSCLK_CNTL, tmp); |
440 | radeon_msleep(15); |
441 | |
442 | tmp = INPLL(pllSCLK_CNTL2); |
443 | tmp &= ~(SCLK_CNTL2__R300_FORCE_TCL | |
444 | SCLK_CNTL2__R300_FORCE_GA | |
445 | SCLK_CNTL2__R300_FORCE_CBA); |
446 | OUTPLL(pllSCLK_CNTL2, tmp); |
447 | } |
448 | |
449 | /* Others */ |
450 | |
451 | tmp = INPLL( pllCLK_PWRMGT_CNTL); |
452 | tmp &= ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK| |
453 | CLK_PWRMGT_CNTL__DISP_DYN_STOP_LAT_MASK| |
454 | CLK_PWRMGT_CNTL__DYN_STOP_MODE_MASK); |
455 | tmp |= CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE_MASK | |
456 | (0x01 << CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT__SHIFT); |
457 | OUTPLL( pllCLK_PWRMGT_CNTL, tmp); |
458 | radeon_msleep(15); |
459 | |
460 | tmp = INPLL(pllCLK_PIN_CNTL); |
461 | tmp |= CLK_PIN_CNTL__SCLK_DYN_START_CNTL; |
462 | OUTPLL(pllCLK_PIN_CNTL, tmp); |
463 | radeon_msleep(15); |
464 | |
465 | /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 |
466 | * to lockup randomly, leave them as set by BIOS. |
467 | */ |
468 | tmp = INPLL(pllSCLK_CNTL); |
469 | tmp &= ~SCLK_CNTL__FORCEON_MASK; |
470 | |
471 | /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ |
472 | if ((rinfo->family == CHIP_FAMILY_RV250 && |
473 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) || |
474 | ((rinfo->family == CHIP_FAMILY_RV100) && |
475 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) { |
476 | tmp |= SCLK_CNTL__FORCE_CP; |
477 | tmp |= SCLK_CNTL__FORCE_VIP; |
478 | } |
479 | OUTPLL(pllSCLK_CNTL, tmp); |
480 | radeon_msleep(15); |
481 | |
482 | if ((rinfo->family == CHIP_FAMILY_RV200) || |
483 | (rinfo->family == CHIP_FAMILY_RV250) || |
484 | (rinfo->family == CHIP_FAMILY_RV280)) { |
485 | tmp = INPLL(pllSCLK_MORE_CNTL); |
486 | tmp &= ~SCLK_MORE_CNTL__FORCEON; |
487 | |
488 | /* RV200::A11 A12 RV250::A11 A12 */ |
489 | if (((rinfo->family == CHIP_FAMILY_RV200) || |
490 | (rinfo->family == CHIP_FAMILY_RV250)) && |
491 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) |
492 | tmp |= SCLK_MORE_CNTL__FORCEON; |
493 | |
494 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
495 | radeon_msleep(15); |
496 | } |
497 | |
498 | |
499 | /* RV200::A11 A12, RV250::A11 A12 */ |
500 | if (((rinfo->family == CHIP_FAMILY_RV200) || |
501 | (rinfo->family == CHIP_FAMILY_RV250)) && |
502 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) { |
503 | tmp = INPLL(pllPLL_PWRMGT_CNTL); |
504 | tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE; |
505 | OUTPLL(pllPLL_PWRMGT_CNTL, tmp); |
506 | radeon_msleep(15); |
507 | } |
508 | |
509 | tmp = INPLL(pllPIXCLKS_CNTL); |
510 | tmp |= PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb | |
511 | PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb| |
512 | PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb| |
513 | PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb| |
514 | PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb| |
515 | PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb| |
516 | PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb; |
517 | OUTPLL(pllPIXCLKS_CNTL, tmp); |
518 | radeon_msleep(15); |
519 | |
520 | tmp = INPLL(pllVCLK_ECP_CNTL); |
521 | tmp |= VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb | |
522 | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb; |
523 | OUTPLL(pllVCLK_ECP_CNTL, tmp); |
524 | |
525 | /* X doesn't do that ... hrm, we do on mobility && Macs */ |
526 | #ifdef CONFIG_PPC |
527 | if (rinfo->is_mobility) { |
528 | tmp = INPLL(pllMCLK_CNTL); |
529 | tmp &= ~(MCLK_CNTL__FORCE_MCLKA | |
530 | MCLK_CNTL__FORCE_MCLKB | |
531 | MCLK_CNTL__FORCE_YCLKA | |
532 | MCLK_CNTL__FORCE_YCLKB); |
533 | OUTPLL(pllMCLK_CNTL, tmp); |
534 | radeon_msleep(15); |
535 | |
536 | tmp = INPLL(pllMCLK_MISC); |
537 | tmp |= MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT| |
538 | MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT| |
539 | MCLK_MISC__MC_MCLK_DYN_ENABLE| |
540 | MCLK_MISC__IO_MCLK_DYN_ENABLE; |
541 | OUTPLL(pllMCLK_MISC, tmp); |
542 | radeon_msleep(15); |
543 | } |
544 | #endif /* CONFIG_PPC */ |
545 | } |
546 | |
547 | #ifdef CONFIG_PM |
548 | |
549 | static void OUTMC( struct radeonfb_info *rinfo, u8 indx, u32 value) |
550 | { |
551 | OUTREG( MC_IND_INDEX, indx | MC_IND_INDEX__MC_IND_WR_EN); |
552 | OUTREG( MC_IND_DATA, value); |
553 | } |
554 | |
555 | static u32 INMC(struct radeonfb_info *rinfo, u8 indx) |
556 | { |
557 | OUTREG( MC_IND_INDEX, indx); |
558 | return INREG( MC_IND_DATA); |
559 | } |
560 | |
561 | static void radeon_pm_save_regs(struct radeonfb_info *rinfo, int saving_for_d3) |
562 | { |
563 | rinfo->save_regs[0] = INPLL(PLL_PWRMGT_CNTL); |
564 | rinfo->save_regs[1] = INPLL(CLK_PWRMGT_CNTL); |
565 | rinfo->save_regs[2] = INPLL(MCLK_CNTL); |
566 | rinfo->save_regs[3] = INPLL(SCLK_CNTL); |
567 | rinfo->save_regs[4] = INPLL(CLK_PIN_CNTL); |
568 | rinfo->save_regs[5] = INPLL(VCLK_ECP_CNTL); |
569 | rinfo->save_regs[6] = INPLL(PIXCLKS_CNTL); |
570 | rinfo->save_regs[7] = INPLL(MCLK_MISC); |
571 | rinfo->save_regs[8] = INPLL(P2PLL_CNTL); |
572 | |
573 | rinfo->save_regs[9] = INREG(DISP_MISC_CNTL); |
574 | rinfo->save_regs[10] = INREG(DISP_PWR_MAN); |
575 | rinfo->save_regs[11] = INREG(LVDS_GEN_CNTL); |
576 | rinfo->save_regs[13] = INREG(TV_DAC_CNTL); |
577 | rinfo->save_regs[14] = INREG(BUS_CNTL1); |
578 | rinfo->save_regs[15] = INREG(CRTC_OFFSET_CNTL); |
579 | rinfo->save_regs[16] = INREG(AGP_CNTL); |
580 | rinfo->save_regs[17] = (INREG(CRTC_GEN_CNTL) & 0xfdffffff) | 0x04000000; |
581 | rinfo->save_regs[18] = (INREG(CRTC2_GEN_CNTL) & 0xfdffffff) | 0x04000000; |
582 | rinfo->save_regs[19] = INREG(GPIOPAD_A); |
583 | rinfo->save_regs[20] = INREG(GPIOPAD_EN); |
584 | rinfo->save_regs[21] = INREG(GPIOPAD_MASK); |
585 | rinfo->save_regs[22] = INREG(ZV_LCDPAD_A); |
586 | rinfo->save_regs[23] = INREG(ZV_LCDPAD_EN); |
587 | rinfo->save_regs[24] = INREG(ZV_LCDPAD_MASK); |
588 | rinfo->save_regs[25] = INREG(GPIO_VGA_DDC); |
589 | rinfo->save_regs[26] = INREG(GPIO_DVI_DDC); |
590 | rinfo->save_regs[27] = INREG(GPIO_MONID); |
591 | rinfo->save_regs[28] = INREG(GPIO_CRT2_DDC); |
592 | |
593 | rinfo->save_regs[29] = INREG(SURFACE_CNTL); |
594 | rinfo->save_regs[30] = INREG(MC_FB_LOCATION); |
595 | rinfo->save_regs[31] = INREG(DISPLAY_BASE_ADDR); |
596 | rinfo->save_regs[32] = INREG(MC_AGP_LOCATION); |
597 | rinfo->save_regs[33] = INREG(CRTC2_DISPLAY_BASE_ADDR); |
598 | |
599 | rinfo->save_regs[34] = INPLL(SCLK_MORE_CNTL); |
600 | rinfo->save_regs[35] = INREG(MEM_SDRAM_MODE_REG); |
601 | rinfo->save_regs[36] = INREG(BUS_CNTL); |
602 | rinfo->save_regs[39] = INREG(RBBM_CNTL); |
603 | rinfo->save_regs[40] = INREG(DAC_CNTL); |
604 | rinfo->save_regs[41] = INREG(HOST_PATH_CNTL); |
605 | rinfo->save_regs[37] = INREG(MPP_TB_CONFIG); |
606 | rinfo->save_regs[38] = INREG(FCP_CNTL); |
607 | |
608 | if (rinfo->is_mobility) { |
609 | rinfo->save_regs[12] = INREG(LVDS_PLL_CNTL); |
610 | rinfo->save_regs[43] = INPLL(pllSSPLL_CNTL); |
611 | rinfo->save_regs[44] = INPLL(pllSSPLL_REF_DIV); |
612 | rinfo->save_regs[45] = INPLL(pllSSPLL_DIV_0); |
613 | rinfo->save_regs[90] = INPLL(pllSS_INT_CNTL); |
614 | rinfo->save_regs[91] = INPLL(pllSS_TST_CNTL); |
615 | rinfo->save_regs[81] = INREG(LVDS_GEN_CNTL); |
616 | } |
617 | |
618 | if (rinfo->family >= CHIP_FAMILY_RV200) { |
619 | rinfo->save_regs[42] = INREG(MEM_REFRESH_CNTL); |
620 | rinfo->save_regs[46] = INREG(MC_CNTL); |
621 | rinfo->save_regs[47] = INREG(MC_INIT_GFX_LAT_TIMER); |
622 | rinfo->save_regs[48] = INREG(MC_INIT_MISC_LAT_TIMER); |
623 | rinfo->save_regs[49] = INREG(MC_TIMING_CNTL); |
624 | rinfo->save_regs[50] = INREG(MC_READ_CNTL_AB); |
625 | rinfo->save_regs[51] = INREG(MC_IOPAD_CNTL); |
626 | rinfo->save_regs[52] = INREG(MC_CHIP_IO_OE_CNTL_AB); |
627 | rinfo->save_regs[53] = INREG(MC_DEBUG); |
628 | } |
629 | rinfo->save_regs[54] = INREG(PAMAC0_DLY_CNTL); |
630 | rinfo->save_regs[55] = INREG(PAMAC1_DLY_CNTL); |
631 | rinfo->save_regs[56] = INREG(PAD_CTLR_MISC); |
632 | rinfo->save_regs[57] = INREG(FW_CNTL); |
633 | |
634 | if (rinfo->family >= CHIP_FAMILY_R300) { |
635 | rinfo->save_regs[58] = INMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER); |
636 | rinfo->save_regs[59] = INMC(rinfo, ixR300_MC_IMP_CNTL); |
637 | rinfo->save_regs[60] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0); |
638 | rinfo->save_regs[61] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1); |
639 | rinfo->save_regs[62] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0); |
640 | rinfo->save_regs[63] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1); |
641 | rinfo->save_regs[64] = INMC(rinfo, ixR300_MC_BIST_CNTL_3); |
642 | rinfo->save_regs[65] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0); |
643 | rinfo->save_regs[66] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1); |
644 | rinfo->save_regs[67] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0); |
645 | rinfo->save_regs[68] = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1); |
646 | rinfo->save_regs[69] = INMC(rinfo, ixR300_MC_DEBUG_CNTL); |
647 | rinfo->save_regs[70] = INMC(rinfo, ixR300_MC_DLL_CNTL); |
648 | rinfo->save_regs[71] = INMC(rinfo, ixR300_MC_IMP_CNTL_0); |
649 | rinfo->save_regs[72] = INMC(rinfo, ixR300_MC_ELPIDA_CNTL); |
650 | rinfo->save_regs[96] = INMC(rinfo, ixR300_MC_READ_CNTL_CD); |
651 | } else { |
652 | rinfo->save_regs[59] = INMC(rinfo, ixMC_IMP_CNTL); |
653 | rinfo->save_regs[65] = INMC(rinfo, ixMC_CHP_IO_CNTL_A0); |
654 | rinfo->save_regs[66] = INMC(rinfo, ixMC_CHP_IO_CNTL_A1); |
655 | rinfo->save_regs[67] = INMC(rinfo, ixMC_CHP_IO_CNTL_B0); |
656 | rinfo->save_regs[68] = INMC(rinfo, ixMC_CHP_IO_CNTL_B1); |
657 | rinfo->save_regs[71] = INMC(rinfo, ixMC_IMP_CNTL_0); |
658 | } |
659 | |
660 | rinfo->save_regs[73] = INPLL(pllMPLL_CNTL); |
661 | rinfo->save_regs[74] = INPLL(pllSPLL_CNTL); |
662 | rinfo->save_regs[75] = INPLL(pllMPLL_AUX_CNTL); |
663 | rinfo->save_regs[76] = INPLL(pllSPLL_AUX_CNTL); |
664 | rinfo->save_regs[77] = INPLL(pllM_SPLL_REF_FB_DIV); |
665 | rinfo->save_regs[78] = INPLL(pllAGP_PLL_CNTL); |
666 | rinfo->save_regs[79] = INREG(PAMAC2_DLY_CNTL); |
667 | |
668 | rinfo->save_regs[80] = INREG(OV0_BASE_ADDR); |
669 | rinfo->save_regs[82] = INREG(FP_GEN_CNTL); |
670 | rinfo->save_regs[83] = INREG(FP2_GEN_CNTL); |
671 | rinfo->save_regs[84] = INREG(TMDS_CNTL); |
672 | rinfo->save_regs[85] = INREG(TMDS_TRANSMITTER_CNTL); |
673 | rinfo->save_regs[86] = INREG(DISP_OUTPUT_CNTL); |
674 | rinfo->save_regs[87] = INREG(DISP_HW_DEBUG); |
675 | rinfo->save_regs[88] = INREG(TV_MASTER_CNTL); |
676 | rinfo->save_regs[89] = INPLL(pllP2PLL_REF_DIV); |
677 | rinfo->save_regs[92] = INPLL(pllPPLL_DIV_0); |
678 | rinfo->save_regs[93] = INPLL(pllPPLL_CNTL); |
679 | rinfo->save_regs[94] = INREG(GRPH_BUFFER_CNTL); |
680 | rinfo->save_regs[95] = INREG(GRPH2_BUFFER_CNTL); |
681 | rinfo->save_regs[96] = INREG(HDP_DEBUG); |
682 | rinfo->save_regs[97] = INPLL(pllMDLL_CKO); |
683 | rinfo->save_regs[98] = INPLL(pllMDLL_RDCKA); |
684 | rinfo->save_regs[99] = INPLL(pllMDLL_RDCKB); |
685 | } |
686 | |
687 | static void radeon_pm_restore_regs(struct radeonfb_info *rinfo) |
688 | { |
689 | OUTPLL(P2PLL_CNTL, rinfo->save_regs[8] & 0xFFFFFFFE); /* First */ |
690 | |
691 | OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]); |
692 | OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]); |
693 | OUTPLL(MCLK_CNTL, rinfo->save_regs[2]); |
694 | OUTPLL(SCLK_CNTL, rinfo->save_regs[3]); |
695 | OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]); |
696 | OUTPLL(VCLK_ECP_CNTL, rinfo->save_regs[5]); |
697 | OUTPLL(PIXCLKS_CNTL, rinfo->save_regs[6]); |
698 | OUTPLL(MCLK_MISC, rinfo->save_regs[7]); |
699 | if (rinfo->family == CHIP_FAMILY_RV350) |
700 | OUTPLL(SCLK_MORE_CNTL, rinfo->save_regs[34]); |
701 | |
702 | OUTREG(SURFACE_CNTL, rinfo->save_regs[29]); |
703 | OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); |
704 | OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); |
705 | OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); |
706 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); |
707 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
708 | |
709 | OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); |
710 | OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]); |
711 | OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11]); |
712 | OUTREG(LVDS_PLL_CNTL,rinfo->save_regs[12]); |
713 | OUTREG(TV_DAC_CNTL, rinfo->save_regs[13]); |
714 | OUTREG(BUS_CNTL1, rinfo->save_regs[14]); |
715 | OUTREG(CRTC_OFFSET_CNTL, rinfo->save_regs[15]); |
716 | OUTREG(AGP_CNTL, rinfo->save_regs[16]); |
717 | OUTREG(CRTC_GEN_CNTL, rinfo->save_regs[17]); |
718 | OUTREG(CRTC2_GEN_CNTL, rinfo->save_regs[18]); |
719 | OUTPLL(P2PLL_CNTL, rinfo->save_regs[8]); |
720 | |
721 | OUTREG(GPIOPAD_A, rinfo->save_regs[19]); |
722 | OUTREG(GPIOPAD_EN, rinfo->save_regs[20]); |
723 | OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]); |
724 | OUTREG(ZV_LCDPAD_A, rinfo->save_regs[22]); |
725 | OUTREG(ZV_LCDPAD_EN, rinfo->save_regs[23]); |
726 | OUTREG(ZV_LCDPAD_MASK, rinfo->save_regs[24]); |
727 | OUTREG(GPIO_VGA_DDC, rinfo->save_regs[25]); |
728 | OUTREG(GPIO_DVI_DDC, rinfo->save_regs[26]); |
729 | OUTREG(GPIO_MONID, rinfo->save_regs[27]); |
730 | OUTREG(GPIO_CRT2_DDC, rinfo->save_regs[28]); |
731 | } |
732 | |
733 | static void radeon_pm_disable_iopad(struct radeonfb_info *rinfo) |
734 | { |
735 | OUTREG(GPIOPAD_MASK, 0x0001ffff); |
736 | OUTREG(GPIOPAD_EN, 0x00000400); |
737 | OUTREG(GPIOPAD_A, 0x00000000); |
738 | OUTREG(ZV_LCDPAD_MASK, 0x00000000); |
739 | OUTREG(ZV_LCDPAD_EN, 0x00000000); |
740 | OUTREG(ZV_LCDPAD_A, 0x00000000); |
741 | OUTREG(GPIO_VGA_DDC, 0x00030000); |
742 | OUTREG(GPIO_DVI_DDC, 0x00000000); |
743 | OUTREG(GPIO_MONID, 0x00030000); |
744 | OUTREG(GPIO_CRT2_DDC, 0x00000000); |
745 | } |
746 | |
747 | static void radeon_pm_program_v2clk(struct radeonfb_info *rinfo) |
748 | { |
749 | /* Set v2clk to 65MHz */ |
750 | if (rinfo->family <= CHIP_FAMILY_RV280) { |
751 | OUTPLL(pllPIXCLKS_CNTL, |
752 | __INPLL(rinfo, pllPIXCLKS_CNTL) |
753 | & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK); |
754 | |
755 | OUTPLL(pllP2PLL_REF_DIV, 0x0000000c); |
756 | OUTPLL(pllP2PLL_CNTL, 0x0000bf00); |
757 | } else { |
758 | OUTPLL(pllP2PLL_REF_DIV, 0x0000000c); |
759 | INPLL(pllP2PLL_REF_DIV); |
760 | OUTPLL(pllP2PLL_CNTL, 0x0000a700); |
761 | } |
762 | |
763 | OUTPLL(pllP2PLL_DIV_0, 0x00020074 | P2PLL_DIV_0__P2PLL_ATOMIC_UPDATE_W); |
764 | |
765 | OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_SLEEP); |
766 | mdelay(1); |
767 | |
768 | OUTPLL(pllP2PLL_CNTL, INPLL(pllP2PLL_CNTL) & ~P2PLL_CNTL__P2PLL_RESET); |
769 | mdelay( 1); |
770 | |
771 | OUTPLL(pllPIXCLKS_CNTL, |
772 | (INPLL(pllPIXCLKS_CNTL) & ~PIXCLKS_CNTL__PIX2CLK_SRC_SEL_MASK) |
773 | | (0x03 << PIXCLKS_CNTL__PIX2CLK_SRC_SEL__SHIFT)); |
774 | mdelay( 1); |
775 | } |
776 | |
777 | static void radeon_pm_low_current(struct radeonfb_info *rinfo) |
778 | { |
779 | u32 reg; |
780 | |
781 | reg = INREG(BUS_CNTL1); |
782 | if (rinfo->family <= CHIP_FAMILY_RV280) { |
783 | reg &= ~BUS_CNTL1_MOBILE_PLATFORM_SEL_MASK; |
784 | reg |= BUS_CNTL1_AGPCLK_VALID | (1<<BUS_CNTL1_MOBILE_PLATFORM_SEL_SHIFT); |
785 | } else { |
786 | reg |= 0x4080; |
787 | } |
788 | OUTREG(BUS_CNTL1, reg); |
789 | |
790 | reg = INPLL(PLL_PWRMGT_CNTL); |
791 | reg |= PLL_PWRMGT_CNTL_SPLL_TURNOFF | PLL_PWRMGT_CNTL_PPLL_TURNOFF | |
792 | PLL_PWRMGT_CNTL_P2PLL_TURNOFF | PLL_PWRMGT_CNTL_TVPLL_TURNOFF; |
793 | reg &= ~PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK; |
794 | reg &= ~PLL_PWRMGT_CNTL_MOBILE_SU; |
795 | OUTPLL(PLL_PWRMGT_CNTL, reg); |
796 | |
797 | reg = INREG(TV_DAC_CNTL); |
798 | reg &= ~(TV_DAC_CNTL_BGADJ_MASK |TV_DAC_CNTL_DACADJ_MASK); |
799 | reg |=TV_DAC_CNTL_BGSLEEP | TV_DAC_CNTL_RDACPD | TV_DAC_CNTL_GDACPD | |
800 | TV_DAC_CNTL_BDACPD | |
801 | (8<<TV_DAC_CNTL_BGADJ__SHIFT) | (8<<TV_DAC_CNTL_DACADJ__SHIFT); |
802 | OUTREG(TV_DAC_CNTL, reg); |
803 | |
804 | reg = INREG(TMDS_TRANSMITTER_CNTL); |
805 | reg &= ~(TMDS_PLL_EN | TMDS_PLLRST); |
806 | OUTREG(TMDS_TRANSMITTER_CNTL, reg); |
807 | |
808 | reg = INREG(DAC_CNTL); |
809 | reg &= ~DAC_CMP_EN; |
810 | OUTREG(DAC_CNTL, reg); |
811 | |
812 | reg = INREG(DAC_CNTL2); |
813 | reg &= ~DAC2_CMP_EN; |
814 | OUTREG(DAC_CNTL2, reg); |
815 | |
816 | reg = INREG(TV_DAC_CNTL); |
817 | reg &= ~TV_DAC_CNTL_DETECT; |
818 | OUTREG(TV_DAC_CNTL, reg); |
819 | } |
820 | |
821 | static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo) |
822 | { |
823 | |
824 | u32 sclk_cntl, mclk_cntl, sclk_more_cntl; |
825 | |
826 | u32 pll_pwrmgt_cntl; |
827 | u32 clk_pwrmgt_cntl; |
828 | u32 clk_pin_cntl; |
829 | u32 vclk_ecp_cntl; |
830 | u32 pixclks_cntl; |
831 | u32 disp_mis_cntl; |
832 | u32 disp_pwr_man; |
833 | u32 tmp; |
834 | |
835 | /* Force Core Clocks */ |
836 | sclk_cntl = INPLL( pllSCLK_CNTL); |
837 | sclk_cntl |= SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT| |
838 | SCLK_CNTL__VIP_MAX_DYN_STOP_LAT| |
839 | SCLK_CNTL__RE_MAX_DYN_STOP_LAT| |
840 | SCLK_CNTL__PB_MAX_DYN_STOP_LAT| |
841 | SCLK_CNTL__TAM_MAX_DYN_STOP_LAT| |
842 | SCLK_CNTL__TDM_MAX_DYN_STOP_LAT| |
843 | SCLK_CNTL__RB_MAX_DYN_STOP_LAT| |
844 | |
845 | SCLK_CNTL__FORCE_DISP2| |
846 | SCLK_CNTL__FORCE_CP| |
847 | SCLK_CNTL__FORCE_HDP| |
848 | SCLK_CNTL__FORCE_DISP1| |
849 | SCLK_CNTL__FORCE_TOP| |
850 | SCLK_CNTL__FORCE_E2| |
851 | SCLK_CNTL__FORCE_SE| |
852 | SCLK_CNTL__FORCE_IDCT| |
853 | SCLK_CNTL__FORCE_VIP| |
854 | |
855 | SCLK_CNTL__FORCE_PB| |
856 | SCLK_CNTL__FORCE_TAM| |
857 | SCLK_CNTL__FORCE_TDM| |
858 | SCLK_CNTL__FORCE_RB| |
859 | SCLK_CNTL__FORCE_TV_SCLK| |
860 | SCLK_CNTL__FORCE_SUBPIC| |
861 | SCLK_CNTL__FORCE_OV0; |
862 | if (rinfo->family <= CHIP_FAMILY_RV280) |
863 | sclk_cntl |= SCLK_CNTL__FORCE_RE; |
864 | else |
865 | sclk_cntl |= SCLK_CNTL__SE_MAX_DYN_STOP_LAT | |
866 | SCLK_CNTL__E2_MAX_DYN_STOP_LAT | |
867 | SCLK_CNTL__TV_MAX_DYN_STOP_LAT | |
868 | SCLK_CNTL__HDP_MAX_DYN_STOP_LAT | |
869 | SCLK_CNTL__CP_MAX_DYN_STOP_LAT; |
870 | |
871 | OUTPLL( pllSCLK_CNTL, sclk_cntl); |
872 | |
873 | sclk_more_cntl = INPLL(pllSCLK_MORE_CNTL); |
874 | sclk_more_cntl |= SCLK_MORE_CNTL__FORCE_DISPREGS | |
875 | SCLK_MORE_CNTL__FORCE_MC_GUI | |
876 | SCLK_MORE_CNTL__FORCE_MC_HOST; |
877 | |
878 | OUTPLL(pllSCLK_MORE_CNTL, sclk_more_cntl); |
879 | |
880 | |
881 | mclk_cntl = INPLL( pllMCLK_CNTL); |
882 | mclk_cntl &= ~( MCLK_CNTL__FORCE_MCLKA | |
883 | MCLK_CNTL__FORCE_MCLKB | |
884 | MCLK_CNTL__FORCE_YCLKA | |
885 | MCLK_CNTL__FORCE_YCLKB | |
886 | MCLK_CNTL__FORCE_MC |
887 | ); |
888 | OUTPLL( pllMCLK_CNTL, mclk_cntl); |
889 | |
890 | /* Force Display clocks */ |
891 | vclk_ecp_cntl = INPLL( pllVCLK_ECP_CNTL); |
892 | vclk_ecp_cntl &= ~(VCLK_ECP_CNTL__PIXCLK_ALWAYS_ONb |
893 | | VCLK_ECP_CNTL__PIXCLK_DAC_ALWAYS_ONb); |
894 | vclk_ecp_cntl |= VCLK_ECP_CNTL__ECP_FORCE_ON; |
895 | OUTPLL( pllVCLK_ECP_CNTL, vclk_ecp_cntl); |
896 | |
897 | |
898 | pixclks_cntl = INPLL( pllPIXCLKS_CNTL); |
899 | pixclks_cntl &= ~( PIXCLKS_CNTL__PIXCLK_GV_ALWAYS_ONb | |
900 | PIXCLKS_CNTL__PIXCLK_BLEND_ALWAYS_ONb| |
901 | PIXCLKS_CNTL__PIXCLK_DIG_TMDS_ALWAYS_ONb | |
902 | PIXCLKS_CNTL__PIXCLK_LVDS_ALWAYS_ONb| |
903 | PIXCLKS_CNTL__PIXCLK_TMDS_ALWAYS_ONb| |
904 | PIXCLKS_CNTL__PIX2CLK_ALWAYS_ONb| |
905 | PIXCLKS_CNTL__PIX2CLK_DAC_ALWAYS_ONb); |
906 | |
907 | OUTPLL( pllPIXCLKS_CNTL, pixclks_cntl); |
908 | |
909 | /* Switch off LVDS interface */ |
910 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & |
911 | ~(LVDS_BLON | LVDS_EN | LVDS_ON | LVDS_DIGON)); |
912 | |
913 | /* Enable System power management */ |
914 | pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL); |
915 | |
916 | pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__SPLL_TURNOFF | |
917 | PLL_PWRMGT_CNTL__MPLL_TURNOFF| |
918 | PLL_PWRMGT_CNTL__PPLL_TURNOFF| |
919 | PLL_PWRMGT_CNTL__P2PLL_TURNOFF| |
920 | PLL_PWRMGT_CNTL__TVPLL_TURNOFF; |
921 | |
922 | OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl); |
923 | |
924 | clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL); |
925 | |
926 | clk_pwrmgt_cntl &= ~( CLK_PWRMGT_CNTL__MPLL_PWRMGT_OFF| |
927 | CLK_PWRMGT_CNTL__SPLL_PWRMGT_OFF| |
928 | CLK_PWRMGT_CNTL__PPLL_PWRMGT_OFF| |
929 | CLK_PWRMGT_CNTL__P2PLL_PWRMGT_OFF| |
930 | CLK_PWRMGT_CNTL__MCLK_TURNOFF| |
931 | CLK_PWRMGT_CNTL__SCLK_TURNOFF| |
932 | CLK_PWRMGT_CNTL__PCLK_TURNOFF| |
933 | CLK_PWRMGT_CNTL__P2CLK_TURNOFF| |
934 | CLK_PWRMGT_CNTL__TVPLL_PWRMGT_OFF| |
935 | CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN| |
936 | CLK_PWRMGT_CNTL__ENGINE_DYNCLK_MODE| |
937 | CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK| |
938 | CLK_PWRMGT_CNTL__CG_NO1_DEBUG_MASK |
939 | ); |
940 | |
941 | clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__GLOBAL_PMAN_EN |
942 | | CLK_PWRMGT_CNTL__DISP_PM; |
943 | |
944 | OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl); |
945 | |
946 | clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); |
947 | |
948 | clk_pin_cntl &= ~CLK_PIN_CNTL__ACCESS_REGS_IN_SUSPEND; |
949 | |
950 | /* because both INPLL and OUTPLL take the same lock, that's why. */ |
951 | tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; |
952 | OUTPLL( pllMCLK_MISC, tmp); |
953 | |
954 | /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset |
955 | * and radeon chip dependent. Thus we only enable it on Mac for |
956 | * now (until we get more info on how to compute the correct |
957 | * value for various X86 bridges). |
958 | */ |
959 | #ifdef CONFIG_PPC_PMAC |
960 | if (machine_is(powermac)) { |
961 | /* AGP PLL control */ |
962 | if (rinfo->family <= CHIP_FAMILY_RV280) { |
963 | OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); |
964 | OUTREG(BUS_CNTL1, |
965 | (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) |
966 | | (2<<BUS_CNTL1__MOBILE_PLATFORM_SEL__SHIFT)); // 440BX |
967 | } else { |
968 | OUTREG(BUS_CNTL1, INREG(BUS_CNTL1)); |
969 | OUTREG(BUS_CNTL1, (INREG(BUS_CNTL1) & ~0x4000) | 0x8000); |
970 | } |
971 | } |
972 | #endif |
973 | |
974 | OUTREG(CRTC_OFFSET_CNTL, (INREG(CRTC_OFFSET_CNTL) |
975 | & ~CRTC_OFFSET_CNTL__CRTC_STEREO_SYNC_OUT_EN)); |
976 | |
977 | clk_pin_cntl &= ~CLK_PIN_CNTL__CG_CLK_TO_OUTPIN; |
978 | clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb; |
979 | OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl); |
980 | |
981 | /* Solano2M */ |
982 | OUTREG(AGP_CNTL, |
983 | (INREG(AGP_CNTL) & ~(AGP_CNTL__MAX_IDLE_CLK_MASK)) |
984 | | (0x20<<AGP_CNTL__MAX_IDLE_CLK__SHIFT)); |
985 | |
986 | /* ACPI mode */ |
987 | /* because both INPLL and OUTPLL take the same lock, that's why. */ |
988 | tmp = INPLL( pllPLL_PWRMGT_CNTL) & ~PLL_PWRMGT_CNTL__PM_MODE_SEL; |
989 | OUTPLL( pllPLL_PWRMGT_CNTL, tmp); |
990 | |
991 | |
992 | disp_mis_cntl = INREG(DISP_MISC_CNTL); |
993 | |
994 | disp_mis_cntl &= ~( DISP_MISC_CNTL__SOFT_RESET_GRPH_PP | |
995 | DISP_MISC_CNTL__SOFT_RESET_SUBPIC_PP | |
996 | DISP_MISC_CNTL__SOFT_RESET_OV0_PP | |
997 | DISP_MISC_CNTL__SOFT_RESET_GRPH_SCLK| |
998 | DISP_MISC_CNTL__SOFT_RESET_SUBPIC_SCLK| |
999 | DISP_MISC_CNTL__SOFT_RESET_OV0_SCLK| |
1000 | DISP_MISC_CNTL__SOFT_RESET_GRPH2_PP| |
1001 | DISP_MISC_CNTL__SOFT_RESET_GRPH2_SCLK| |
1002 | DISP_MISC_CNTL__SOFT_RESET_LVDS| |
1003 | DISP_MISC_CNTL__SOFT_RESET_TMDS| |
1004 | DISP_MISC_CNTL__SOFT_RESET_DIG_TMDS| |
1005 | DISP_MISC_CNTL__SOFT_RESET_TV); |
1006 | |
1007 | OUTREG(DISP_MISC_CNTL, disp_mis_cntl); |
1008 | |
1009 | disp_pwr_man = INREG(DISP_PWR_MAN); |
1010 | |
1011 | disp_pwr_man &= ~( DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN | |
1012 | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN | |
1013 | DISP_PWR_MAN__DISP_PWR_MAN_DPMS_MASK| |
1014 | DISP_PWR_MAN__DISP_D3_RST| |
1015 | DISP_PWR_MAN__DISP_D3_REG_RST |
1016 | ); |
1017 | |
1018 | disp_pwr_man |= DISP_PWR_MAN__DISP_D3_GRPH_RST| |
1019 | DISP_PWR_MAN__DISP_D3_SUBPIC_RST| |
1020 | DISP_PWR_MAN__DISP_D3_OV0_RST| |
1021 | DISP_PWR_MAN__DISP_D1D2_GRPH_RST| |
1022 | DISP_PWR_MAN__DISP_D1D2_SUBPIC_RST| |
1023 | DISP_PWR_MAN__DISP_D1D2_OV0_RST| |
1024 | DISP_PWR_MAN__DIG_TMDS_ENABLE_RST| |
1025 | DISP_PWR_MAN__TV_ENABLE_RST| |
1026 | // DISP_PWR_MAN__AUTO_PWRUP_EN| |
1027 | 0; |
1028 | |
1029 | OUTREG(DISP_PWR_MAN, disp_pwr_man); |
1030 | |
1031 | clk_pwrmgt_cntl = INPLL( pllCLK_PWRMGT_CNTL); |
1032 | pll_pwrmgt_cntl = INPLL( pllPLL_PWRMGT_CNTL) ; |
1033 | clk_pin_cntl = INPLL( pllCLK_PIN_CNTL); |
1034 | disp_pwr_man = INREG(DISP_PWR_MAN); |
1035 | |
1036 | |
1037 | /* D2 */ |
1038 | clk_pwrmgt_cntl |= CLK_PWRMGT_CNTL__DISP_PM; |
1039 | pll_pwrmgt_cntl |= PLL_PWRMGT_CNTL__MOBILE_SU | PLL_PWRMGT_CNTL__SU_SCLK_USE_BCLK; |
1040 | clk_pin_cntl |= CLK_PIN_CNTL__XTALIN_ALWAYS_ONb; |
1041 | disp_pwr_man &= ~(DISP_PWR_MAN__DISP_PWR_MAN_D3_CRTC_EN_MASK |
1042 | | DISP_PWR_MAN__DISP2_PWR_MAN_D3_CRTC2_EN_MASK); |
1043 | |
1044 | OUTPLL( pllCLK_PWRMGT_CNTL, clk_pwrmgt_cntl); |
1045 | OUTPLL( pllPLL_PWRMGT_CNTL, pll_pwrmgt_cntl); |
1046 | OUTPLL( pllCLK_PIN_CNTL, clk_pin_cntl); |
1047 | OUTREG(DISP_PWR_MAN, disp_pwr_man); |
1048 | |
1049 | /* disable display request & disable display */ |
1050 | OUTREG( CRTC_GEN_CNTL, (INREG( CRTC_GEN_CNTL) & ~CRTC_GEN_CNTL__CRTC_EN) |
1051 | | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B); |
1052 | OUTREG( CRTC2_GEN_CNTL, (INREG( CRTC2_GEN_CNTL) & ~CRTC2_GEN_CNTL__CRTC2_EN) |
1053 | | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B); |
1054 | |
1055 | mdelay(17); |
1056 | |
1057 | } |
1058 | |
1059 | static void radeon_pm_yclk_mclk_sync(struct radeonfb_info *rinfo) |
1060 | { |
1061 | u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1; |
1062 | |
1063 | mc_chp_io_cntl_a1 = INMC( rinfo, ixMC_CHP_IO_CNTL_A1) |
1064 | & ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK; |
1065 | mc_chp_io_cntl_b1 = INMC( rinfo, ixMC_CHP_IO_CNTL_B1) |
1066 | & ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK; |
1067 | |
1068 | OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, value: mc_chp_io_cntl_a1 |
1069 | | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT)); |
1070 | OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, value: mc_chp_io_cntl_b1 |
1071 | | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT)); |
1072 | |
1073 | OUTMC( rinfo, ixMC_CHP_IO_CNTL_A1, value: mc_chp_io_cntl_a1); |
1074 | OUTMC( rinfo, ixMC_CHP_IO_CNTL_B1, value: mc_chp_io_cntl_b1); |
1075 | |
1076 | mdelay( 1); |
1077 | } |
1078 | |
1079 | static void radeon_pm_yclk_mclk_sync_m10(struct radeonfb_info *rinfo) |
1080 | { |
1081 | u32 mc_chp_io_cntl_a1, mc_chp_io_cntl_b1; |
1082 | |
1083 | mc_chp_io_cntl_a1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1) |
1084 | & ~MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA_MASK; |
1085 | mc_chp_io_cntl_b1 = INMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1) |
1086 | & ~MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB_MASK; |
1087 | |
1088 | OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, |
1089 | value: mc_chp_io_cntl_a1 | (1<<MC_CHP_IO_CNTL_A1__MEM_SYNC_ENA__SHIFT)); |
1090 | OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, |
1091 | value: mc_chp_io_cntl_b1 | (1<<MC_CHP_IO_CNTL_B1__MEM_SYNC_ENB__SHIFT)); |
1092 | |
1093 | OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_A1, value: mc_chp_io_cntl_a1); |
1094 | OUTMC( rinfo, ixR300_MC_CHP_IO_CNTL_B1, value: mc_chp_io_cntl_b1); |
1095 | |
1096 | mdelay( 1); |
1097 | } |
1098 | |
1099 | static void radeon_pm_program_mode_reg(struct radeonfb_info *rinfo, u16 value, |
1100 | u8 delay_required) |
1101 | { |
1102 | u32 mem_sdram_mode; |
1103 | |
1104 | mem_sdram_mode = INREG( MEM_SDRAM_MODE_REG); |
1105 | |
1106 | mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK; |
1107 | mem_sdram_mode |= (value<<MEM_SDRAM_MODE_REG__MEM_MODE_REG__SHIFT) |
1108 | | MEM_SDRAM_MODE_REG__MEM_CFG_TYPE; |
1109 | OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); |
1110 | if (delay_required >= 2) |
1111 | mdelay(1); |
1112 | |
1113 | mem_sdram_mode |= MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET; |
1114 | OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); |
1115 | if (delay_required >= 2) |
1116 | mdelay(1); |
1117 | |
1118 | mem_sdram_mode &= ~MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET; |
1119 | OUTREG( MEM_SDRAM_MODE_REG, mem_sdram_mode); |
1120 | if (delay_required >= 2) |
1121 | mdelay(1); |
1122 | |
1123 | if (delay_required) { |
1124 | do { |
1125 | if (delay_required >= 2) |
1126 | mdelay(1); |
1127 | } while ((INREG(MC_STATUS) |
1128 | & (MC_STATUS__MEM_PWRUP_COMPL_A | |
1129 | MC_STATUS__MEM_PWRUP_COMPL_B)) == 0); |
1130 | } |
1131 | } |
1132 | |
1133 | static void radeon_pm_m10_program_mode_wait(struct radeonfb_info *rinfo) |
1134 | { |
1135 | int cnt; |
1136 | |
1137 | for (cnt = 0; cnt < 100; ++cnt) { |
1138 | mdelay(1); |
1139 | if (INREG(MC_STATUS) & (MC_STATUS__MEM_PWRUP_COMPL_A |
1140 | | MC_STATUS__MEM_PWRUP_COMPL_B)) |
1141 | break; |
1142 | } |
1143 | } |
1144 | |
1145 | |
1146 | static void radeon_pm_enable_dll(struct radeonfb_info *rinfo) |
1147 | { |
1148 | #define DLL_RESET_DELAY 5 |
1149 | #define DLL_SLEEP_DELAY 1 |
1150 | |
1151 | u32 cko = INPLL(pllMDLL_CKO) | MDLL_CKO__MCKOA_SLEEP |
1152 | | MDLL_CKO__MCKOA_RESET; |
1153 | u32 cka = INPLL(pllMDLL_RDCKA) | MDLL_RDCKA__MRDCKA0_SLEEP |
1154 | | MDLL_RDCKA__MRDCKA1_SLEEP | MDLL_RDCKA__MRDCKA0_RESET |
1155 | | MDLL_RDCKA__MRDCKA1_RESET; |
1156 | u32 ckb = INPLL(pllMDLL_RDCKB) | MDLL_RDCKB__MRDCKB0_SLEEP |
1157 | | MDLL_RDCKB__MRDCKB1_SLEEP | MDLL_RDCKB__MRDCKB0_RESET |
1158 | | MDLL_RDCKB__MRDCKB1_RESET; |
1159 | |
1160 | /* Setting up the DLL range for write */ |
1161 | OUTPLL(pllMDLL_CKO, cko); |
1162 | OUTPLL(pllMDLL_RDCKA, cka); |
1163 | OUTPLL(pllMDLL_RDCKB, ckb); |
1164 | |
1165 | mdelay(DLL_RESET_DELAY*2); |
1166 | |
1167 | cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP); |
1168 | OUTPLL(pllMDLL_CKO, cko); |
1169 | mdelay(DLL_SLEEP_DELAY); |
1170 | cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET); |
1171 | OUTPLL(pllMDLL_CKO, cko); |
1172 | mdelay(DLL_RESET_DELAY); |
1173 | |
1174 | cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP); |
1175 | OUTPLL(pllMDLL_RDCKA, cka); |
1176 | mdelay(DLL_SLEEP_DELAY); |
1177 | cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET); |
1178 | OUTPLL(pllMDLL_RDCKA, cka); |
1179 | mdelay(DLL_RESET_DELAY); |
1180 | |
1181 | ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP); |
1182 | OUTPLL(pllMDLL_RDCKB, ckb); |
1183 | mdelay(DLL_SLEEP_DELAY); |
1184 | ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET); |
1185 | OUTPLL(pllMDLL_RDCKB, ckb); |
1186 | mdelay(DLL_RESET_DELAY); |
1187 | |
1188 | |
1189 | #undef DLL_RESET_DELAY |
1190 | #undef DLL_SLEEP_DELAY |
1191 | } |
1192 | |
1193 | static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo) |
1194 | { |
1195 | u32 dll_value; |
1196 | u32 dll_sleep_mask = 0; |
1197 | u32 dll_reset_mask = 0; |
1198 | u32 mc; |
1199 | |
1200 | #define DLL_RESET_DELAY 5 |
1201 | #define DLL_SLEEP_DELAY 1 |
1202 | |
1203 | OUTMC(rinfo, ixR300_MC_DLL_CNTL, value: rinfo->save_regs[70]); |
1204 | mc = INREG(MC_CNTL); |
1205 | /* Check which channels are enabled */ |
1206 | switch (mc & 0x3) { |
1207 | case 1: |
1208 | if (mc & 0x4) |
1209 | break; |
1210 | fallthrough; |
1211 | case 2: |
1212 | dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP; |
1213 | dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET; |
1214 | fallthrough; |
1215 | case 0: |
1216 | dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP; |
1217 | dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET; |
1218 | } |
1219 | switch (mc & 0x3) { |
1220 | case 1: |
1221 | if (!(mc & 0x4)) |
1222 | break; |
1223 | fallthrough; |
1224 | case 2: |
1225 | dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP; |
1226 | dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET; |
1227 | dll_sleep_mask |= MDLL_R300_RDCK__MRDCKC_SLEEP; |
1228 | dll_reset_mask |= MDLL_R300_RDCK__MRDCKC_RESET; |
1229 | } |
1230 | |
1231 | dll_value = INPLL(pllMDLL_RDCKA); |
1232 | |
1233 | /* Power Up */ |
1234 | dll_value &= ~(dll_sleep_mask); |
1235 | OUTPLL(pllMDLL_RDCKA, dll_value); |
1236 | mdelay( DLL_SLEEP_DELAY); |
1237 | |
1238 | dll_value &= ~(dll_reset_mask); |
1239 | OUTPLL(pllMDLL_RDCKA, dll_value); |
1240 | mdelay( DLL_RESET_DELAY); |
1241 | |
1242 | #undef DLL_RESET_DELAY |
1243 | #undef DLL_SLEEP_DELAY |
1244 | } |
1245 | |
1246 | |
1247 | static void radeon_pm_full_reset_sdram(struct radeonfb_info *rinfo) |
1248 | { |
1249 | u32 crtcGenCntl, crtcGenCntl2, memRefreshCntl, crtc_more_cntl, |
1250 | fp_gen_cntl, fp2_gen_cntl; |
1251 | |
1252 | crtcGenCntl = INREG( CRTC_GEN_CNTL); |
1253 | crtcGenCntl2 = INREG( CRTC2_GEN_CNTL); |
1254 | |
1255 | crtc_more_cntl = INREG( CRTC_MORE_CNTL); |
1256 | fp_gen_cntl = INREG( FP_GEN_CNTL); |
1257 | fp2_gen_cntl = INREG( FP2_GEN_CNTL); |
1258 | |
1259 | |
1260 | OUTREG( CRTC_MORE_CNTL, 0); |
1261 | OUTREG( FP_GEN_CNTL, 0); |
1262 | OUTREG( FP2_GEN_CNTL,0); |
1263 | |
1264 | OUTREG( CRTC_GEN_CNTL, (crtcGenCntl | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B) ); |
1265 | OUTREG( CRTC2_GEN_CNTL, (crtcGenCntl2 | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B) ); |
1266 | |
1267 | /* This is the code for the Aluminium PowerBooks M10 / iBooks M11 */ |
1268 | if (rinfo->family == CHIP_FAMILY_RV350) { |
1269 | u32 sdram_mode_reg = rinfo->save_regs[35]; |
1270 | static const u32 default_mrtable[] = |
1271 | { 0x21320032, |
1272 | 0x21321000, 0xa1321000, 0x21321000, 0xffffffff, |
1273 | 0x21320032, 0xa1320032, 0x21320032, 0xffffffff, |
1274 | 0x21321002, 0xa1321002, 0x21321002, 0xffffffff, |
1275 | 0x21320132, 0xa1320132, 0x21320132, 0xffffffff, |
1276 | 0x21320032, 0xa1320032, 0x21320032, 0xffffffff, |
1277 | 0x31320032 }; |
1278 | |
1279 | const u32 *mrtable = default_mrtable; |
1280 | int i, mrtable_size = ARRAY_SIZE(default_mrtable); |
1281 | |
1282 | mdelay(30); |
1283 | |
1284 | /* Disable refresh */ |
1285 | memRefreshCntl = INREG( MEM_REFRESH_CNTL) |
1286 | & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; |
1287 | OUTREG( MEM_REFRESH_CNTL, memRefreshCntl |
1288 | | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); |
1289 | |
1290 | /* Configure and enable M & SPLLs */ |
1291 | radeon_pm_enable_dll_m10(rinfo); |
1292 | radeon_pm_yclk_mclk_sync_m10(rinfo); |
1293 | |
1294 | #ifdef CONFIG_PPC |
1295 | if (rinfo->of_node != NULL) { |
1296 | int size; |
1297 | |
1298 | mrtable = of_get_property(rinfo->of_node, "ATY,MRT" , &size); |
1299 | if (mrtable) |
1300 | mrtable_size = size >> 2; |
1301 | else |
1302 | mrtable = default_mrtable; |
1303 | } |
1304 | #endif /* CONFIG_PPC */ |
1305 | |
1306 | /* Program the SDRAM */ |
1307 | sdram_mode_reg = mrtable[0]; |
1308 | OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg); |
1309 | for (i = 0; i < mrtable_size; i++) { |
1310 | if (mrtable[i] == 0xffffffffu) |
1311 | radeon_pm_m10_program_mode_wait(rinfo); |
1312 | else { |
1313 | sdram_mode_reg &= ~(MEM_SDRAM_MODE_REG__MEM_MODE_REG_MASK |
1314 | | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE |
1315 | | MEM_SDRAM_MODE_REG__MEM_SDRAM_RESET); |
1316 | sdram_mode_reg |= mrtable[i]; |
1317 | |
1318 | OUTREG(MEM_SDRAM_MODE_REG, sdram_mode_reg); |
1319 | mdelay(1); |
1320 | } |
1321 | } |
1322 | |
1323 | /* Restore memory refresh */ |
1324 | OUTREG(MEM_REFRESH_CNTL, memRefreshCntl); |
1325 | mdelay(30); |
1326 | |
1327 | } |
1328 | /* Here come the desktop RV200 "QW" card */ |
1329 | else if (!rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV200) { |
1330 | /* Disable refresh */ |
1331 | memRefreshCntl = INREG( MEM_REFRESH_CNTL) |
1332 | & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; |
1333 | OUTREG(MEM_REFRESH_CNTL, memRefreshCntl |
1334 | | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); |
1335 | mdelay(30); |
1336 | |
1337 | /* Reset memory */ |
1338 | OUTREG(MEM_SDRAM_MODE_REG, |
1339 | INREG( MEM_SDRAM_MODE_REG) & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1340 | |
1341 | radeon_pm_program_mode_reg(rinfo, value: 0x2002, delay_required: 2); |
1342 | radeon_pm_program_mode_reg(rinfo, value: 0x0132, delay_required: 2); |
1343 | radeon_pm_program_mode_reg(rinfo, value: 0x0032, delay_required: 2); |
1344 | |
1345 | OUTREG(MEM_SDRAM_MODE_REG, |
1346 | INREG(MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1347 | |
1348 | OUTREG( MEM_REFRESH_CNTL, memRefreshCntl); |
1349 | |
1350 | } |
1351 | /* The M6 */ |
1352 | else if (rinfo->is_mobility && rinfo->family == CHIP_FAMILY_RV100) { |
1353 | /* Disable refresh */ |
1354 | memRefreshCntl = INREG(EXT_MEM_CNTL) & ~(1 << 20); |
1355 | OUTREG( EXT_MEM_CNTL, memRefreshCntl | (1 << 20)); |
1356 | |
1357 | /* Reset memory */ |
1358 | OUTREG( MEM_SDRAM_MODE_REG, |
1359 | INREG( MEM_SDRAM_MODE_REG) |
1360 | & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1361 | |
1362 | /* DLL */ |
1363 | radeon_pm_enable_dll(rinfo); |
1364 | |
1365 | /* MLCK / YCLK sync */ |
1366 | radeon_pm_yclk_mclk_sync(rinfo); |
1367 | |
1368 | /* Program Mode Register */ |
1369 | radeon_pm_program_mode_reg(rinfo, value: 0x2000, delay_required: 1); |
1370 | radeon_pm_program_mode_reg(rinfo, value: 0x2001, delay_required: 1); |
1371 | radeon_pm_program_mode_reg(rinfo, value: 0x2002, delay_required: 1); |
1372 | radeon_pm_program_mode_reg(rinfo, value: 0x0132, delay_required: 1); |
1373 | radeon_pm_program_mode_reg(rinfo, value: 0x0032, delay_required: 1); |
1374 | |
1375 | /* Complete & re-enable refresh */ |
1376 | OUTREG( MEM_SDRAM_MODE_REG, |
1377 | INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1378 | |
1379 | OUTREG(EXT_MEM_CNTL, memRefreshCntl); |
1380 | } |
1381 | /* And finally, the M7..M9 models, including M9+ (RV280) */ |
1382 | else if (rinfo->is_mobility) { |
1383 | |
1384 | /* Disable refresh */ |
1385 | memRefreshCntl = INREG( MEM_REFRESH_CNTL) |
1386 | & ~MEM_REFRESH_CNTL__MEM_REFRESH_DIS; |
1387 | OUTREG( MEM_REFRESH_CNTL, memRefreshCntl |
1388 | | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); |
1389 | |
1390 | /* Reset memory */ |
1391 | OUTREG( MEM_SDRAM_MODE_REG, |
1392 | INREG( MEM_SDRAM_MODE_REG) |
1393 | & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1394 | |
1395 | /* DLL */ |
1396 | radeon_pm_enable_dll(rinfo); |
1397 | |
1398 | /* MLCK / YCLK sync */ |
1399 | radeon_pm_yclk_mclk_sync(rinfo); |
1400 | |
1401 | /* M6, M7 and M9 so far ... */ |
1402 | if (rinfo->family <= CHIP_FAMILY_RV250) { |
1403 | radeon_pm_program_mode_reg(rinfo, value: 0x2000, delay_required: 1); |
1404 | radeon_pm_program_mode_reg(rinfo, value: 0x2001, delay_required: 1); |
1405 | radeon_pm_program_mode_reg(rinfo, value: 0x2002, delay_required: 1); |
1406 | radeon_pm_program_mode_reg(rinfo, value: 0x0132, delay_required: 1); |
1407 | radeon_pm_program_mode_reg(rinfo, value: 0x0032, delay_required: 1); |
1408 | } |
1409 | /* M9+ (iBook G4) */ |
1410 | else if (rinfo->family == CHIP_FAMILY_RV280) { |
1411 | radeon_pm_program_mode_reg(rinfo, value: 0x2000, delay_required: 1); |
1412 | radeon_pm_program_mode_reg(rinfo, value: 0x0132, delay_required: 1); |
1413 | radeon_pm_program_mode_reg(rinfo, value: 0x0032, delay_required: 1); |
1414 | } |
1415 | |
1416 | /* Complete & re-enable refresh */ |
1417 | OUTREG( MEM_SDRAM_MODE_REG, |
1418 | INREG( MEM_SDRAM_MODE_REG) | MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1419 | |
1420 | OUTREG( MEM_REFRESH_CNTL, memRefreshCntl); |
1421 | } |
1422 | |
1423 | OUTREG( CRTC_GEN_CNTL, crtcGenCntl); |
1424 | OUTREG( CRTC2_GEN_CNTL, crtcGenCntl2); |
1425 | OUTREG( FP_GEN_CNTL, fp_gen_cntl); |
1426 | OUTREG( FP2_GEN_CNTL, fp2_gen_cntl); |
1427 | |
1428 | OUTREG( CRTC_MORE_CNTL, crtc_more_cntl); |
1429 | |
1430 | mdelay( 15); |
1431 | } |
1432 | |
1433 | #if defined(CONFIG_X86) || defined(CONFIG_PPC_PMAC) |
1434 | static void radeon_pm_reset_pad_ctlr_strength(struct radeonfb_info *rinfo) |
1435 | { |
1436 | u32 tmp, tmp2; |
1437 | int i,j; |
1438 | |
1439 | /* Reset the PAD_CTLR_STRENGTH & wait for it to be stable */ |
1440 | INREG(PAD_CTLR_STRENGTH); |
1441 | OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~PAD_MANUAL_OVERRIDE); |
1442 | tmp = INREG(PAD_CTLR_STRENGTH); |
1443 | for (i = j = 0; i < 65; ++i) { |
1444 | mdelay(1); |
1445 | tmp2 = INREG(PAD_CTLR_STRENGTH); |
1446 | if (tmp != tmp2) { |
1447 | tmp = tmp2; |
1448 | i = 0; |
1449 | j++; |
1450 | if (j > 10) { |
1451 | printk(KERN_WARNING "radeon: PAD_CTLR_STRENGTH doesn't " |
1452 | "stabilize !\n" ); |
1453 | break; |
1454 | } |
1455 | } |
1456 | } |
1457 | } |
1458 | |
1459 | static void radeon_pm_all_ppls_off(struct radeonfb_info *rinfo) |
1460 | { |
1461 | u32 tmp; |
1462 | |
1463 | tmp = INPLL(pllPPLL_CNTL); |
1464 | OUTPLL(pllPPLL_CNTL, tmp | 0x3); |
1465 | tmp = INPLL(pllP2PLL_CNTL); |
1466 | OUTPLL(pllP2PLL_CNTL, tmp | 0x3); |
1467 | tmp = INPLL(pllSPLL_CNTL); |
1468 | OUTPLL(pllSPLL_CNTL, tmp | 0x3); |
1469 | tmp = INPLL(pllMPLL_CNTL); |
1470 | OUTPLL(pllMPLL_CNTL, tmp | 0x3); |
1471 | } |
1472 | |
1473 | static void radeon_pm_start_mclk_sclk(struct radeonfb_info *rinfo) |
1474 | { |
1475 | u32 tmp; |
1476 | |
1477 | /* Switch SPLL to PCI source */ |
1478 | tmp = INPLL(pllSCLK_CNTL); |
1479 | OUTPLL(pllSCLK_CNTL, tmp & ~SCLK_CNTL__SCLK_SRC_SEL_MASK); |
1480 | |
1481 | /* Reconfigure SPLL charge pump, VCO gain, duty cycle */ |
1482 | tmp = INPLL(pllSPLL_CNTL); |
1483 | OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN); |
1484 | radeon_pll_errata_after_index(rinfo); |
1485 | OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); |
1486 | radeon_pll_errata_after_data(rinfo); |
1487 | |
1488 | /* Set SPLL feedback divider */ |
1489 | tmp = INPLL(pllM_SPLL_REF_FB_DIV); |
1490 | tmp = (tmp & 0xff00fffful) | (rinfo->save_regs[77] & 0x00ff0000ul); |
1491 | OUTPLL(pllM_SPLL_REF_FB_DIV, tmp); |
1492 | |
1493 | /* Power up SPLL */ |
1494 | tmp = INPLL(pllSPLL_CNTL); |
1495 | OUTPLL(pllSPLL_CNTL, tmp & ~1); |
1496 | (void)INPLL(pllSPLL_CNTL); |
1497 | |
1498 | mdelay(10); |
1499 | |
1500 | /* Release SPLL reset */ |
1501 | tmp = INPLL(pllSPLL_CNTL); |
1502 | OUTPLL(pllSPLL_CNTL, tmp & ~0x2); |
1503 | (void)INPLL(pllSPLL_CNTL); |
1504 | |
1505 | mdelay(10); |
1506 | |
1507 | /* Select SCLK source */ |
1508 | tmp = INPLL(pllSCLK_CNTL); |
1509 | tmp &= ~SCLK_CNTL__SCLK_SRC_SEL_MASK; |
1510 | tmp |= rinfo->save_regs[3] & SCLK_CNTL__SCLK_SRC_SEL_MASK; |
1511 | OUTPLL(pllSCLK_CNTL, tmp); |
1512 | (void)INPLL(pllSCLK_CNTL); |
1513 | |
1514 | mdelay(10); |
1515 | |
1516 | /* Reconfigure MPLL charge pump, VCO gain, duty cycle */ |
1517 | tmp = INPLL(pllMPLL_CNTL); |
1518 | OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN); |
1519 | radeon_pll_errata_after_index(rinfo); |
1520 | OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); |
1521 | radeon_pll_errata_after_data(rinfo); |
1522 | |
1523 | /* Set MPLL feedback divider */ |
1524 | tmp = INPLL(pllM_SPLL_REF_FB_DIV); |
1525 | tmp = (tmp & 0xffff00fful) | (rinfo->save_regs[77] & 0x0000ff00ul); |
1526 | |
1527 | OUTPLL(pllM_SPLL_REF_FB_DIV, tmp); |
1528 | /* Power up MPLL */ |
1529 | tmp = INPLL(pllMPLL_CNTL); |
1530 | OUTPLL(pllMPLL_CNTL, tmp & ~0x2); |
1531 | (void)INPLL(pllMPLL_CNTL); |
1532 | |
1533 | mdelay(10); |
1534 | |
1535 | /* Un-reset MPLL */ |
1536 | tmp = INPLL(pllMPLL_CNTL); |
1537 | OUTPLL(pllMPLL_CNTL, tmp & ~0x1); |
1538 | (void)INPLL(pllMPLL_CNTL); |
1539 | |
1540 | mdelay(10); |
1541 | |
1542 | /* Select source for MCLK */ |
1543 | tmp = INPLL(pllMCLK_CNTL); |
1544 | tmp |= rinfo->save_regs[2] & 0xffff; |
1545 | OUTPLL(pllMCLK_CNTL, tmp); |
1546 | (void)INPLL(pllMCLK_CNTL); |
1547 | |
1548 | mdelay(10); |
1549 | } |
1550 | |
1551 | static void radeon_pm_m10_disable_spread_spectrum(struct radeonfb_info *rinfo) |
1552 | { |
1553 | u32 r2ec; |
1554 | |
1555 | /* GACK ! I though we didn't have a DDA on Radeon's anymore |
1556 | * here we rewrite with the same value, ... I suppose we clear |
1557 | * some bits that are already clear ? Or maybe this 0x2ec |
1558 | * register is something new ? |
1559 | */ |
1560 | mdelay(20); |
1561 | r2ec = INREG(VGA_DDA_ON_OFF); |
1562 | OUTREG(VGA_DDA_ON_OFF, r2ec); |
1563 | mdelay(1); |
1564 | |
1565 | /* Spread spectrum PLLL off */ |
1566 | OUTPLL(pllSSPLL_CNTL, 0xbf03); |
1567 | |
1568 | /* Spread spectrum disabled */ |
1569 | OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3); |
1570 | |
1571 | /* The trace shows read & rewrite of LVDS_PLL_CNTL here with same |
1572 | * value, not sure what for... |
1573 | */ |
1574 | |
1575 | r2ec |= 0x3f0; |
1576 | OUTREG(VGA_DDA_ON_OFF, r2ec); |
1577 | mdelay(1); |
1578 | } |
1579 | |
1580 | static void radeon_pm_m10_enable_lvds_spread_spectrum(struct radeonfb_info *rinfo) |
1581 | { |
1582 | u32 r2ec, tmp; |
1583 | |
1584 | /* GACK (bis) ! I though we didn't have a DDA on Radeon's anymore |
1585 | * here we rewrite with the same value, ... I suppose we clear/set |
1586 | * some bits that are already clear/set ? |
1587 | */ |
1588 | r2ec = INREG(VGA_DDA_ON_OFF); |
1589 | OUTREG(VGA_DDA_ON_OFF, r2ec); |
1590 | mdelay(1); |
1591 | |
1592 | /* Enable spread spectrum */ |
1593 | OUTPLL(pllSSPLL_CNTL, rinfo->save_regs[43] | 3); |
1594 | mdelay(3); |
1595 | |
1596 | OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44]); |
1597 | OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45]); |
1598 | tmp = INPLL(pllSSPLL_CNTL); |
1599 | OUTPLL(pllSSPLL_CNTL, tmp & ~0x2); |
1600 | mdelay(6); |
1601 | tmp = INPLL(pllSSPLL_CNTL); |
1602 | OUTPLL(pllSSPLL_CNTL, tmp & ~0x1); |
1603 | mdelay(5); |
1604 | |
1605 | OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90]); |
1606 | |
1607 | r2ec |= 8; |
1608 | OUTREG(VGA_DDA_ON_OFF, r2ec); |
1609 | mdelay(20); |
1610 | |
1611 | /* Enable LVDS interface */ |
1612 | tmp = INREG(LVDS_GEN_CNTL); |
1613 | OUTREG(LVDS_GEN_CNTL, tmp | LVDS_EN); |
1614 | |
1615 | /* Enable LVDS_PLL */ |
1616 | tmp = INREG(LVDS_PLL_CNTL); |
1617 | tmp &= ~0x30000; |
1618 | tmp |= 0x10000; |
1619 | OUTREG(LVDS_PLL_CNTL, tmp); |
1620 | |
1621 | OUTPLL(pllSCLK_MORE_CNTL, rinfo->save_regs[34]); |
1622 | OUTPLL(pllSS_TST_CNTL, rinfo->save_regs[91]); |
1623 | |
1624 | /* The trace reads that one here, waiting for something to settle down ? */ |
1625 | INREG(RBBM_STATUS); |
1626 | |
1627 | /* Ugh ? SS_TST_DEC is supposed to be a read register in the |
1628 | * R300 register spec at least... |
1629 | */ |
1630 | tmp = INPLL(pllSS_TST_CNTL); |
1631 | tmp |= 0x00400000; |
1632 | OUTPLL(pllSS_TST_CNTL, tmp); |
1633 | } |
1634 | |
1635 | static void radeon_pm_restore_pixel_pll(struct radeonfb_info *rinfo) |
1636 | { |
1637 | u32 tmp; |
1638 | |
1639 | OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN); |
1640 | radeon_pll_errata_after_index(rinfo); |
1641 | OUTREG8(CLOCK_CNTL_DATA, 0); |
1642 | radeon_pll_errata_after_data(rinfo); |
1643 | |
1644 | tmp = INPLL(pllVCLK_ECP_CNTL); |
1645 | OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80); |
1646 | mdelay(5); |
1647 | |
1648 | tmp = INPLL(pllPPLL_REF_DIV); |
1649 | tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div; |
1650 | OUTPLL(pllPPLL_REF_DIV, tmp); |
1651 | INPLL(pllPPLL_REF_DIV); |
1652 | |
1653 | /* Reconfigure SPLL charge pump, VCO gain, duty cycle, |
1654 | * probably useless since we already did it ... |
1655 | */ |
1656 | tmp = INPLL(pllPPLL_CNTL); |
1657 | OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN); |
1658 | radeon_pll_errata_after_index(rinfo); |
1659 | OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); |
1660 | radeon_pll_errata_after_data(rinfo); |
1661 | |
1662 | /* Restore our "reference" PPLL divider set by firmware |
1663 | * according to proper spread spectrum calculations |
1664 | */ |
1665 | OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]); |
1666 | |
1667 | tmp = INPLL(pllPPLL_CNTL); |
1668 | OUTPLL(pllPPLL_CNTL, tmp & ~0x2); |
1669 | mdelay(5); |
1670 | |
1671 | tmp = INPLL(pllPPLL_CNTL); |
1672 | OUTPLL(pllPPLL_CNTL, tmp & ~0x1); |
1673 | mdelay(5); |
1674 | |
1675 | tmp = INPLL(pllVCLK_ECP_CNTL); |
1676 | OUTPLL(pllVCLK_ECP_CNTL, tmp | 3); |
1677 | mdelay(5); |
1678 | |
1679 | tmp = INPLL(pllVCLK_ECP_CNTL); |
1680 | OUTPLL(pllVCLK_ECP_CNTL, tmp | 3); |
1681 | mdelay(5); |
1682 | |
1683 | /* Switch pixel clock to firmware default div 0 */ |
1684 | OUTREG8(CLOCK_CNTL_INDEX+1, 0); |
1685 | radeon_pll_errata_after_index(rinfo); |
1686 | radeon_pll_errata_after_data(rinfo); |
1687 | } |
1688 | |
1689 | static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo) |
1690 | { |
1691 | OUTREG(MC_CNTL, rinfo->save_regs[46]); |
1692 | OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]); |
1693 | OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]); |
1694 | OUTREG(MEM_SDRAM_MODE_REG, |
1695 | rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1696 | OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]); |
1697 | OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]); |
1698 | OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]); |
1699 | OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]); |
1700 | OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]); |
1701 | OUTREG(MC_DEBUG, rinfo->save_regs[53]); |
1702 | |
1703 | OUTMC(rinfo, ixR300_MC_MC_INIT_WR_LAT_TIMER, value: rinfo->save_regs[58]); |
1704 | OUTMC(rinfo, ixR300_MC_IMP_CNTL, value: rinfo->save_regs[59]); |
1705 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C0, value: rinfo->save_regs[60]); |
1706 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_C1, value: rinfo->save_regs[61]); |
1707 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D0, value: rinfo->save_regs[62]); |
1708 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_D1, value: rinfo->save_regs[63]); |
1709 | OUTMC(rinfo, ixR300_MC_BIST_CNTL_3, value: rinfo->save_regs[64]); |
1710 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A0, value: rinfo->save_regs[65]); |
1711 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_A1, value: rinfo->save_regs[66]); |
1712 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B0, value: rinfo->save_regs[67]); |
1713 | OUTMC(rinfo, ixR300_MC_CHP_IO_CNTL_B1, value: rinfo->save_regs[68]); |
1714 | OUTMC(rinfo, ixR300_MC_DEBUG_CNTL, value: rinfo->save_regs[69]); |
1715 | OUTMC(rinfo, ixR300_MC_DLL_CNTL, value: rinfo->save_regs[70]); |
1716 | OUTMC(rinfo, ixR300_MC_IMP_CNTL_0, value: rinfo->save_regs[71]); |
1717 | OUTMC(rinfo, ixR300_MC_ELPIDA_CNTL, value: rinfo->save_regs[72]); |
1718 | OUTMC(rinfo, ixR300_MC_READ_CNTL_CD, value: rinfo->save_regs[96]); |
1719 | OUTREG(MC_IND_INDEX, 0); |
1720 | } |
1721 | |
1722 | static void radeon_reinitialize_M10(struct radeonfb_info *rinfo) |
1723 | { |
1724 | u32 tmp, i; |
1725 | |
1726 | /* Restore a bunch of registers first */ |
1727 | OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); |
1728 | OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); |
1729 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); |
1730 | OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); |
1731 | OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]); |
1732 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
1733 | OUTREG(BUS_CNTL, rinfo->save_regs[36]); |
1734 | OUTREG(BUS_CNTL1, rinfo->save_regs[14]); |
1735 | OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]); |
1736 | OUTREG(FCP_CNTL, rinfo->save_regs[38]); |
1737 | OUTREG(RBBM_CNTL, rinfo->save_regs[39]); |
1738 | OUTREG(DAC_CNTL, rinfo->save_regs[40]); |
1739 | OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8); |
1740 | OUTREG(DAC_MACRO_CNTL, (INREG(DAC_MACRO_CNTL) & ~0x6) | 8); |
1741 | |
1742 | /* Hrm... */ |
1743 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE); |
1744 | |
1745 | /* Reset the PAD CTLR */ |
1746 | radeon_pm_reset_pad_ctlr_strength(rinfo); |
1747 | |
1748 | /* Some PLLs are Read & written identically in the trace here... |
1749 | * I suppose it's actually to switch them all off & reset, |
1750 | * let's assume off is what we want. I'm just doing that for all major PLLs now. |
1751 | */ |
1752 | radeon_pm_all_ppls_off(rinfo); |
1753 | |
1754 | /* Clear tiling, reset swappers */ |
1755 | INREG(SURFACE_CNTL); |
1756 | OUTREG(SURFACE_CNTL, 0); |
1757 | |
1758 | /* Some black magic with TV_DAC_CNTL, we should restore those from backups |
1759 | * rather than hard coding... |
1760 | */ |
1761 | tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK; |
1762 | tmp |= 8 << TV_DAC_CNTL_BGADJ__SHIFT; |
1763 | OUTREG(TV_DAC_CNTL, tmp); |
1764 | |
1765 | tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK; |
1766 | tmp |= 7 << TV_DAC_CNTL_DACADJ__SHIFT; |
1767 | OUTREG(TV_DAC_CNTL, tmp); |
1768 | |
1769 | /* More registers restored */ |
1770 | OUTREG(AGP_CNTL, rinfo->save_regs[16]); |
1771 | OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]); |
1772 | OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); |
1773 | |
1774 | /* Hrmmm ... What is that ? */ |
1775 | tmp = rinfo->save_regs[1] |
1776 | & ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK | |
1777 | CLK_PWRMGT_CNTL__MC_BUSY); |
1778 | OUTPLL(pllCLK_PWRMGT_CNTL, tmp); |
1779 | |
1780 | OUTREG(PAD_CTLR_MISC, rinfo->save_regs[56]); |
1781 | OUTREG(FW_CNTL, rinfo->save_regs[57]); |
1782 | OUTREG(HDP_DEBUG, rinfo->save_regs[96]); |
1783 | OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]); |
1784 | OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]); |
1785 | OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]); |
1786 | |
1787 | /* Restore Memory Controller configuration */ |
1788 | radeon_pm_m10_reconfigure_mc(rinfo); |
1789 | |
1790 | /* Make sure CRTC's dont touch memory */ |
1791 | OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL) |
1792 | | CRTC_GEN_CNTL__CRTC_DISP_REQ_EN_B); |
1793 | OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL) |
1794 | | CRTC2_GEN_CNTL__CRTC2_DISP_REQ_EN_B); |
1795 | mdelay(30); |
1796 | |
1797 | /* Disable SDRAM refresh */ |
1798 | OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL) |
1799 | | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); |
1800 | |
1801 | /* Restore XTALIN routing (CLK_PIN_CNTL) */ |
1802 | OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]); |
1803 | |
1804 | /* Switch MCLK, YCLK and SCLK PLLs to PCI source & force them ON */ |
1805 | tmp = rinfo->save_regs[2] & 0xff000000; |
1806 | tmp |= MCLK_CNTL__FORCE_MCLKA | |
1807 | MCLK_CNTL__FORCE_MCLKB | |
1808 | MCLK_CNTL__FORCE_YCLKA | |
1809 | MCLK_CNTL__FORCE_YCLKB | |
1810 | MCLK_CNTL__FORCE_MC; |
1811 | OUTPLL(pllMCLK_CNTL, tmp); |
1812 | |
1813 | /* Force all clocks on in SCLK */ |
1814 | tmp = INPLL(pllSCLK_CNTL); |
1815 | tmp |= SCLK_CNTL__FORCE_DISP2| |
1816 | SCLK_CNTL__FORCE_CP| |
1817 | SCLK_CNTL__FORCE_HDP| |
1818 | SCLK_CNTL__FORCE_DISP1| |
1819 | SCLK_CNTL__FORCE_TOP| |
1820 | SCLK_CNTL__FORCE_E2| |
1821 | SCLK_CNTL__FORCE_SE| |
1822 | SCLK_CNTL__FORCE_IDCT| |
1823 | SCLK_CNTL__FORCE_VIP| |
1824 | SCLK_CNTL__FORCE_PB| |
1825 | SCLK_CNTL__FORCE_TAM| |
1826 | SCLK_CNTL__FORCE_TDM| |
1827 | SCLK_CNTL__FORCE_RB| |
1828 | SCLK_CNTL__FORCE_TV_SCLK| |
1829 | SCLK_CNTL__FORCE_SUBPIC| |
1830 | SCLK_CNTL__FORCE_OV0; |
1831 | tmp |= SCLK_CNTL__CP_MAX_DYN_STOP_LAT | |
1832 | SCLK_CNTL__HDP_MAX_DYN_STOP_LAT | |
1833 | SCLK_CNTL__TV_MAX_DYN_STOP_LAT | |
1834 | SCLK_CNTL__E2_MAX_DYN_STOP_LAT | |
1835 | SCLK_CNTL__SE_MAX_DYN_STOP_LAT | |
1836 | SCLK_CNTL__IDCT_MAX_DYN_STOP_LAT| |
1837 | SCLK_CNTL__VIP_MAX_DYN_STOP_LAT | |
1838 | SCLK_CNTL__RE_MAX_DYN_STOP_LAT | |
1839 | SCLK_CNTL__PB_MAX_DYN_STOP_LAT | |
1840 | SCLK_CNTL__TAM_MAX_DYN_STOP_LAT | |
1841 | SCLK_CNTL__TDM_MAX_DYN_STOP_LAT | |
1842 | SCLK_CNTL__RB_MAX_DYN_STOP_LAT; |
1843 | OUTPLL(pllSCLK_CNTL, tmp); |
1844 | |
1845 | OUTPLL(pllVCLK_ECP_CNTL, 0); |
1846 | OUTPLL(pllPIXCLKS_CNTL, 0); |
1847 | OUTPLL(pllMCLK_MISC, |
1848 | MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT | |
1849 | MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT); |
1850 | |
1851 | mdelay(5); |
1852 | |
1853 | /* Restore the M_SPLL_REF_FB_DIV, MPLL_AUX_CNTL and SPLL_AUX_CNTL values */ |
1854 | OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]); |
1855 | OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]); |
1856 | OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]); |
1857 | |
1858 | /* Now restore the major PLLs settings, keeping them off & reset though */ |
1859 | OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3); |
1860 | OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3); |
1861 | OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03); |
1862 | OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03); |
1863 | |
1864 | /* Restore MC DLL state and switch it off/reset too */ |
1865 | OUTMC(rinfo, ixR300_MC_DLL_CNTL, value: rinfo->save_regs[70]); |
1866 | |
1867 | /* Switch MDLL off & reset */ |
1868 | OUTPLL(pllMDLL_RDCKA, rinfo->save_regs[98] | 0xff); |
1869 | mdelay(5); |
1870 | |
1871 | /* Setup some black magic bits in PLL_PWRMGT_CNTL. Hrm... we saved |
1872 | * 0xa1100007... and MacOS writes 0xa1000007 .. |
1873 | */ |
1874 | OUTPLL(pllPLL_PWRMGT_CNTL, rinfo->save_regs[0]); |
1875 | |
1876 | /* Restore more stuffs */ |
1877 | OUTPLL(pllHTOTAL_CNTL, 0); |
1878 | OUTPLL(pllHTOTAL2_CNTL, 0); |
1879 | |
1880 | /* More PLL initial configuration */ |
1881 | tmp = INPLL(pllSCLK_CNTL2); /* What for ? */ |
1882 | OUTPLL(pllSCLK_CNTL2, tmp); |
1883 | |
1884 | tmp = INPLL(pllSCLK_MORE_CNTL); |
1885 | tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS | /* a guess */ |
1886 | SCLK_MORE_CNTL__FORCE_MC_GUI | |
1887 | SCLK_MORE_CNTL__FORCE_MC_HOST; |
1888 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
1889 | |
1890 | /* Now we actually start MCLK and SCLK */ |
1891 | radeon_pm_start_mclk_sclk(rinfo); |
1892 | |
1893 | /* Full reset sdrams, this also re-inits the MDLL */ |
1894 | radeon_pm_full_reset_sdram(rinfo); |
1895 | |
1896 | /* Fill palettes */ |
1897 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20); |
1898 | for (i=0; i<256; i++) |
1899 | OUTREG(PALETTE_30_DATA, 0x15555555); |
1900 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20); |
1901 | udelay(20); |
1902 | for (i=0; i<256; i++) |
1903 | OUTREG(PALETTE_30_DATA, 0x15555555); |
1904 | |
1905 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20); |
1906 | mdelay(3); |
1907 | |
1908 | /* Restore TMDS */ |
1909 | OUTREG(FP_GEN_CNTL, rinfo->save_regs[82]); |
1910 | OUTREG(FP2_GEN_CNTL, rinfo->save_regs[83]); |
1911 | |
1912 | /* Set LVDS registers but keep interface & pll down */ |
1913 | OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] & |
1914 | ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN)); |
1915 | OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000); |
1916 | |
1917 | OUTREG(DISP_OUTPUT_CNTL, rinfo->save_regs[86]); |
1918 | |
1919 | /* Restore GPIOPAD state */ |
1920 | OUTREG(GPIOPAD_A, rinfo->save_regs[19]); |
1921 | OUTREG(GPIOPAD_EN, rinfo->save_regs[20]); |
1922 | OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]); |
1923 | |
1924 | /* write some stuff to the framebuffer... */ |
1925 | for (i = 0; i < 0x8000; ++i) |
1926 | writeb(val: 0, addr: rinfo->fb_base + i); |
1927 | |
1928 | mdelay(40); |
1929 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON); |
1930 | mdelay(40); |
1931 | |
1932 | /* Restore a few more things */ |
1933 | OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]); |
1934 | OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]); |
1935 | |
1936 | /* Take care of spread spectrum & PPLLs now */ |
1937 | radeon_pm_m10_disable_spread_spectrum(rinfo); |
1938 | radeon_pm_restore_pixel_pll(rinfo); |
1939 | |
1940 | /* GRRRR... I can't figure out the proper LVDS power sequence, and the |
1941 | * code I have for blank/unblank doesn't quite work on some laptop models |
1942 | * it seems ... Hrm. What I have here works most of the time ... |
1943 | */ |
1944 | radeon_pm_m10_enable_lvds_spread_spectrum(rinfo); |
1945 | } |
1946 | #endif |
1947 | |
1948 | #ifdef CONFIG_PPC |
1949 | #ifdef CONFIG_PPC_PMAC |
1950 | static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo) |
1951 | { |
1952 | OUTREG(MC_CNTL, rinfo->save_regs[46]); |
1953 | OUTREG(MC_INIT_GFX_LAT_TIMER, rinfo->save_regs[47]); |
1954 | OUTREG(MC_INIT_MISC_LAT_TIMER, rinfo->save_regs[48]); |
1955 | OUTREG(MEM_SDRAM_MODE_REG, |
1956 | rinfo->save_regs[35] & ~MEM_SDRAM_MODE_REG__MC_INIT_COMPLETE); |
1957 | OUTREG(MC_TIMING_CNTL, rinfo->save_regs[49]); |
1958 | OUTREG(MC_READ_CNTL_AB, rinfo->save_regs[50]); |
1959 | OUTREG(MEM_REFRESH_CNTL, rinfo->save_regs[42]); |
1960 | OUTREG(MC_IOPAD_CNTL, rinfo->save_regs[51]); |
1961 | OUTREG(MC_DEBUG, rinfo->save_regs[53]); |
1962 | OUTREG(MC_CHIP_IO_OE_CNTL_AB, rinfo->save_regs[52]); |
1963 | |
1964 | OUTMC(rinfo, ixMC_IMP_CNTL, rinfo->save_regs[59] /*0x00f460d6*/); |
1965 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, rinfo->save_regs[65] /*0xfecfa666*/); |
1966 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, rinfo->save_regs[66] /*0x141555ff*/); |
1967 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, rinfo->save_regs[67] /*0xfecfa666*/); |
1968 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/); |
1969 | OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/); |
1970 | OUTREG(MC_IND_INDEX, 0); |
1971 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
1972 | |
1973 | mdelay(20); |
1974 | } |
1975 | |
1976 | static void radeon_reinitialize_M9P(struct radeonfb_info *rinfo) |
1977 | { |
1978 | u32 tmp, i; |
1979 | |
1980 | /* Restore a bunch of registers first */ |
1981 | OUTREG(SURFACE_CNTL, rinfo->save_regs[29]); |
1982 | OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); |
1983 | OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); |
1984 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); |
1985 | OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); |
1986 | OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]); |
1987 | OUTREG(BUS_CNTL, rinfo->save_regs[36]); |
1988 | OUTREG(BUS_CNTL1, rinfo->save_regs[14]); |
1989 | OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]); |
1990 | OUTREG(FCP_CNTL, rinfo->save_regs[38]); |
1991 | OUTREG(RBBM_CNTL, rinfo->save_regs[39]); |
1992 | |
1993 | OUTREG(DAC_CNTL, rinfo->save_regs[40]); |
1994 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | DAC2_EXPAND_MODE); |
1995 | |
1996 | /* Reset the PAD CTLR */ |
1997 | radeon_pm_reset_pad_ctlr_strength(rinfo); |
1998 | |
1999 | /* Some PLLs are Read & written identically in the trace here... |
2000 | * I suppose it's actually to switch them all off & reset, |
2001 | * let's assume off is what we want. I'm just doing that for all major PLLs now. |
2002 | */ |
2003 | radeon_pm_all_ppls_off(rinfo); |
2004 | |
2005 | /* Clear tiling, reset swappers */ |
2006 | INREG(SURFACE_CNTL); |
2007 | OUTREG(SURFACE_CNTL, 0); |
2008 | |
2009 | /* Some black magic with TV_DAC_CNTL, we should restore those from backups |
2010 | * rather than hard coding... |
2011 | */ |
2012 | tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_BGADJ_MASK; |
2013 | tmp |= 6 << TV_DAC_CNTL_BGADJ__SHIFT; |
2014 | OUTREG(TV_DAC_CNTL, tmp); |
2015 | |
2016 | tmp = INREG(TV_DAC_CNTL) & ~TV_DAC_CNTL_DACADJ_MASK; |
2017 | tmp |= 6 << TV_DAC_CNTL_DACADJ__SHIFT; |
2018 | OUTREG(TV_DAC_CNTL, tmp); |
2019 | |
2020 | OUTPLL(pllAGP_PLL_CNTL, rinfo->save_regs[78]); |
2021 | |
2022 | OUTREG(PAMAC0_DLY_CNTL, rinfo->save_regs[54]); |
2023 | OUTREG(PAMAC1_DLY_CNTL, rinfo->save_regs[55]); |
2024 | OUTREG(PAMAC2_DLY_CNTL, rinfo->save_regs[79]); |
2025 | |
2026 | OUTREG(AGP_CNTL, rinfo->save_regs[16]); |
2027 | OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]); /* MacOS sets that to 0 !!! */ |
2028 | OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); |
2029 | |
2030 | tmp = rinfo->save_regs[1] |
2031 | & ~(CLK_PWRMGT_CNTL__ACTIVE_HILO_LAT_MASK | |
2032 | CLK_PWRMGT_CNTL__MC_BUSY); |
2033 | OUTPLL(pllCLK_PWRMGT_CNTL, tmp); |
2034 | |
2035 | OUTREG(FW_CNTL, rinfo->save_regs[57]); |
2036 | |
2037 | /* Disable SDRAM refresh */ |
2038 | OUTREG(MEM_REFRESH_CNTL, INREG(MEM_REFRESH_CNTL) |
2039 | | MEM_REFRESH_CNTL__MEM_REFRESH_DIS); |
2040 | |
2041 | /* Restore XTALIN routing (CLK_PIN_CNTL) */ |
2042 | OUTPLL(pllCLK_PIN_CNTL, rinfo->save_regs[4]); |
2043 | |
2044 | /* Force MCLK to be PCI sourced and forced ON */ |
2045 | tmp = rinfo->save_regs[2] & 0xff000000; |
2046 | tmp |= MCLK_CNTL__FORCE_MCLKA | |
2047 | MCLK_CNTL__FORCE_MCLKB | |
2048 | MCLK_CNTL__FORCE_YCLKA | |
2049 | MCLK_CNTL__FORCE_YCLKB | |
2050 | MCLK_CNTL__FORCE_MC | |
2051 | MCLK_CNTL__FORCE_AIC; |
2052 | OUTPLL(pllMCLK_CNTL, tmp); |
2053 | |
2054 | /* Force SCLK to be PCI sourced with a bunch forced */ |
2055 | tmp = 0 | |
2056 | SCLK_CNTL__FORCE_DISP2| |
2057 | SCLK_CNTL__FORCE_CP| |
2058 | SCLK_CNTL__FORCE_HDP| |
2059 | SCLK_CNTL__FORCE_DISP1| |
2060 | SCLK_CNTL__FORCE_TOP| |
2061 | SCLK_CNTL__FORCE_E2| |
2062 | SCLK_CNTL__FORCE_SE| |
2063 | SCLK_CNTL__FORCE_IDCT| |
2064 | SCLK_CNTL__FORCE_VIP| |
2065 | SCLK_CNTL__FORCE_RE| |
2066 | SCLK_CNTL__FORCE_PB| |
2067 | SCLK_CNTL__FORCE_TAM| |
2068 | SCLK_CNTL__FORCE_TDM| |
2069 | SCLK_CNTL__FORCE_RB; |
2070 | OUTPLL(pllSCLK_CNTL, tmp); |
2071 | |
2072 | /* Clear VCLK_ECP_CNTL & PIXCLKS_CNTL */ |
2073 | OUTPLL(pllVCLK_ECP_CNTL, 0); |
2074 | OUTPLL(pllPIXCLKS_CNTL, 0); |
2075 | |
2076 | /* Setup MCLK_MISC, non dynamic mode */ |
2077 | OUTPLL(pllMCLK_MISC, |
2078 | MCLK_MISC__MC_MCLK_MAX_DYN_STOP_LAT | |
2079 | MCLK_MISC__IO_MCLK_MAX_DYN_STOP_LAT); |
2080 | |
2081 | mdelay(5); |
2082 | |
2083 | /* Set back the default clock dividers */ |
2084 | OUTPLL(pllM_SPLL_REF_FB_DIV, rinfo->save_regs[77]); |
2085 | OUTPLL(pllMPLL_AUX_CNTL, rinfo->save_regs[75]); |
2086 | OUTPLL(pllSPLL_AUX_CNTL, rinfo->save_regs[76]); |
2087 | |
2088 | /* PPLL and P2PLL default values & off */ |
2089 | OUTPLL(pllPPLL_CNTL, rinfo->save_regs[93] | 0x3); |
2090 | OUTPLL(pllP2PLL_CNTL, rinfo->save_regs[8] | 0x3); |
2091 | |
2092 | /* S and M PLLs are reset & off, configure them */ |
2093 | OUTPLL(pllMPLL_CNTL, rinfo->save_regs[73] | 0x03); |
2094 | OUTPLL(pllSPLL_CNTL, rinfo->save_regs[74] | 0x03); |
2095 | |
2096 | /* Default values for MDLL ... fixme */ |
2097 | OUTPLL(pllMDLL_CKO, 0x9c009c); |
2098 | OUTPLL(pllMDLL_RDCKA, 0x08830883); |
2099 | OUTPLL(pllMDLL_RDCKB, 0x08830883); |
2100 | mdelay(5); |
2101 | |
2102 | /* Restore PLL_PWRMGT_CNTL */ // XXXX |
2103 | tmp = rinfo->save_regs[0]; |
2104 | tmp &= ~PLL_PWRMGT_CNTL_SU_SCLK_USE_BCLK; |
2105 | tmp |= PLL_PWRMGT_CNTL_SU_MCLK_USE_BCLK; |
2106 | OUTPLL(PLL_PWRMGT_CNTL, tmp); |
2107 | |
2108 | /* Clear HTOTAL_CNTL & HTOTAL2_CNTL */ |
2109 | OUTPLL(pllHTOTAL_CNTL, 0); |
2110 | OUTPLL(pllHTOTAL2_CNTL, 0); |
2111 | |
2112 | /* All outputs off */ |
2113 | OUTREG(CRTC_GEN_CNTL, 0x04000000); |
2114 | OUTREG(CRTC2_GEN_CNTL, 0x04000000); |
2115 | OUTREG(FP_GEN_CNTL, 0x00004008); |
2116 | OUTREG(FP2_GEN_CNTL, 0x00000008); |
2117 | OUTREG(LVDS_GEN_CNTL, 0x08000008); |
2118 | |
2119 | /* Restore Memory Controller configuration */ |
2120 | radeon_pm_m9p_reconfigure_mc(rinfo); |
2121 | |
2122 | /* Now we actually start MCLK and SCLK */ |
2123 | radeon_pm_start_mclk_sclk(rinfo); |
2124 | |
2125 | /* Full reset sdrams, this also re-inits the MDLL */ |
2126 | radeon_pm_full_reset_sdram(rinfo); |
2127 | |
2128 | /* Fill palettes */ |
2129 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x20); |
2130 | for (i=0; i<256; i++) |
2131 | OUTREG(PALETTE_30_DATA, 0x15555555); |
2132 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~20); |
2133 | udelay(20); |
2134 | for (i=0; i<256; i++) |
2135 | OUTREG(PALETTE_30_DATA, 0x15555555); |
2136 | |
2137 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) & ~0x20); |
2138 | mdelay(3); |
2139 | |
2140 | /* Restore TV stuff, make sure TV DAC is down */ |
2141 | OUTREG(TV_MASTER_CNTL, rinfo->save_regs[88]); |
2142 | OUTREG(TV_DAC_CNTL, rinfo->save_regs[13] | 0x07000000); |
2143 | |
2144 | /* Restore GPIOS. MacOS does some magic here with one of the GPIO bits, |
2145 | * possibly related to the weird PLL related workarounds and to the |
2146 | * fact that CLK_PIN_CNTL is tweaked in ways I don't fully understand, |
2147 | * but we keep things the simple way here |
2148 | */ |
2149 | OUTREG(GPIOPAD_A, rinfo->save_regs[19]); |
2150 | OUTREG(GPIOPAD_EN, rinfo->save_regs[20]); |
2151 | OUTREG(GPIOPAD_MASK, rinfo->save_regs[21]); |
2152 | |
2153 | /* Now do things with SCLK_MORE_CNTL. Force bits are already set, copy |
2154 | * high bits from backup |
2155 | */ |
2156 | tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff; |
2157 | tmp |= rinfo->save_regs[34] & 0xffff0000; |
2158 | tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS; |
2159 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
2160 | |
2161 | tmp = INPLL(pllSCLK_MORE_CNTL) & 0x0000ffff; |
2162 | tmp |= rinfo->save_regs[34] & 0xffff0000; |
2163 | tmp |= SCLK_MORE_CNTL__FORCE_DISPREGS; |
2164 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
2165 | |
2166 | OUTREG(LVDS_GEN_CNTL, rinfo->save_regs[11] & |
2167 | ~(LVDS_EN | LVDS_ON | LVDS_DIGON | LVDS_BLON | LVDS_BL_MOD_EN)); |
2168 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_BLON); |
2169 | OUTREG(LVDS_PLL_CNTL, (rinfo->save_regs[12] & ~0xf0000) | 0x20000); |
2170 | mdelay(20); |
2171 | |
2172 | /* write some stuff to the framebuffer... */ |
2173 | for (i = 0; i < 0x8000; ++i) |
2174 | writeb(0, rinfo->fb_base + i); |
2175 | |
2176 | OUTREG(0x2ec, 0x6332a020); |
2177 | OUTPLL(pllSSPLL_REF_DIV, rinfo->save_regs[44] /*0x3f */); |
2178 | OUTPLL(pllSSPLL_DIV_0, rinfo->save_regs[45] /*0x000081bb */); |
2179 | tmp = INPLL(pllSSPLL_CNTL); |
2180 | tmp &= ~2; |
2181 | OUTPLL(pllSSPLL_CNTL, tmp); |
2182 | mdelay(6); |
2183 | tmp &= ~1; |
2184 | OUTPLL(pllSSPLL_CNTL, tmp); |
2185 | mdelay(5); |
2186 | tmp |= 3; |
2187 | OUTPLL(pllSSPLL_CNTL, tmp); |
2188 | mdelay(5); |
2189 | |
2190 | OUTPLL(pllSS_INT_CNTL, rinfo->save_regs[90] & ~3);/*0x0020300c*/ |
2191 | OUTREG(0x2ec, 0x6332a3f0); |
2192 | mdelay(17); |
2193 | |
2194 | OUTPLL(pllPPLL_REF_DIV, rinfo->pll.ref_div); |
2195 | OUTPLL(pllPPLL_DIV_0, rinfo->save_regs[92]); |
2196 | |
2197 | mdelay(40); |
2198 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) | LVDS_DIGON | LVDS_ON); |
2199 | mdelay(40); |
2200 | |
2201 | /* Restore a few more things */ |
2202 | OUTREG(GRPH_BUFFER_CNTL, rinfo->save_regs[94]); |
2203 | OUTREG(GRPH2_BUFFER_CNTL, rinfo->save_regs[95]); |
2204 | |
2205 | /* Restore PPLL, spread spectrum & LVDS */ |
2206 | radeon_pm_m10_disable_spread_spectrum(rinfo); |
2207 | radeon_pm_restore_pixel_pll(rinfo); |
2208 | radeon_pm_m10_enable_lvds_spread_spectrum(rinfo); |
2209 | } |
2210 | #endif |
2211 | |
2212 | #if 0 /* Not ready yet */ |
2213 | static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) |
2214 | { |
2215 | int i; |
2216 | u32 tmp, tmp2; |
2217 | u32 cko, cka, ckb; |
2218 | u32 cgc, cec, c2gc; |
2219 | |
2220 | OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); |
2221 | OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); |
2222 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); |
2223 | OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); |
2224 | OUTREG(BUS_CNTL, rinfo->save_regs[36]); |
2225 | OUTREG(RBBM_CNTL, rinfo->save_regs[39]); |
2226 | |
2227 | INREG(PAD_CTLR_STRENGTH); |
2228 | OUTREG(PAD_CTLR_STRENGTH, INREG(PAD_CTLR_STRENGTH) & ~0x10000); |
2229 | for (i = 0; i < 65; ++i) { |
2230 | mdelay(1); |
2231 | INREG(PAD_CTLR_STRENGTH); |
2232 | } |
2233 | |
2234 | OUTREG(DISP_TEST_DEBUG_CNTL, INREG(DISP_TEST_DEBUG_CNTL) | 0x10000000); |
2235 | OUTREG(OV0_FLAG_CNTRL, INREG(OV0_FLAG_CNTRL) | 0x100); |
2236 | OUTREG(CRTC_GEN_CNTL, INREG(CRTC_GEN_CNTL)); |
2237 | OUTREG(DAC_CNTL, 0xff00410a); |
2238 | OUTREG(CRTC2_GEN_CNTL, INREG(CRTC2_GEN_CNTL)); |
2239 | OUTREG(DAC_CNTL2, INREG(DAC_CNTL2) | 0x4000); |
2240 | |
2241 | OUTREG(SURFACE_CNTL, rinfo->save_regs[29]); |
2242 | OUTREG(AGP_CNTL, rinfo->save_regs[16]); |
2243 | OUTREG(HOST_PATH_CNTL, rinfo->save_regs[41]); |
2244 | OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); |
2245 | |
2246 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_A0, 0xf7bb4433); |
2247 | OUTREG(MC_IND_INDEX, 0); |
2248 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_B0, 0xf7bb4433); |
2249 | OUTREG(MC_IND_INDEX, 0); |
2250 | |
2251 | OUTREG(CRTC_MORE_CNTL, INREG(CRTC_MORE_CNTL)); |
2252 | |
2253 | tmp = INPLL(pllVCLK_ECP_CNTL); |
2254 | OUTPLL(pllVCLK_ECP_CNTL, tmp); |
2255 | tmp = INPLL(pllPIXCLKS_CNTL); |
2256 | OUTPLL(pllPIXCLKS_CNTL, tmp); |
2257 | |
2258 | OUTPLL(MCLK_CNTL, 0xaa3f0000); |
2259 | OUTPLL(SCLK_CNTL, 0xffff0000); |
2260 | OUTPLL(pllMPLL_AUX_CNTL, 6); |
2261 | OUTPLL(pllSPLL_AUX_CNTL, 1); |
2262 | OUTPLL(MDLL_CKO, 0x9f009f); |
2263 | OUTPLL(MDLL_RDCKA, 0x830083); |
2264 | OUTPLL(pllMDLL_RDCKB, 0x830083); |
2265 | OUTPLL(PPLL_CNTL, 0xa433); |
2266 | OUTPLL(P2PLL_CNTL, 0xa433); |
2267 | OUTPLL(MPLL_CNTL, 0x0400a403); |
2268 | OUTPLL(SPLL_CNTL, 0x0400a433); |
2269 | |
2270 | tmp = INPLL(M_SPLL_REF_FB_DIV); |
2271 | OUTPLL(M_SPLL_REF_FB_DIV, tmp); |
2272 | tmp = INPLL(M_SPLL_REF_FB_DIV); |
2273 | OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0xc); |
2274 | INPLL(M_SPLL_REF_FB_DIV); |
2275 | |
2276 | tmp = INPLL(MPLL_CNTL); |
2277 | OUTREG8(CLOCK_CNTL_INDEX, MPLL_CNTL + PLL_WR_EN); |
2278 | radeon_pll_errata_after_index(rinfo); |
2279 | OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); |
2280 | radeon_pll_errata_after_data(rinfo); |
2281 | |
2282 | tmp = INPLL(M_SPLL_REF_FB_DIV); |
2283 | OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x5900); |
2284 | |
2285 | tmp = INPLL(MPLL_CNTL); |
2286 | OUTPLL(MPLL_CNTL, tmp & ~0x2); |
2287 | mdelay(1); |
2288 | tmp = INPLL(MPLL_CNTL); |
2289 | OUTPLL(MPLL_CNTL, tmp & ~0x1); |
2290 | mdelay(10); |
2291 | |
2292 | OUTPLL(MCLK_CNTL, 0xaa3f1212); |
2293 | mdelay(1); |
2294 | |
2295 | INPLL(M_SPLL_REF_FB_DIV); |
2296 | INPLL(MCLK_CNTL); |
2297 | INPLL(M_SPLL_REF_FB_DIV); |
2298 | |
2299 | tmp = INPLL(SPLL_CNTL); |
2300 | OUTREG8(CLOCK_CNTL_INDEX, SPLL_CNTL + PLL_WR_EN); |
2301 | radeon_pll_errata_after_index(rinfo); |
2302 | OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff); |
2303 | radeon_pll_errata_after_data(rinfo); |
2304 | |
2305 | tmp = INPLL(M_SPLL_REF_FB_DIV); |
2306 | OUTPLL(M_SPLL_REF_FB_DIV, tmp | 0x780000); |
2307 | |
2308 | tmp = INPLL(SPLL_CNTL); |
2309 | OUTPLL(SPLL_CNTL, tmp & ~0x1); |
2310 | mdelay(1); |
2311 | tmp = INPLL(SPLL_CNTL); |
2312 | OUTPLL(SPLL_CNTL, tmp & ~0x2); |
2313 | mdelay(10); |
2314 | |
2315 | tmp = INPLL(SCLK_CNTL); |
2316 | OUTPLL(SCLK_CNTL, tmp | 2); |
2317 | mdelay(1); |
2318 | |
2319 | cko = INPLL(pllMDLL_CKO); |
2320 | cka = INPLL(pllMDLL_RDCKA); |
2321 | ckb = INPLL(pllMDLL_RDCKB); |
2322 | |
2323 | cko &= ~(MDLL_CKO__MCKOA_SLEEP | MDLL_CKO__MCKOB_SLEEP); |
2324 | OUTPLL(pllMDLL_CKO, cko); |
2325 | mdelay(1); |
2326 | cko &= ~(MDLL_CKO__MCKOA_RESET | MDLL_CKO__MCKOB_RESET); |
2327 | OUTPLL(pllMDLL_CKO, cko); |
2328 | mdelay(5); |
2329 | |
2330 | cka &= ~(MDLL_RDCKA__MRDCKA0_SLEEP | MDLL_RDCKA__MRDCKA1_SLEEP); |
2331 | OUTPLL(pllMDLL_RDCKA, cka); |
2332 | mdelay(1); |
2333 | cka &= ~(MDLL_RDCKA__MRDCKA0_RESET | MDLL_RDCKA__MRDCKA1_RESET); |
2334 | OUTPLL(pllMDLL_RDCKA, cka); |
2335 | mdelay(5); |
2336 | |
2337 | ckb &= ~(MDLL_RDCKB__MRDCKB0_SLEEP | MDLL_RDCKB__MRDCKB1_SLEEP); |
2338 | OUTPLL(pllMDLL_RDCKB, ckb); |
2339 | mdelay(1); |
2340 | ckb &= ~(MDLL_RDCKB__MRDCKB0_RESET | MDLL_RDCKB__MRDCKB1_RESET); |
2341 | OUTPLL(pllMDLL_RDCKB, ckb); |
2342 | mdelay(5); |
2343 | |
2344 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x151550ff); |
2345 | OUTREG(MC_IND_INDEX, 0); |
2346 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x151550ff); |
2347 | OUTREG(MC_IND_INDEX, 0); |
2348 | mdelay(1); |
2349 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_A1, 0x141550ff); |
2350 | OUTREG(MC_IND_INDEX, 0); |
2351 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, 0x141550ff); |
2352 | OUTREG(MC_IND_INDEX, 0); |
2353 | mdelay(1); |
2354 | |
2355 | OUTPLL(pllHTOTAL_CNTL, 0); |
2356 | OUTPLL(pllHTOTAL2_CNTL, 0); |
2357 | |
2358 | OUTREG(MEM_CNTL, 0x29002901); |
2359 | OUTREG(MEM_SDRAM_MODE_REG, 0x45320032); /* XXX use save_regs[35]? */ |
2360 | OUTREG(EXT_MEM_CNTL, 0x1a394333); |
2361 | OUTREG(MEM_IO_CNTL_A1, 0x0aac0aac); |
2362 | OUTREG(MEM_INIT_LATENCY_TIMER, 0x34444444); |
2363 | OUTREG(MEM_REFRESH_CNTL, 0x1f1f7218); /* XXX or save_regs[42]? */ |
2364 | OUTREG(MC_DEBUG, 0); |
2365 | OUTREG(MEM_IO_OE_CNTL, 0x04300430); |
2366 | |
2367 | OUTMC(rinfo, ixMC_IMP_CNTL, 0x00f460d6); |
2368 | OUTREG(MC_IND_INDEX, 0); |
2369 | OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249); |
2370 | OUTREG(MC_IND_INDEX, 0); |
2371 | |
2372 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
2373 | |
2374 | radeon_pm_full_reset_sdram(rinfo); |
2375 | |
2376 | INREG(FP_GEN_CNTL); |
2377 | OUTREG(TMDS_CNTL, 0x01000000); /* XXX ? */ |
2378 | tmp = INREG(FP_GEN_CNTL); |
2379 | tmp |= FP_CRTC_DONT_SHADOW_HEND | FP_CRTC_DONT_SHADOW_VPAR | 0x200; |
2380 | OUTREG(FP_GEN_CNTL, tmp); |
2381 | |
2382 | tmp = INREG(DISP_OUTPUT_CNTL); |
2383 | tmp &= ~0x400; |
2384 | OUTREG(DISP_OUTPUT_CNTL, tmp); |
2385 | |
2386 | OUTPLL(CLK_PIN_CNTL, rinfo->save_regs[4]); |
2387 | OUTPLL(CLK_PWRMGT_CNTL, rinfo->save_regs[1]); |
2388 | OUTPLL(PLL_PWRMGT_CNTL, rinfo->save_regs[0]); |
2389 | |
2390 | tmp = INPLL(MCLK_MISC); |
2391 | tmp |= MCLK_MISC__MC_MCLK_DYN_ENABLE | MCLK_MISC__IO_MCLK_DYN_ENABLE; |
2392 | OUTPLL(MCLK_MISC, tmp); |
2393 | |
2394 | tmp = INPLL(SCLK_CNTL); |
2395 | OUTPLL(SCLK_CNTL, tmp); |
2396 | |
2397 | OUTREG(CRTC_MORE_CNTL, 0); |
2398 | OUTREG8(CRTC_GEN_CNTL+1, 6); |
2399 | OUTREG8(CRTC_GEN_CNTL+3, 1); |
2400 | OUTREG(CRTC_PITCH, 32); |
2401 | |
2402 | tmp = INPLL(VCLK_ECP_CNTL); |
2403 | OUTPLL(VCLK_ECP_CNTL, tmp); |
2404 | |
2405 | tmp = INPLL(PPLL_CNTL); |
2406 | OUTPLL(PPLL_CNTL, tmp); |
2407 | |
2408 | /* palette stuff and BIOS_1_SCRATCH... */ |
2409 | |
2410 | tmp = INREG(FP_GEN_CNTL); |
2411 | tmp2 = INREG(TMDS_TRANSMITTER_CNTL); |
2412 | tmp |= 2; |
2413 | OUTREG(FP_GEN_CNTL, tmp); |
2414 | mdelay(5); |
2415 | OUTREG(FP_GEN_CNTL, tmp); |
2416 | mdelay(5); |
2417 | OUTREG(TMDS_TRANSMITTER_CNTL, tmp2); |
2418 | OUTREG(CRTC_MORE_CNTL, 0); |
2419 | mdelay(20); |
2420 | |
2421 | tmp = INREG(CRTC_MORE_CNTL); |
2422 | OUTREG(CRTC_MORE_CNTL, tmp); |
2423 | |
2424 | cgc = INREG(CRTC_GEN_CNTL); |
2425 | cec = INREG(CRTC_EXT_CNTL); |
2426 | c2gc = INREG(CRTC2_GEN_CNTL); |
2427 | |
2428 | OUTREG(CRTC_H_SYNC_STRT_WID, 0x008e0580); |
2429 | OUTREG(CRTC_H_TOTAL_DISP, 0x009f00d2); |
2430 | OUTREG8(CLOCK_CNTL_INDEX, HTOTAL_CNTL + PLL_WR_EN); |
2431 | radeon_pll_errata_after_index(rinfo); |
2432 | OUTREG8(CLOCK_CNTL_DATA, 0); |
2433 | radeon_pll_errata_after_data(rinfo); |
2434 | OUTREG(CRTC_V_SYNC_STRT_WID, 0x00830403); |
2435 | OUTREG(CRTC_V_TOTAL_DISP, 0x03ff0429); |
2436 | OUTREG(FP_CRTC_H_TOTAL_DISP, 0x009f0033); |
2437 | OUTREG(FP_H_SYNC_STRT_WID, 0x008e0080); |
2438 | OUTREG(CRT_CRTC_H_SYNC_STRT_WID, 0x008e0080); |
2439 | OUTREG(FP_CRTC_V_TOTAL_DISP, 0x03ff002a); |
2440 | OUTREG(FP_V_SYNC_STRT_WID, 0x00830004); |
2441 | OUTREG(CRT_CRTC_V_SYNC_STRT_WID, 0x00830004); |
2442 | OUTREG(FP_HORZ_VERT_ACTIVE, 0x009f03ff); |
2443 | OUTREG(FP_HORZ_STRETCH, 0); |
2444 | OUTREG(FP_VERT_STRETCH, 0); |
2445 | OUTREG(OVR_CLR, 0); |
2446 | OUTREG(OVR_WID_LEFT_RIGHT, 0); |
2447 | OUTREG(OVR_WID_TOP_BOTTOM, 0); |
2448 | |
2449 | tmp = INPLL(PPLL_REF_DIV); |
2450 | tmp = (tmp & ~PPLL_REF_DIV_MASK) | rinfo->pll.ref_div; |
2451 | OUTPLL(PPLL_REF_DIV, tmp); |
2452 | INPLL(PPLL_REF_DIV); |
2453 | |
2454 | OUTREG8(CLOCK_CNTL_INDEX, PPLL_CNTL + PLL_WR_EN); |
2455 | radeon_pll_errata_after_index(rinfo); |
2456 | OUTREG8(CLOCK_CNTL_DATA + 1, 0xbc); |
2457 | radeon_pll_errata_after_data(rinfo); |
2458 | |
2459 | tmp = INREG(CLOCK_CNTL_INDEX); |
2460 | radeon_pll_errata_after_index(rinfo); |
2461 | OUTREG(CLOCK_CNTL_INDEX, tmp & 0xff); |
2462 | radeon_pll_errata_after_index(rinfo); |
2463 | radeon_pll_errata_after_data(rinfo); |
2464 | |
2465 | OUTPLL(PPLL_DIV_0, 0x48090); |
2466 | |
2467 | tmp = INPLL(PPLL_CNTL); |
2468 | OUTPLL(PPLL_CNTL, tmp & ~0x2); |
2469 | mdelay(1); |
2470 | tmp = INPLL(PPLL_CNTL); |
2471 | OUTPLL(PPLL_CNTL, tmp & ~0x1); |
2472 | mdelay(10); |
2473 | |
2474 | tmp = INPLL(VCLK_ECP_CNTL); |
2475 | OUTPLL(VCLK_ECP_CNTL, tmp | 3); |
2476 | mdelay(1); |
2477 | |
2478 | tmp = INPLL(VCLK_ECP_CNTL); |
2479 | OUTPLL(VCLK_ECP_CNTL, tmp); |
2480 | |
2481 | c2gc |= CRTC2_DISP_REQ_EN_B; |
2482 | OUTREG(CRTC2_GEN_CNTL, c2gc); |
2483 | cgc |= CRTC_EN; |
2484 | OUTREG(CRTC_GEN_CNTL, cgc); |
2485 | OUTREG(CRTC_EXT_CNTL, cec); |
2486 | OUTREG(CRTC_PITCH, 0xa0); |
2487 | OUTREG(CRTC_OFFSET, 0); |
2488 | OUTREG(CRTC_OFFSET_CNTL, 0); |
2489 | |
2490 | OUTREG(GRPH_BUFFER_CNTL, 0x20117c7c); |
2491 | OUTREG(GRPH2_BUFFER_CNTL, 0x00205c5c); |
2492 | |
2493 | tmp2 = INREG(FP_GEN_CNTL); |
2494 | tmp = INREG(TMDS_TRANSMITTER_CNTL); |
2495 | OUTREG(0x2a8, 0x0000061b); |
2496 | tmp |= TMDS_PLL_EN; |
2497 | OUTREG(TMDS_TRANSMITTER_CNTL, tmp); |
2498 | mdelay(1); |
2499 | tmp &= ~TMDS_PLLRST; |
2500 | OUTREG(TMDS_TRANSMITTER_CNTL, tmp); |
2501 | tmp2 &= ~2; |
2502 | tmp2 |= FP_TMDS_EN; |
2503 | OUTREG(FP_GEN_CNTL, tmp2); |
2504 | mdelay(5); |
2505 | tmp2 |= FP_FPON; |
2506 | OUTREG(FP_GEN_CNTL, tmp2); |
2507 | |
2508 | OUTREG(CUR_HORZ_VERT_OFF, CUR_LOCK | 1); |
2509 | cgc = INREG(CRTC_GEN_CNTL); |
2510 | OUTREG(CUR_HORZ_VERT_POSN, 0xbfff0fff); |
2511 | cgc |= 0x10000; |
2512 | OUTREG(CUR_OFFSET, 0); |
2513 | } |
2514 | #endif /* 0 */ |
2515 | |
2516 | #endif /* CONFIG_PPC */ |
2517 | |
2518 | static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state) |
2519 | { |
2520 | u16 pwr_cmd; |
2521 | |
2522 | for (;;) { |
2523 | pci_read_config_word(dev: rinfo->pdev, |
2524 | where: rinfo->pdev->pm_cap + PCI_PM_CTRL, |
2525 | val: &pwr_cmd); |
2526 | if (pwr_cmd & state) |
2527 | break; |
2528 | pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | state; |
2529 | pci_write_config_word(dev: rinfo->pdev, |
2530 | where: rinfo->pdev->pm_cap + PCI_PM_CTRL, |
2531 | val: pwr_cmd); |
2532 | msleep(msecs: 500); |
2533 | } |
2534 | rinfo->pdev->current_state = state; |
2535 | } |
2536 | |
2537 | static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) |
2538 | { |
2539 | u32 tmp; |
2540 | |
2541 | if (!rinfo->pdev->pm_cap) |
2542 | return; |
2543 | |
2544 | /* Set the chip into appropriate suspend mode (we use D2, |
2545 | * D3 would require a compete re-initialization of the chip, |
2546 | * including PCI config registers, clocks, AGP conf, ...) |
2547 | */ |
2548 | if (suspend) { |
2549 | printk(KERN_DEBUG "radeonfb (%s): switching to D2 state...\n" , |
2550 | pci_name(rinfo->pdev)); |
2551 | |
2552 | /* Disable dynamic power management of clocks for the |
2553 | * duration of the suspend/resume process |
2554 | */ |
2555 | radeon_pm_disable_dynamic_mode(rinfo); |
2556 | |
2557 | /* Save some registers */ |
2558 | radeon_pm_save_regs(rinfo, saving_for_d3: 0); |
2559 | |
2560 | /* Prepare mobility chips for suspend. |
2561 | */ |
2562 | if (rinfo->is_mobility) { |
2563 | /* Program V2CLK */ |
2564 | radeon_pm_program_v2clk(rinfo); |
2565 | |
2566 | /* Disable IO PADs */ |
2567 | radeon_pm_disable_iopad(rinfo); |
2568 | |
2569 | /* Set low current */ |
2570 | radeon_pm_low_current(rinfo); |
2571 | |
2572 | /* Prepare chip for power management */ |
2573 | radeon_pm_setup_for_suspend(rinfo); |
2574 | |
2575 | if (rinfo->family <= CHIP_FAMILY_RV280) { |
2576 | /* Reset the MDLL */ |
2577 | /* because both INPLL and OUTPLL take the same |
2578 | * lock, that's why. */ |
2579 | tmp = INPLL( pllMDLL_CKO) | MDLL_CKO__MCKOA_RESET |
2580 | | MDLL_CKO__MCKOB_RESET; |
2581 | OUTPLL( pllMDLL_CKO, tmp ); |
2582 | } |
2583 | } |
2584 | |
2585 | /* Switch PCI power management to D2. */ |
2586 | pci_disable_device(dev: rinfo->pdev); |
2587 | pci_save_state(dev: rinfo->pdev); |
2588 | /* The chip seems to need us to whack the PM register |
2589 | * repeatedly until it sticks. We do that -prior- to |
2590 | * calling pci_set_power_state() |
2591 | */ |
2592 | radeonfb_whack_power_state(rinfo, PCI_D2); |
2593 | pci_platform_power_transition(dev: rinfo->pdev, PCI_D2); |
2594 | } else { |
2595 | printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n" , |
2596 | pci_name(rinfo->pdev)); |
2597 | |
2598 | if (rinfo->family <= CHIP_FAMILY_RV250) { |
2599 | /* Reset the SDRAM controller */ |
2600 | radeon_pm_full_reset_sdram(rinfo); |
2601 | |
2602 | /* Restore some registers */ |
2603 | radeon_pm_restore_regs(rinfo); |
2604 | } else { |
2605 | /* Restore registers first */ |
2606 | radeon_pm_restore_regs(rinfo); |
2607 | /* init sdram controller */ |
2608 | radeon_pm_full_reset_sdram(rinfo); |
2609 | } |
2610 | } |
2611 | } |
2612 | |
2613 | static int radeonfb_pci_suspend_late(struct device *dev, pm_message_t mesg) |
2614 | { |
2615 | struct pci_dev *pdev = to_pci_dev(dev); |
2616 | struct fb_info *info = pci_get_drvdata(pdev); |
2617 | struct radeonfb_info *rinfo = info->par; |
2618 | |
2619 | if (mesg.event == pdev->dev.power.power_state.event) |
2620 | return 0; |
2621 | |
2622 | printk(KERN_DEBUG "radeonfb (%s): suspending for event: %d...\n" , |
2623 | pci_name(pdev), mesg.event); |
2624 | |
2625 | /* For suspend-to-disk, we cheat here. We don't suspend anything and |
2626 | * let fbcon continue drawing until we are all set. That shouldn't |
2627 | * really cause any problem at this point, provided that the wakeup |
2628 | * code knows that any state in memory may not match the HW |
2629 | */ |
2630 | switch (mesg.event) { |
2631 | case PM_EVENT_FREEZE: /* about to take snapshot */ |
2632 | case PM_EVENT_PRETHAW: /* before restoring snapshot */ |
2633 | goto done; |
2634 | } |
2635 | |
2636 | console_lock(); |
2637 | |
2638 | fb_set_suspend(info, state: 1); |
2639 | |
2640 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { |
2641 | /* Make sure engine is reset */ |
2642 | radeon_engine_idle(); |
2643 | radeonfb_engine_reset(rinfo); |
2644 | radeon_engine_idle(); |
2645 | } |
2646 | |
2647 | /* Blank display and LCD */ |
2648 | radeon_screen_blank(rinfo, blank: FB_BLANK_POWERDOWN, mode_switch: 1); |
2649 | |
2650 | /* Sleep */ |
2651 | rinfo->asleep = 1; |
2652 | rinfo->lock_blank = 1; |
2653 | del_timer_sync(timer: &rinfo->lvds_timer); |
2654 | |
2655 | #ifdef CONFIG_PPC_PMAC |
2656 | /* On powermac, we have hooks to properly suspend/resume AGP now, |
2657 | * use them here. We'll ultimately need some generic support here, |
2658 | * but the generic code isn't quite ready for that yet |
2659 | */ |
2660 | pmac_suspend_agp_for_card(pdev); |
2661 | #endif /* CONFIG_PPC_PMAC */ |
2662 | |
2663 | /* If we support wakeup from poweroff, we save all regs we can including cfg |
2664 | * space |
2665 | */ |
2666 | if (rinfo->pm_mode & radeon_pm_off) { |
2667 | /* Always disable dynamic clocks or weird things are happening when |
2668 | * the chip goes off (basically the panel doesn't shut down properly |
2669 | * and we crash on wakeup), |
2670 | * also, we want the saved regs context to have no dynamic clocks in |
2671 | * it, we'll restore the dynamic clocks state on wakeup |
2672 | */ |
2673 | radeon_pm_disable_dynamic_mode(rinfo); |
2674 | msleep(msecs: 50); |
2675 | radeon_pm_save_regs(rinfo, saving_for_d3: 1); |
2676 | |
2677 | if (rinfo->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) { |
2678 | /* Switch off LVDS interface */ |
2679 | usleep_range(min: 1000, max: 2000); |
2680 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_BL_MOD_EN)); |
2681 | usleep_range(min: 1000, max: 2000); |
2682 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_EN | LVDS_ON)); |
2683 | OUTREG(LVDS_PLL_CNTL, (INREG(LVDS_PLL_CNTL) & ~30000) | 0x20000); |
2684 | msleep(msecs: 20); |
2685 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); |
2686 | } |
2687 | } |
2688 | /* If we support D2, we go to it (should be fixed later with a flag forcing |
2689 | * D3 only for some laptops) |
2690 | */ |
2691 | if (rinfo->pm_mode & radeon_pm_d2) |
2692 | radeon_set_suspend(rinfo, suspend: 1); |
2693 | |
2694 | console_unlock(); |
2695 | |
2696 | done: |
2697 | pdev->dev.power.power_state = mesg; |
2698 | |
2699 | return 0; |
2700 | } |
2701 | |
2702 | static int radeonfb_pci_suspend(struct device *dev) |
2703 | { |
2704 | return radeonfb_pci_suspend_late(dev, PMSG_SUSPEND); |
2705 | } |
2706 | |
2707 | static int radeonfb_pci_hibernate(struct device *dev) |
2708 | { |
2709 | return radeonfb_pci_suspend_late(dev, PMSG_HIBERNATE); |
2710 | } |
2711 | |
2712 | static int radeonfb_pci_freeze(struct device *dev) |
2713 | { |
2714 | return radeonfb_pci_suspend_late(dev, PMSG_FREEZE); |
2715 | } |
2716 | |
2717 | static int radeon_check_power_loss(struct radeonfb_info *rinfo) |
2718 | { |
2719 | return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) || |
2720 | rinfo->save_regs[2] != INPLL(MCLK_CNTL) || |
2721 | rinfo->save_regs[3] != INPLL(SCLK_CNTL); |
2722 | } |
2723 | |
2724 | static int radeonfb_pci_resume(struct device *dev) |
2725 | { |
2726 | struct pci_dev *pdev = to_pci_dev(dev); |
2727 | struct fb_info *info = pci_get_drvdata(pdev); |
2728 | struct radeonfb_info *rinfo = info->par; |
2729 | int rc = 0; |
2730 | |
2731 | if (pdev->dev.power.power_state.event == PM_EVENT_ON) |
2732 | return 0; |
2733 | |
2734 | if (rinfo->no_schedule) { |
2735 | if (!console_trylock()) |
2736 | return 0; |
2737 | } else |
2738 | console_lock(); |
2739 | |
2740 | printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n" , |
2741 | pci_name(pdev), pdev->dev.power.power_state.event); |
2742 | |
2743 | /* PCI state will have been restored by the core, so |
2744 | * we should be in D0 now with our config space fully |
2745 | * restored |
2746 | */ |
2747 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { |
2748 | /* Wakeup chip */ |
2749 | if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) { |
2750 | if (rinfo->reinit_func != NULL) |
2751 | rinfo->reinit_func(rinfo); |
2752 | else { |
2753 | printk(KERN_ERR "radeonfb (%s): can't resume radeon from" |
2754 | " D3 cold, need softboot !" , pci_name(pdev)); |
2755 | rc = -EIO; |
2756 | goto bail; |
2757 | } |
2758 | } |
2759 | /* If we support D2, try to resume... we should check what was our |
2760 | * state though... (were we really in D2 state ?). Right now, this code |
2761 | * is only enable on Macs so it's fine. |
2762 | */ |
2763 | else if (rinfo->pm_mode & radeon_pm_d2) |
2764 | radeon_set_suspend(rinfo, suspend: 0); |
2765 | |
2766 | rinfo->asleep = 0; |
2767 | } else |
2768 | radeon_engine_idle(); |
2769 | |
2770 | /* Restore display & engine */ |
2771 | radeon_write_mode (rinfo, mode: &rinfo->state, reg_only: 1); |
2772 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) |
2773 | radeonfb_engine_init (rinfo); |
2774 | |
2775 | fb_pan_display(info, var: &info->var); |
2776 | fb_set_cmap(cmap: &info->cmap, fb_info: info); |
2777 | |
2778 | /* Refresh */ |
2779 | fb_set_suspend(info, state: 0); |
2780 | |
2781 | /* Unblank */ |
2782 | rinfo->lock_blank = 0; |
2783 | radeon_screen_blank(rinfo, blank: FB_BLANK_UNBLANK, mode_switch: 1); |
2784 | |
2785 | #ifdef CONFIG_PPC_PMAC |
2786 | /* On powermac, we have hooks to properly suspend/resume AGP now, |
2787 | * use them here. We'll ultimately need some generic support here, |
2788 | * but the generic code isn't quite ready for that yet |
2789 | */ |
2790 | pmac_resume_agp_for_card(pdev); |
2791 | #endif /* CONFIG_PPC_PMAC */ |
2792 | |
2793 | |
2794 | /* Check status of dynclk */ |
2795 | if (rinfo->dynclk == 1) |
2796 | radeon_pm_enable_dynamic_mode(rinfo); |
2797 | else if (rinfo->dynclk == 0) |
2798 | radeon_pm_disable_dynamic_mode(rinfo); |
2799 | |
2800 | pdev->dev.power.power_state = PMSG_ON; |
2801 | |
2802 | bail: |
2803 | console_unlock(); |
2804 | |
2805 | return rc; |
2806 | } |
2807 | |
2808 | const struct dev_pm_ops radeonfb_pci_pm_ops = { |
2809 | .suspend = radeonfb_pci_suspend, |
2810 | .resume = radeonfb_pci_resume, |
2811 | .freeze = radeonfb_pci_freeze, |
2812 | .thaw = radeonfb_pci_resume, |
2813 | .poweroff = radeonfb_pci_hibernate, |
2814 | .restore = radeonfb_pci_resume, |
2815 | }; |
2816 | |
2817 | #ifdef CONFIG_PPC__disabled |
2818 | static void radeonfb_early_resume(void *data) |
2819 | { |
2820 | struct radeonfb_info *rinfo = data; |
2821 | |
2822 | rinfo->no_schedule = 1; |
2823 | pci_restore_state(rinfo->pdev); |
2824 | radeonfb_pci_resume(rinfo->pdev); |
2825 | rinfo->no_schedule = 0; |
2826 | } |
2827 | #endif /* CONFIG_PPC */ |
2828 | |
2829 | #endif /* CONFIG_PM */ |
2830 | |
2831 | void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep) |
2832 | { |
2833 | /* Enable/Disable dynamic clocks: TODO add sysfs access */ |
2834 | if (rinfo->family == CHIP_FAMILY_RS480) |
2835 | rinfo->dynclk = -1; |
2836 | else |
2837 | rinfo->dynclk = dynclk; |
2838 | |
2839 | if (rinfo->dynclk == 1) { |
2840 | radeon_pm_enable_dynamic_mode(rinfo); |
2841 | printk("radeonfb: Dynamic Clock Power Management enabled\n" ); |
2842 | } else if (rinfo->dynclk == 0) { |
2843 | radeon_pm_disable_dynamic_mode(rinfo); |
2844 | printk("radeonfb: Dynamic Clock Power Management disabled\n" ); |
2845 | } |
2846 | |
2847 | #if defined(CONFIG_PM) |
2848 | #if defined(CONFIG_PPC_PMAC) |
2849 | /* Check if we can power manage on suspend/resume. We can do |
2850 | * D2 on M6, M7 and M9, and we can resume from D3 cold a few other |
2851 | * "Mac" cards, but that's all. We need more infos about what the |
2852 | * BIOS does tho. Right now, all this PM stuff is pmac-only for that |
2853 | * reason. --BenH |
2854 | */ |
2855 | if (machine_is(powermac) && rinfo->of_node) { |
2856 | if (rinfo->is_mobility && rinfo->pdev->pm_cap && |
2857 | rinfo->family <= CHIP_FAMILY_RV250) |
2858 | rinfo->pm_mode |= radeon_pm_d2; |
2859 | |
2860 | /* We can restart Jasper (M10 chip in albooks), BlueStone (7500 chip |
2861 | * in some desktop G4s), Via (M9+ chip on iBook G4) and |
2862 | * Snowy (M11 chip on iBook G4 manufactured after July 2005) |
2863 | */ |
2864 | if (of_node_name_eq(rinfo->of_node, "ATY,JasperParent" ) || |
2865 | of_node_name_eq(rinfo->of_node, "ATY,SnowyParent" )) { |
2866 | rinfo->reinit_func = radeon_reinitialize_M10; |
2867 | rinfo->pm_mode |= radeon_pm_off; |
2868 | } |
2869 | #if 0 /* Not ready yet */ |
2870 | if (!strcmp(rinfo->of_node->name, "ATY,BlueStoneParent" )) { |
2871 | rinfo->reinit_func = radeon_reinitialize_QW; |
2872 | rinfo->pm_mode |= radeon_pm_off; |
2873 | } |
2874 | #endif |
2875 | if (of_node_name_eq(rinfo->of_node, "ATY,ViaParent" )) { |
2876 | rinfo->reinit_func = radeon_reinitialize_M9P; |
2877 | rinfo->pm_mode |= radeon_pm_off; |
2878 | } |
2879 | |
2880 | /* If any of the above is set, we assume the machine can sleep/resume. |
2881 | * It's a bit of a "shortcut" but will work fine. Ideally, we need infos |
2882 | * from the platform about what happens to the chip... |
2883 | * Now we tell the platform about our capability |
2884 | */ |
2885 | if (rinfo->pm_mode != radeon_pm_none) { |
2886 | pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1); |
2887 | #if 0 /* Disable the early video resume hack for now as it's causing problems, among |
2888 | * others we now rely on the PCI core restoring the config space for us, which |
2889 | * isn't the case with that hack, and that code path causes various things to |
2890 | * be called with interrupts off while they shouldn't. I'm leaving the code in |
2891 | * as it can be useful for debugging purposes |
2892 | */ |
2893 | pmac_set_early_video_resume(radeonfb_early_resume, rinfo); |
2894 | #endif |
2895 | } |
2896 | |
2897 | #if 0 |
2898 | /* Power down TV DAC, that saves a significant amount of power, |
2899 | * we'll have something better once we actually have some TVOut |
2900 | * support |
2901 | */ |
2902 | OUTREG(TV_DAC_CNTL, INREG(TV_DAC_CNTL) | 0x07000000); |
2903 | #endif |
2904 | } |
2905 | #endif /* defined(CONFIG_PPC_PMAC) */ |
2906 | #endif /* defined(CONFIG_PM) */ |
2907 | |
2908 | if (ignore_devlist) |
2909 | printk(KERN_DEBUG |
2910 | "radeonfb: skipping test for device workarounds\n" ); |
2911 | else |
2912 | radeon_apply_workarounds(rinfo); |
2913 | |
2914 | if (force_sleep) { |
2915 | printk(KERN_DEBUG |
2916 | "radeonfb: forcefully enabling D2 sleep mode\n" ); |
2917 | rinfo->pm_mode |= radeon_pm_d2; |
2918 | } |
2919 | } |
2920 | |
2921 | void radeonfb_pm_exit(struct radeonfb_info *rinfo) |
2922 | { |
2923 | #if defined(CONFIG_PM) && defined(CONFIG_PPC_PMAC) |
2924 | if (rinfo->pm_mode != radeon_pm_none) |
2925 | pmac_set_early_video_resume(NULL, NULL); |
2926 | #endif |
2927 | } |
2928 | |