Subversion Repositories Kolibri OS

Rev

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
}