Rev 1029 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1029 | serge | 1 | /* |
2 | * Copyright 2007, 2008 Luc Verhaegen |
||
3 | * Copyright 2007, 2008 Matthias Hopf |
||
4 | * Copyright 2007, 2008 Egbert Eich |
||
5 | * Copyright 2007, 2008 Advanced Micro Devices, Inc. |
||
6 | * |
||
7 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
8 | * copy of this software and associated documentation files (the "Software"), |
||
9 | * to deal in the Software without restriction, including without limitation |
||
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
11 | * and/or sell copies of the Software, and to permit persons to whom the |
||
12 | * Software is furnished to do so, subject to the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice shall be included in |
||
15 | * all copies or substantial portions of the Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
20 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
23 | * OTHER DEALINGS IN THE SOFTWARE. |
||
24 | */ |
||
25 | |||
26 | /* |
||
27 | * MC idling: |
||
28 | * |
||
29 | * For SetupFBLocation and Restore, we require a fully idle MC as we might lock up |
||
30 | * otherwise. Both calls now check whether the MC is Idle before attempting |
||
31 | * to set up the MC, and complain loudly when this fails. |
||
32 | * |
||
33 | * Likely suspect registers for when the Idle fails: |
||
34 | * DxVGA_CONTROL & D1VGA_MODE_ENABLE (run RHDVGADisable beforehand) |
||
35 | * DxCRTC_CONTROL & 0x1 (run DxCRTCDisable beforehand) |
||
36 | * (... Add more here...) |
||
37 | * |
||
38 | * |
||
39 | * MC addressing: |
||
40 | * |
||
41 | * On R600 and up the MC can use a larger than 32bit card internal address for |
||
42 | * its framebuffer. This is why the Address used inside the MC code is a |
||
43 | * CARD64. |
||
44 | * |
||
45 | * rhdPtr->FbIntAddress is kept as a CARD32 for the time being. This is still |
||
46 | * valid, as this makes the R500 code simpler, and since we pick FbIntAddress |
||
47 | * from a 32bit register anyway on R600. FbIntAddress will also correctly cast |
||
48 | * to a CARD64 when passed to the likes of the SetupFBLocation callback. |
||
49 | */ |
||
50 | |||
51 | #ifdef HAVE_CONFIG_H |
||
52 | #include "config.h" |
||
53 | #endif |
||
54 | |||
55 | #if HAVE_XF86_ANSIC_H |
||
56 | # include "xf86_ansic.h" |
||
57 | #else |
||
58 | # include |
||
59 | #endif |
||
60 | |||
61 | #include "xf86.h" |
||
62 | |||
63 | #include "rhd.h" |
||
64 | #include "rhd_regs.h" |
||
65 | #include "rhd_crtc.h" /* for definition of Crtc->Id */ |
||
66 | |||
67 | struct rhdMC { |
||
68 | int scrnIndex; |
||
69 | |||
70 | CARD32 FbLocation; |
||
71 | CARD32 HdpFbAddress; |
||
72 | CARD32 MiscLatencyTimer; |
||
73 | Bool Stored; |
||
74 | void (*Save)(struct rhdMC *MC); |
||
75 | void (*Restore)(struct rhdMC *MC); |
||
76 | Bool (*Idle)(struct rhdMC *MC); |
||
77 | CARD64 (*GetFBLocation)(struct rhdMC *MC, CARD32 *size); |
||
78 | void (*SetupFBLocation)(struct rhdMC *MC, CARD64 Address, CARD32 Size); |
||
79 | void (*TuneAccessForDisplay)(struct rhdMC *MC, int crtc, |
||
80 | DisplayModePtr Mode, DisplayModePtr ScaledToMode); |
||
81 | }; |
||
82 | |||
83 | /* |
||
84 | * Some common FB location calculations. |
||
85 | */ |
||
86 | /* |
||
87 | * Applicable for all R5xx and RS600, RS690, RS740 |
||
88 | */ |
||
89 | static CARD64 |
||
90 | R5xxMCGetFBLocation(CARD32 Value, CARD32 *Size) |
||
91 | { |
||
92 | *Size = (Value & 0xFFFF0000) - ((Value & 0xFFFF) << 16); |
||
93 | return (Value & 0xFFFF) << 16; |
||
94 | } |
||
95 | |||
96 | #define R5XX_FB_LOCATION(address, size) \ |
||
97 | ((((address) + (size)) & 0xFFFF0000) | (((address) >> 16) & 0xFFFF)) |
||
98 | #define R5XX_HDP_LOCATION(address) \ |
||
99 | (((address) >> 16) & 0xFFFF) |
||
100 | |||
101 | /* |
||
102 | * Applicable for all R6xx and R7xx, and RS780/RS790 |
||
103 | */ |
||
104 | static CARD64 |
||
105 | R6xxMCGetFBLocation(CARD32 Value, CARD32 *Size) |
||
106 | { |
||
107 | *Size = (((Value & 0xFFFF0000) - ((Value & 0xFFFF) << 16))) << 8; |
||
108 | return (Value & 0xFFFF) << 24; |
||
109 | } |
||
110 | |||
111 | #define R6XX_FB_LOCATION(address, size) \ |
||
112 | (((((address) + (size)) >> 8) & 0xFFFF0000) | (((address) >> 24) & 0xFFFF)) |
||
113 | #define R6XX_HDP_LOCATION(address) \ |
||
114 | ((((address) >> 8) & 0x00FF0000)) |
||
115 | |||
116 | /* |
||
117 | * |
||
118 | */ |
||
119 | static void |
||
120 | RV515MCSave(struct rhdMC *MC) |
||
121 | { |
||
122 | MC->FbLocation = RHDReadMC(MC, MC_IND_ALL | RV515_MC_FB_LOCATION); |
||
123 | MC->MiscLatencyTimer = RHDReadMC(MC, MC_IND_ALL | RV515_MC_MISC_LAT_TIMER); |
||
124 | MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION); |
||
125 | } |
||
126 | |||
127 | /* |
||
128 | * |
||
129 | */ |
||
130 | static void |
||
131 | RV515MCRestore(struct rhdMC *MC) |
||
132 | { |
||
133 | RHDWriteMC(MC, MC_IND_ALL | RV515_MC_FB_LOCATION, MC->FbLocation); |
||
134 | RHDWriteMC(MC, MC_IND_ALL | RV515_MC_MISC_LAT_TIMER, MC->MiscLatencyTimer); |
||
135 | RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress); |
||
136 | } |
||
137 | |||
138 | /* |
||
139 | * |
||
140 | */ |
||
141 | static Bool |
||
142 | RV515MCWaitIdle(struct rhdMC *MC) |
||
143 | { |
||
144 | if (RHDReadMC(MC, MC_IND_ALL | RV515_MC_STATUS) & RV515_MC_IDLE) |
||
145 | return TRUE; |
||
146 | return FALSE; |
||
147 | } |
||
148 | |||
149 | /* |
||
150 | * |
||
151 | */ |
||
152 | static CARD64 |
||
153 | RV515MCGetFBLocation(struct rhdMC *MC, CARD32 *Size) |
||
154 | { |
||
155 | return R5xxMCGetFBLocation(RHDReadMC(MC, RV515_MC_FB_LOCATION | MC_IND_ALL), Size); |
||
156 | } |
||
157 | |||
158 | /* |
||
159 | * |
||
160 | */ |
||
161 | static void |
||
162 | RV515MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size) |
||
163 | { |
||
164 | RHDWriteMC(MC, RV515_MC_FB_LOCATION | MC_IND_ALL, |
||
165 | R5XX_FB_LOCATION(Address, Size)); |
||
166 | RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address)); |
||
167 | } |
||
168 | |||
169 | /* |
||
170 | * |
||
171 | */ |
||
172 | static void |
||
173 | RV515MCTuneMCAccessForDisplay(struct rhdMC *MC, int Crtc, |
||
174 | DisplayModePtr Mode, DisplayModePtr ScaledToMode) |
||
175 | { |
||
176 | CARD32 value, setting = 0x1; |
||
177 | |||
178 | value = RHDReadMC(MC, RV515_MC_MISC_LAT_TIMER); |
||
179 | |||
180 | if (Crtc == RHD_CRTC_1) { |
||
181 | value &= ~(0x0F << MC_DISP0R_INIT_LAT_SHIFT); |
||
182 | value |= setting << MC_DISP0R_INIT_LAT_SHIFT; |
||
183 | } else { /* RHD_CRTC_2 */ |
||
184 | value &= ~(0x0F << MC_DISP1R_INIT_LAT_SHIFT); |
||
185 | value |= setting << MC_DISP1R_INIT_LAT_SHIFT; |
||
186 | } |
||
187 | |||
188 | RHDWriteMC(MC, RV515_MC_MISC_LAT_TIMER, value); |
||
189 | } |
||
190 | |||
191 | /* |
||
192 | * |
||
193 | */ |
||
194 | static void |
||
195 | R500MCSave(struct rhdMC *MC) |
||
196 | { |
||
197 | MC->FbLocation = RHDReadMC(MC, MC_IND_ALL | R5XX_MC_FB_LOCATION); |
||
198 | MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION); |
||
199 | } |
||
200 | |||
201 | /* |
||
202 | * |
||
203 | */ |
||
204 | static void |
||
205 | R500MCRestore(struct rhdMC *MC) |
||
206 | { |
||
207 | RHDWriteMC(MC, MC_IND_ALL | R5XX_MC_FB_LOCATION, MC->FbLocation); |
||
208 | RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress); |
||
209 | } |
||
210 | |||
211 | /* |
||
212 | * |
||
213 | */ |
||
214 | static Bool |
||
215 | R500MCWaitIdle(struct rhdMC *MC) |
||
216 | { |
||
217 | if (RHDReadMC(MC, MC_IND_ALL | R5XX_MC_STATUS) & R5XX_MC_IDLE) |
||
218 | return TRUE; |
||
219 | return FALSE; |
||
220 | } |
||
221 | |||
222 | /* |
||
223 | * |
||
224 | */ |
||
225 | static CARD64 |
||
226 | R500MCGetFBLocation(struct rhdMC *MC, CARD32 *Size) |
||
227 | { |
||
228 | return R5xxMCGetFBLocation(RHDReadMC(MC, R5XX_MC_FB_LOCATION | MC_IND_ALL), Size); |
||
229 | } |
||
230 | |||
231 | /* |
||
232 | * |
||
233 | */ |
||
234 | static void |
||
235 | R500MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size) |
||
236 | { |
||
237 | RHDWriteMC(MC, R5XX_MC_FB_LOCATION | MC_IND_ALL, |
||
238 | R5XX_FB_LOCATION(Address, Size)); |
||
239 | RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address)); |
||
240 | } |
||
241 | |||
242 | /* |
||
243 | * |
||
244 | */ |
||
245 | static void |
||
246 | RS600MCSave(struct rhdMC *MC) |
||
247 | { |
||
248 | MC->FbLocation = RHDReadMC(MC, RS60_NB_FB_LOCATION); |
||
249 | MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION); |
||
250 | } |
||
251 | |||
252 | /* |
||
253 | * |
||
254 | */ |
||
255 | static void |
||
256 | RS600MCRestore(struct rhdMC *MC) |
||
257 | { |
||
258 | RHDWriteMC(MC, RS60_NB_FB_LOCATION, MC->FbLocation); |
||
259 | RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress); |
||
260 | } |
||
261 | |||
262 | /* |
||
263 | * |
||
264 | */ |
||
265 | static Bool |
||
266 | RS600MCWaitIdle(struct rhdMC *MC) |
||
267 | { |
||
268 | if (RHDReadMC(MC, RS60_MC_SYSTEM_STATUS) & RS6X_MC_SEQUENCER_IDLE) |
||
269 | return TRUE; |
||
270 | return FALSE; |
||
271 | } |
||
272 | |||
273 | /* |
||
274 | * |
||
275 | */ |
||
276 | static CARD64 |
||
277 | RS600MCGetFBLocation(struct rhdMC *MC, CARD32 *Size) |
||
278 | { |
||
279 | return R5xxMCGetFBLocation(RHDReadMC(MC, RS60_NB_FB_LOCATION), Size); |
||
280 | } |
||
281 | |||
282 | /* |
||
283 | * |
||
284 | */ |
||
285 | static void |
||
286 | RS600MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size) |
||
287 | { |
||
288 | RHDWriteMC(MC, RS60_NB_FB_LOCATION, R5XX_FB_LOCATION(Address, Size)); |
||
289 | RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address)); |
||
290 | } |
||
291 | |||
292 | /* |
||
293 | * |
||
294 | */ |
||
295 | static void |
||
296 | RS690MCSave(struct rhdMC *MC) |
||
297 | { |
||
298 | MC->FbLocation = RHDReadMC(MC, RS69_MCCFG_FB_LOCATION); |
||
299 | MC->HdpFbAddress = RHDRegRead(MC, HDP_FB_LOCATION); |
||
300 | MC->MiscLatencyTimer = RHDReadMC(MC, RS69_MC_INIT_MISC_LAT_TIMER); |
||
301 | |||
302 | } |
||
303 | |||
304 | /* |
||
305 | * |
||
306 | */ |
||
307 | static void |
||
308 | RS690MCRestore(struct rhdMC *MC) |
||
309 | { |
||
310 | RHDWriteMC(MC, RS69_MCCFG_FB_LOCATION, MC->FbLocation); |
||
311 | RHDRegWrite(MC, HDP_FB_LOCATION, MC->HdpFbAddress); |
||
312 | RHDWriteMC(MC, RS69_MC_INIT_MISC_LAT_TIMER, MC->MiscLatencyTimer); |
||
313 | } |
||
314 | |||
315 | /* |
||
316 | * |
||
317 | */ |
||
318 | static Bool |
||
319 | RS690MCWaitIdle(struct rhdMC *MC) |
||
320 | { |
||
321 | if (RHDReadMC(MC, RS69_MC_SYSTEM_STATUS) & RS6X_MC_SEQUENCER_IDLE) |
||
322 | return TRUE; |
||
323 | return FALSE; |
||
324 | } |
||
325 | |||
326 | /* |
||
327 | * |
||
328 | */ |
||
329 | static CARD64 |
||
330 | RS690MCGetFBLocation(struct rhdMC *MC, CARD32 *Size) |
||
331 | { |
||
332 | return R5xxMCGetFBLocation(RHDReadMC(MC, RS69_MCCFG_FB_LOCATION), Size); |
||
333 | } |
||
334 | |||
335 | /* |
||
336 | * |
||
337 | */ |
||
338 | static void |
||
339 | RS690MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size) |
||
340 | { |
||
341 | RHDWriteMC(MC, RS69_MCCFG_FB_LOCATION, R5XX_FB_LOCATION(Address, Size)); |
||
342 | RHDRegWrite(MC, HDP_FB_LOCATION, R5XX_HDP_LOCATION(Address)); |
||
343 | } |
||
344 | |||
345 | /* |
||
346 | * |
||
347 | */ |
||
348 | static void |
||
349 | RS690MCTuneMCAccessForDisplay(struct rhdMC *MC, int Crtc, |
||
350 | DisplayModePtr Mode, DisplayModePtr ScaledToMode) |
||
351 | { |
||
352 | CARD32 value, setting = 0x1; |
||
353 | |||
354 | value = RHDReadMC(MC, RS69_MC_INIT_MISC_LAT_TIMER); |
||
355 | |||
356 | if (Crtc == RHD_CRTC_1) { |
||
357 | value &= ~(0x0F << MC_DISP0R_INIT_LAT_SHIFT); |
||
358 | value |= setting << MC_DISP0R_INIT_LAT_SHIFT; |
||
359 | } else { /* RHD_CRTC_2 */ |
||
360 | value &= ~(0x0F << MC_DISP1R_INIT_LAT_SHIFT); |
||
361 | value |= setting << MC_DISP1R_INIT_LAT_SHIFT; |
||
362 | } |
||
363 | |||
364 | RHDWriteMC(MC, RS69_MC_INIT_MISC_LAT_TIMER, value); |
||
365 | } |
||
366 | |||
367 | /* |
||
368 | * |
||
369 | */ |
||
370 | static void |
||
371 | R600MCSave(struct rhdMC *MC) |
||
372 | { |
||
373 | MC->FbLocation = RHDRegRead(MC, R6XX_MC_VM_FB_LOCATION); |
||
374 | MC->HdpFbAddress = RHDRegRead(MC, R6XX_HDP_NONSURFACE_BASE); |
||
375 | } |
||
376 | |||
377 | /* |
||
378 | * |
||
379 | */ |
||
380 | static void |
||
381 | R600MCRestore(struct rhdMC *MC) |
||
382 | { |
||
383 | RHDRegWrite(MC, R6XX_MC_VM_FB_LOCATION, MC->FbLocation); |
||
384 | RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbAddress); |
||
385 | } |
||
386 | |||
387 | /* |
||
388 | * |
||
389 | */ |
||
390 | static Bool |
||
391 | R600MCWaitIdle(struct rhdMC *MC) |
||
392 | { |
||
393 | if (!(RHDRegRead(MC, SRBM_STATUS) & 0x3f00)) |
||
394 | return TRUE; |
||
395 | return FALSE; |
||
396 | } |
||
397 | |||
398 | |||
399 | /* |
||
400 | * |
||
401 | */ |
||
402 | static CARD64 |
||
403 | R600MCGetFBLocation(struct rhdMC *MC, CARD32 *Size) |
||
404 | { |
||
405 | return R6xxMCGetFBLocation(RHDRegRead(MC, R6XX_MC_VM_FB_LOCATION), Size); |
||
406 | } |
||
407 | |||
408 | /* |
||
409 | * |
||
410 | */ |
||
411 | static void |
||
412 | R600MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size) |
||
413 | { |
||
414 | RHDRegWrite(MC, R6XX_MC_VM_FB_LOCATION, R6XX_FB_LOCATION(Address, Size)); |
||
415 | RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(Address)); |
||
416 | } |
||
417 | |||
418 | /* |
||
419 | * |
||
420 | */ |
||
421 | #ifdef NOTYET |
||
422 | |||
423 | /* |
||
424 | * |
||
425 | */ |
||
426 | static void |
||
427 | RS780MCSave(struct rhdMC *MC) |
||
428 | { |
||
429 | MC->FbLocation = RHDReadMC(MC, RS78_MC_FB_LOCATION); |
||
430 | MC->HdpFbAddress = RHDRegRead(MC, R6XX_HDP_NONSURFACE_BASE); |
||
431 | } |
||
432 | |||
433 | /* |
||
434 | * |
||
435 | */ |
||
436 | static void |
||
437 | RS780MCRestore(struct rhdMC *MC) |
||
438 | { |
||
439 | RHDWriteMC(MC, RS78_MC_FB_LOCATION, MC->FbLocation); |
||
440 | RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbAddress); |
||
441 | } |
||
442 | |||
443 | /* |
||
444 | * |
||
445 | */ |
||
446 | static Bool |
||
447 | RS780MCWaitIdle(struct rhdMC *MC) |
||
448 | { |
||
449 | if (RHDReadMC(MC, RS78_MC_SYSTEM_STATUS) & RS78_MC_SEQUENCER_IDLE) |
||
450 | return TRUE; |
||
451 | return FALSE; |
||
452 | } |
||
453 | |||
454 | /* |
||
455 | * |
||
456 | */ |
||
457 | static CARD64 |
||
458 | RS780MCGetFBLocation(struct rhdMC *MC, CARD32 *Size) |
||
459 | { |
||
460 | /* is this correct? */ |
||
461 | |||
462 | return R5xxMCGetFBLocation(RHDReadMC(MC, RS78_MC_FB_LOCATION), Size); |
||
463 | } |
||
464 | |||
465 | /* |
||
466 | * |
||
467 | */ |
||
468 | static void |
||
469 | RS780MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size) |
||
470 | { |
||
471 | /* is this correct? */ |
||
472 | RHDWriteMC(MC, RS78_MC_FB_LOCATION, R5XX_FB_LOCATION(Address, Size)); |
||
473 | RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(Address)); |
||
474 | } |
||
475 | #endif /* NOTYET */ |
||
476 | |||
477 | /* |
||
478 | * |
||
479 | */ |
||
480 | static void |
||
481 | R700MCSave(struct rhdMC *MC) |
||
482 | { |
||
483 | MC->FbLocation = RHDRegRead(MC, R7XX_MC_VM_FB_LOCATION); |
||
484 | MC->HdpFbAddress = RHDRegRead(MC, R6XX_HDP_NONSURFACE_BASE); |
||
485 | } |
||
486 | |||
487 | /* |
||
488 | * |
||
489 | */ |
||
490 | static void |
||
491 | R700MCRestore(struct rhdMC *MC) |
||
492 | { |
||
493 | RHDFUNC(MC); |
||
494 | |||
495 | RHDRegWrite(MC, R7XX_MC_VM_FB_LOCATION, MC->FbLocation); |
||
496 | RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, MC->HdpFbAddress); |
||
497 | } |
||
498 | |||
499 | /* |
||
500 | * Idle is the R600 one... |
||
501 | */ |
||
502 | |||
503 | /* |
||
504 | * |
||
505 | */ |
||
506 | static CARD64 |
||
507 | R700MCGetFBLocation(struct rhdMC *MC, CARD32 *Size) |
||
508 | { |
||
509 | return R6xxMCGetFBLocation(RHDRegRead(MC, R7XX_MC_VM_FB_LOCATION), Size); |
||
510 | } |
||
511 | |||
512 | /* |
||
513 | * |
||
514 | */ |
||
515 | static void |
||
516 | R700MCSetupFBLocation(struct rhdMC *MC, CARD64 Address, CARD32 Size) |
||
517 | { |
||
518 | RHDRegWrite(MC, R7XX_MC_VM_FB_LOCATION, R6XX_FB_LOCATION(Address, Size)); |
||
519 | RHDRegWrite(MC, R6XX_HDP_NONSURFACE_BASE, R6XX_HDP_LOCATION(Address)); |
||
520 | } |
||
521 | |||
522 | |||
523 | /* |
||
524 | * |
||
525 | */ |
||
526 | void |
||
527 | RHDMCInit(RHDPtr rhdPtr) |
||
528 | { |
||
529 | struct rhdMC *MC; |
||
530 | |||
531 | RHDFUNC(rhdPtr); |
||
532 | |||
533 | /* These devices have an internal address reference, which some other |
||
534 | * address registers in there also use. This can be different from the |
||
535 | * address in the BAR. |
||
536 | * |
||
537 | * We read out the address here from some known location. This address |
||
538 | * is as good a guess as any, we just need to pick one, but then make |
||
539 | * sure that it is made consistent in MCSetupFBLocation and the various MC |
||
540 | * accessing subsystems. |
||
541 | */ |
||
542 | |||
543 | RHDDebug(rhdPtr->scrnIndex, "MC FB Address: 0x%08X.\n", |
||
544 | rhdPtr->FbIntAddress); |
||
545 | |||
546 | MC = xnfcalloc(1, sizeof(struct rhdMC)); |
||
547 | MC->scrnIndex = rhdPtr->scrnIndex; |
||
548 | |||
549 | if (rhdPtr->ChipSet < RHD_RS600) { |
||
550 | switch(rhdPtr->ChipSet) { |
||
551 | case RHD_RV515: |
||
552 | case RHD_RV505: |
||
553 | case RHD_RV516: |
||
554 | case RHD_RV550: |
||
555 | case RHD_M52: |
||
556 | case RHD_M54: |
||
557 | case RHD_M62: |
||
558 | case RHD_M64: |
||
559 | case RHD_M71: |
||
560 | MC->Save = RV515MCSave; |
||
561 | MC->Restore = RV515MCRestore; |
||
562 | MC->SetupFBLocation = RV515MCSetupFBLocation; |
||
563 | MC->GetFBLocation = RV515MCGetFBLocation; |
||
564 | MC->Idle = RV515MCWaitIdle; |
||
565 | MC->TuneAccessForDisplay = RV515MCTuneMCAccessForDisplay; |
||
566 | break; |
||
567 | default: |
||
568 | MC->Save = R500MCSave; |
||
569 | MC->Restore = R500MCRestore; |
||
570 | MC->SetupFBLocation = R500MCSetupFBLocation; |
||
571 | MC->GetFBLocation = R500MCGetFBLocation; |
||
572 | MC->Idle = R500MCWaitIdle; |
||
573 | break; |
||
574 | } |
||
575 | |||
576 | } else if (rhdPtr->ChipSet == RHD_RS600) { |
||
577 | MC->Save = RS600MCSave; |
||
578 | MC->Restore = RS600MCRestore; |
||
579 | MC->SetupFBLocation = RS600MCSetupFBLocation; |
||
580 | MC->Idle = RS600MCWaitIdle; |
||
581 | MC->GetFBLocation = RS600MCGetFBLocation; |
||
582 | } else if (rhdPtr->ChipSet < RHD_R600) { |
||
583 | MC->Save = RS690MCSave; |
||
584 | MC->Restore = RS690MCRestore; |
||
585 | MC->SetupFBLocation = RS690MCSetupFBLocation; |
||
586 | MC->Idle = RS690MCWaitIdle; |
||
587 | MC->GetFBLocation = RS690MCGetFBLocation; |
||
588 | MC->TuneAccessForDisplay = RS690MCTuneMCAccessForDisplay; |
||
589 | } else if (rhdPtr->ChipSet <= RHD_RS780) { |
||
590 | MC->Save = R600MCSave; |
||
591 | MC->Restore = R600MCRestore; |
||
592 | MC->SetupFBLocation = R600MCSetupFBLocation; |
||
593 | MC->Idle = R600MCWaitIdle; |
||
594 | MC->GetFBLocation = R600MCGetFBLocation; |
||
595 | } |
||
596 | #ifdef NOTYET |
||
597 | else if (rhdPtr->ChipSet == RHD_RS780) { |
||
598 | MC->Save = RS780MCSave; |
||
599 | MC->Restore = RS780MCRestore; |
||
600 | MC->SetupFBLocation = RS780MCSetupFBLocation; |
||
601 | MC->Idle = RS780MCWaitIdle; |
||
602 | MC->GetFBLocation = RS780MCGetFBLocation; |
||
603 | } |
||
604 | #endif /* NOTYET */ |
||
605 | else if (rhdPtr->ChipSet >= RHD_RV770) { |
||
606 | MC->Save = R700MCSave; |
||
607 | MC->Restore = R700MCRestore; |
||
608 | MC->SetupFBLocation = R700MCSetupFBLocation; |
||
609 | MC->Idle = R600MCWaitIdle; |
||
610 | MC->GetFBLocation = R700MCGetFBLocation; |
||
611 | } else { |
||
612 | xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "I don't know anything about MC on this chipset\n"); |
||
613 | xfree(MC); |
||
614 | return; |
||
615 | } |
||
616 | if (rhdPtr->ChipSet < RHD_R600) |
||
617 | rhdPtr->FbIntAddress = RHDRegRead(rhdPtr, HDP_FB_LOCATION) << 16; |
||
618 | else |
||
619 | rhdPtr->FbIntAddress = RHDRegRead(rhdPtr, R6XX_CONFIG_FB_BASE); |
||
620 | MC->GetFBLocation(MC, &rhdPtr->FbIntSize); |
||
621 | |||
622 | rhdPtr->MC = MC; |
||
623 | |||
624 | } |
||
625 | |||
626 | /* |
||
627 | * Free structure. |
||
628 | */ |
||
629 | void |
||
630 | RHDMCDestroy(RHDPtr rhdPtr) |
||
631 | { |
||
632 | RHDFUNC(rhdPtr); |
||
633 | |||
634 | if (!rhdPtr->MC) |
||
635 | return; |
||
636 | |||
637 | xfree(rhdPtr->MC); |
||
638 | rhdPtr->MC = NULL; |
||
639 | } |
||
640 | |||
641 | /* |
||
642 | * |
||
643 | */ |
||
644 | void |
||
645 | RHDMCSave(RHDPtr rhdPtr) |
||
646 | { |
||
647 | struct rhdMC *MC = rhdPtr->MC; |
||
648 | |||
649 | ASSERT(MC); |
||
650 | |||
651 | RHDFUNC(rhdPtr); |
||
652 | |||
653 | MC->Save(MC); |
||
654 | |||
655 | MC->Stored = TRUE; |
||
656 | } |
||
657 | |||
658 | /* |
||
659 | * Make sure that nothing is accessing memory anymore before calling this. |
||
660 | */ |
||
661 | void |
||
662 | RHDMCRestore(RHDPtr rhdPtr) |
||
663 | { |
||
664 | struct rhdMC *MC = rhdPtr->MC; |
||
665 | |||
666 | // ASSERT(MC); |
||
667 | // RHD_UNSETDEBUGFLAG(rhdPtr, MC_SETUP); |
||
668 | |||
669 | RHDFUNC(rhdPtr); |
||
670 | |||
671 | if (!MC->Stored) { |
||
672 | xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, |
||
673 | "%s: trying to restore uninitialized values.\n",__func__); |
||
674 | return; |
||
675 | } |
||
676 | |||
677 | if (MC->Idle(MC)) |
||
678 | MC->Restore(MC); |
||
679 | else |
||
680 | xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, |
||
681 | "%s: MC is still not idle!!!\n", __func__); |
||
682 | } |
||
683 | |||
684 | /* |
||
685 | * |
||
686 | */ |
||
687 | Bool |
||
688 | RHDMCIdleWait(RHDPtr rhdPtr, CARD32 count) |
||
689 | { |
||
690 | struct rhdMC *MC = rhdPtr->MC; |
||
691 | |||
692 | RHDFUNC(rhdPtr); |
||
693 | |||
694 | ASSERT(MC); |
||
695 | |||
696 | do { |
||
697 | if (MC->Idle(MC)) |
||
698 | return TRUE; |
||
699 | usleep(100); |
||
700 | } while (count--); |
||
701 | |||
702 | RHDDebug(rhdPtr->scrnIndex, "%s: MC not idle\n",__func__); |
||
703 | |||
704 | return FALSE; |
||
705 | } |
||
706 | |||
707 | /* |
||
708 | * Get FB location and size. |
||
709 | */ |
||
710 | CARD64 |
||
711 | RHDMCGetFBLocation(RHDPtr rhdPtr, CARD32 *size) |
||
712 | { |
||
713 | struct rhdMC *MC = rhdPtr->MC; |
||
714 | |||
715 | // ASSERT(MC); |
||
716 | // ASSERT(size); |
||
717 | |||
718 | RHDFUNC(rhdPtr); |
||
719 | |||
720 | return MC->GetFBLocation(MC, size); |
||
721 | } |
||
722 | |||
723 | /* |
||
724 | * Make sure that nothing is accessing memory anymore before calling this. |
||
725 | */ |
||
726 | Bool |
||
727 | RHDMCSetupFBLocation(RHDPtr rhdPtr, CARD64 Address, CARD32 Size) |
||
728 | { |
||
729 | struct rhdMC *MC = rhdPtr->MC; |
||
730 | CARD64 OldAddress; |
||
731 | CARD32 OldSize; |
||
732 | |||
733 | // ASSERT(MC); |
||
734 | // RHD_SETDEBUGFLAG(rhdPtr, MC_SETUP); |
||
735 | |||
736 | RHDFUNC(rhdPtr); |
||
737 | |||
738 | if (!MC->Idle(MC)) { |
||
739 | xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, |
||
740 | "%s: Cannot setup MC: not idle!!!\n", __func__); |
||
741 | return FALSE; |
||
742 | } |
||
743 | |||
744 | OldAddress = MC->GetFBLocation(MC, &OldSize); |
||
745 | if (OldAddress == Address && OldSize == Size) |
||
746 | return TRUE; |
||
747 | |||
748 | /* If this ever occurs, we might have issues */ |
||
749 | if (OldAddress >> 32) |
||
750 | xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING, "%s: Board claims to use a " |
||
751 | "higher than 32bit address for its FB\n", __func__); |
||
752 | |||
753 | RHDDebug(rhdPtr->scrnIndex, |
||
754 | "Setting MC from 0x%08X to 0x%08X [Size 0x%08X]\n", |
||
755 | OldAddress, rhdPtr->FbIntAddress, Size); |
||
756 | |||
757 | MC->SetupFBLocation(MC, Address, Size); |
||
758 | |||
759 | return TRUE; |
||
760 | } |
||
761 | |||
762 | /* |
||
763 | * |
||
764 | */ |
||
765 | void |
||
766 | RHDMCTuneAccessForDisplay(RHDPtr rhdPtr, int Crtc, |
||
767 | DisplayModePtr Mode, DisplayModePtr ScaledToMode) |
||
768 | { |
||
769 | struct rhdMC *MC = rhdPtr->MC; |
||
770 | |||
771 | ASSERT(MC); |
||
772 | |||
773 | RHDFUNC(rhdPtr); |
||
774 | |||
775 | if (MC->TuneAccessForDisplay) |
||
776 | MC->TuneAccessForDisplay(MC, Crtc, Mode, ScaledToMode); |
||
777 | } |
||
778 | |||
779 | /* |
||
780 | * |
||
781 | */ |
||
782 | Bool |
||
783 | RHD_MC_IGP_SideportMemoryPresent(RHDPtr rhdPtr) |
||
784 | { |
||
785 | Bool Present = FALSE; |
||
786 | |||
787 | RHDFUNC(rhdPtr); |
||
788 | |||
789 | switch (rhdPtr->ChipSet) { |
||
790 | case RHD_RS690: |
||
791 | case RHD_RS740: |
||
792 | Present = (RHDReadMC(rhdPtr, RS69_MC_MISC_UMA_CNTL) & RS69_SIDE_PORT_PRESENT_R) != 0; |
||
793 | break; |
||
794 | case RHD_RS780: |
||
795 | Present = (RHDReadMC(rhdPtr, RS78_MC_MISC_UMA_CNTL) & RS78_SIDE_PORT_PRESENT_R) != 0; |
||
796 | break; |
||
797 | default: |
||
798 | break; |
||
799 | } |
||
800 | xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "IGP sideport memory %s present.\n", Present ? "" : "not"); |
||
801 | |||
802 | return Present; |
||
803 | }><>>=>>>><>><>><>><>><>><>><>><>><>><>><>><>><> |