Subversion Repositories Kolibri OS

Rev

Rev 885 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
883 serge 1
#define RADEON_SCRATCH_REG0     0x15e0
2
#define RADEON_SCRATCH_REG1		0x15e4
3
#define RADEON_SCRATCH_REG2		0x15e8
4
#define RADEON_SCRATCH_REG3		0x15ec
5
#define RADEON_SCRATCH_REG4		0x15f0
6
#define RADEON_SCRATCH_REG5		0x15f4
7
#define RADEON_SCRATCH_UMSK		0x0770
8
#define RADEON_SCRATCH_ADDR		0x0774
9
 
10
#   define RS400_BUS_MASTER_DIS      (1 << 14)
11
//#   define RADEON_BUS_MASTER_DIS     (1 <<  6)
12
 
13
#define RADEON_ISYNC_CNTL       0x1724
14
#	define RADEON_ISYNC_ANY2D_IDLE3D	(1 << 0)
15
#	define RADEON_ISYNC_ANY3D_IDLE2D	(1 << 1)
16
#	define RADEON_ISYNC_TRIG2D_IDLE3D	(1 << 2)
17
#	define RADEON_ISYNC_TRIG3D_IDLE2D	(1 << 3)
18
#	define RADEON_ISYNC_WAIT_IDLEGUI	(1 << 4)
19
#	define RADEON_ISYNC_CPSCRATCH_IDLEGUI	(1 << 5)
20
 
21
 
22
#define RADEON_IDLE_RETRY      16 /* Fall out of idle loops after this count */
1002 serge 23
#define RADEON_TIMEOUT    4000000 /* Fall out of wait loops after this count */
883 serge 24
 
25
 
26
 
27
void RADEONEngineFlush(RHDPtr info)
28
{
29
     int i;
30
 
31
     if (info->ChipFamily <= CHIP_FAMILY_RV280)
32
     {
33
        MASKREG(RADEON_RB3D_DSTCACHE_CTLSTAT,RADEON_RB3D_DC_FLUSH_ALL,
34
                                             ~RADEON_RB3D_DC_FLUSH_ALL);
35
        for (i = 0; i < RADEON_TIMEOUT; i++) {
36
           if (!(INREG(RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY))
37
            break;
38
        }
39
        if (i == RADEON_TIMEOUT) {
40
           dbgprintf("DC flush timeout: %x\n",
41
                     (u32_t)INREG(RADEON_RB3D_DSTCACHE_CTLSTAT));
42
        }
43
     }
44
     else
45
     {
46
//        MASKREG(R300_DSTCACHE_CTLSTAT,R300_RB2D_DC_FLUSH_ALL,
47
//                                      ~R300_RB2D_DC_FLUSH_ALL);
48
//        for (i = 0; i < RADEON_TIMEOUT; i++) {
49
//            if (!(INREG(R300_DSTCACHE_CTLSTAT) & R300_RB2D_DC_BUSY))
50
//            break;
51
//        }
52
//        if (i == RADEON_TIMEOUT) {
53
//           dbgprintf("DC flush timeout: %x\n",
54
//                     (u32_t)INREG(R300_DSTCACHE_CTLSTAT));
55
//        }
56
     }
57
}
58
 
59
static Bool R5xxFIFOWaitLocal(u32_t required)             //R100-R500
60
{
61
     int i;
62
 
63
     for (i = 0; i < RADEON_TIMEOUT; i++)
64
        if (required <= (INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK))
65
           return TRUE;
66
 
67
     dbgprintf("%s: Timeout 0x%08X.\n", __func__, (u32_t) INREG(RADEON_RBBM_STATUS));
68
     return FALSE;
69
}
70
 
71
static int radeon_do_wait_for_idle()
72
{
73
	int i, ret;
74
 
75
    ret = R5xxFIFOWaitLocal(64);
76
	if (ret)
77
		return ret;
78
 
79
    for (i = 0; i < RADEON_TIMEOUT; i++)
80
    {
81
        if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) {
82
            RADEONEngineFlush(&rhd);
83
			return 0;
84
		}
85
        usleep(1);
86
	}
87
    dbgprintf("wait idle failed status : 0x%08X 0x%08X\n",
88
               INREG(RADEON_RBBM_STATUS),
89
               INREG(R300_VAP_CNTL_STATUS));
90
 
91
    return 1;
92
}
93
 
94
 
95
 
96
/* ================================================================
97
 * CP control, initialization
98
 */
99
 
100
/* Load the microcode for the CP */
101
 
102
#include "radeon_microcode.h"
103
 
104
static void load_microcode(RHDPtr info)
105
{
106
	int i;
107
    const u32_t (*microcode)[2];
108
 
109
     OUTREG(RADEON_CP_ME_RAM_ADDR, 0);
110
 
111
     if ( (info->ChipFamily  == CHIP_FAMILY_LEGACY ) ||
112
          (info->ChipFamily  == CHIP_FAMILY_RADEON ) ||
113
          (info->ChipFamily  == CHIP_FAMILY_RV100  ) ||
114
          (info->ChipFamily  == CHIP_FAMILY_RV200  ) ||
115
          (info->ChipFamily  == CHIP_FAMILY_RS100  ) ||
116
          (info->ChipFamily  == CHIP_FAMILY_RS200  ))
117
     {
118
        microcode = R100_cp_microcode;
119
        dbgprintf("Loading R100 Microcode\n");
120
     }
121
     else if ((info->ChipFamily == CHIP_FAMILY_R200 ) ||
122
              (info->ChipFamily == CHIP_FAMILY_RV250) ||
123
              (info->ChipFamily == CHIP_FAMILY_RV280) ||
124
              (info->ChipFamily == CHIP_FAMILY_RS300))
125
     {
126
        microcode = R200_cp_microcode;
127
        dbgprintf("Loading R200 Microcode\n");
128
     }
129
     else if ((info->ChipFamily == CHIP_FAMILY_R300)  ||
130
              (info->ChipFamily == CHIP_FAMILY_R350)  ||
131
              (info->ChipFamily == CHIP_FAMILY_RV350) ||
132
              (info->ChipFamily == CHIP_FAMILY_RV380) ||
133
              (info->ChipFamily == CHIP_FAMILY_RS400) ||
134
              (info->ChipFamily == CHIP_FAMILY_RS480))
135
     {
136
        dbgprintf("Loading R300 Microcode\n");
137
        microcode = R300_cp_microcode;
138
     }
139
     else if ((info->ChipFamily == CHIP_FAMILY_R420)  ||
140
              (info->ChipFamily == CHIP_FAMILY_RV410))
141
     {
142
        dbgprintf("Loading R400 Microcode\n");
143
        microcode = R420_cp_microcode;
144
 
145
     }
146
     else if ((info->ChipFamily == CHIP_FAMILY_RS600) ||
147
              (info->ChipFamily == CHIP_FAMILY_RS690) ||
148
              (info->ChipFamily == CHIP_FAMILY_RS740))
149
     {
150
        dbgprintf("Loading RS690/RS740 Microcode\n");
151
        microcode = RS690_cp_microcode;
152
     }
153
     else if ((info->ChipFamily == CHIP_FAMILY_RV515) ||
154
              (info->ChipFamily == CHIP_FAMILY_R520)  ||
155
              (info->ChipFamily == CHIP_FAMILY_RV530) ||
156
              (info->ChipFamily == CHIP_FAMILY_R580)  ||
157
              (info->ChipFamily == CHIP_FAMILY_RV560) ||
158
              (info->ChipFamily == CHIP_FAMILY_RV570))
159
     {
160
        dbgprintf("Loading R500 Microcode\n");
161
        microcode = R520_cp_microcode;
162
     }
163
 
164
     for (i = 0; i < 256; i++) {
165
       OUTREG(RADEON_CP_ME_RAM_DATAH, microcode[i][1]);
166
       OUTREG(RADEON_CP_ME_RAM_DATAL, microcode[i][0]);
167
     }
168
}
169
 
170
 
171
void init_ring_buffer(RHDPtr info)
172
{
173
     u32_t ring_base;
174
     u32_t tmp;
175
 
176
     info->ringBase = CreateRingBuffer( 64*1024, PG_SW);
177
 
178
     dbgprintf("create cp ring buffer %x\n", rhd.ringBase);
179
     ring_base = GetPgAddr(rhd.ringBase);
180
     dbgprintf("ring base %x\n", ring_base);
181
 
182
     OUTREG(RADEON_CP_RB_BASE, ring_base);
183
 
184
     info->ring_avail = 64*1024/4 ;
185
 
186
	/* Set the write pointer delay */
187
     OUTREG(RADEON_CP_RB_WPTR_DELAY, 0);
188
 
189
	/* Initialize the ring buffer's read and write pointers */
190
     rhd.ring_rp = rhd.ring_wp = INREG(RADEON_CP_RB_RPTR);
191
     rhd.host_rp =  rhd.ring_rp;
192
 
193
     OUTREG(RADEON_CP_RB_WPTR,rhd.ring_rp);
194
 
885 serge 195
     tmp = (((u32_t)&rhd.host_rp) & 4095) + GetPgAddr((void*)&rhd.host_rp);
883 serge 196
 
197
     OUTREG(RADEON_CP_RB_RPTR_ADDR, tmp); // ring buffer read pointer
198
 
199
	/* Set ring buffer size */
200
     OUTREG(RADEON_CP_RB_CNTL, (1<<27)|(0<<18)|(10<<8)|13);
201
 
202
	/* Initialize the scratch register pointer.  This will cause
203
	 * the scratch register values to be written out to memory
204
	 * whenever they are updated.
205
	 *
206
	 * We simply put this behind the ring read pointer, this works
207
	 * with PCI GART as well as (whatever kind of) AGP GART
208
	 */
209
 
885 serge 210
     tmp = (((u32_t)&rhd.scratch0) & 4095) + GetPgAddr((void*)&rhd.scratch0);
883 serge 211
     OUTREG(RADEON_SCRATCH_ADDR, tmp);
212
 
213
     OUTREG(RADEON_SCRATCH_UMSK, 0x0);
214
     //OUTREG(0x778, 1);
215
 
216
	/* Turn on bus mastering */
217
     if ( (info->ChipFamily == CHIP_FAMILY_RS400) ||
218
          (info->ChipFamily == CHIP_FAMILY_RS690) ||
219
          (info->ChipFamily == CHIP_FAMILY_RS740) )
220
     {
221
		/* rs400, rs690/rs740 */
222
        tmp = INREG(RADEON_BUS_CNTL) & ~RS400_BUS_MASTER_DIS;
223
        OUTREG(RADEON_BUS_CNTL, tmp);
224
     }
225
     else if (!((info->ChipFamily == CHIP_FAMILY_RV380) ||
226
                (info->ChipFamily >= CHIP_FAMILY_R420)))
227
     {
228
		/* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */
229
        tmp = INREG(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
230
        OUTREG(RADEON_BUS_CNTL, tmp);
231
	} /* PCIE cards appears to not need this */
232
 
233
    tmp = INREG(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;
234
    OUTREG(RADEON_BUS_CNTL, tmp);
235
 
236
    radeon_do_wait_for_idle();
237
 
238
	/* Sync everything up */
239
    OUTREG(RADEON_ISYNC_CNTL,
240
          (RADEON_ISYNC_ANY2D_IDLE3D |
241
           RADEON_ISYNC_ANY3D_IDLE2D |
242
           RADEON_ISYNC_WAIT_IDLEGUI |
243
           RADEON_ISYNC_CPSCRATCH_IDLEGUI));
244
}
245
 
246
 
247
void radeon_engine_reset(RHDPtr info)
248
{
1002 serge 249
    u32_t  clock_cntl_index;
250
    u32_t  mclk_cntl;
251
    u32_t  rbbm_soft_reset;
252
    u32_t  host_path_cntl;
883 serge 253
 
254
    if (info->ChipFamily <= CHIP_FAMILY_RV410)
255
    {
256
	        /* may need something similar for newer chips */
257
        clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
258
        mclk_cntl = INPLL( RADEON_MCLK_CNTL);
259
 
260
        OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl |
261
						    RADEON_FORCEON_MCLKA |
262
						    RADEON_FORCEON_MCLKB |
263
						    RADEON_FORCEON_YCLKA |
264
						    RADEON_FORCEON_YCLKB |
265
						    RADEON_FORCEON_MC |
266
						    RADEON_FORCEON_AIC));
267
	}
268
 
269
    rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);
270
 
271
    OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
272
					      RADEON_SOFT_RESET_CP |
273
					      RADEON_SOFT_RESET_HI |
274
					      RADEON_SOFT_RESET_SE |
275
					      RADEON_SOFT_RESET_RE |
276
					      RADEON_SOFT_RESET_PP |
277
					      RADEON_SOFT_RESET_E2 |
278
					      RADEON_SOFT_RESET_RB));
279
    INREG(RADEON_RBBM_SOFT_RESET);
280
    OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &
281
					      ~(RADEON_SOFT_RESET_CP |
282
						RADEON_SOFT_RESET_HI |
283
						RADEON_SOFT_RESET_SE |
284
						RADEON_SOFT_RESET_RE |
285
						RADEON_SOFT_RESET_PP |
286
						RADEON_SOFT_RESET_E2 |
287
						RADEON_SOFT_RESET_RB)));
288
    INREG(RADEON_RBBM_SOFT_RESET);
289
 
290
    if (info->ChipFamily <= CHIP_FAMILY_RV410) {
291
        OUTPLL(RADEON_MCLK_CNTL, mclk_cntl);
292
        OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
293
        OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
294
	}
295
 };
296
 
297
#define RADEON_WAIT_UNTIL_IDLE() do {                   \
298
    OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 1 ) );         \
299
	OUT_RING( (RADEON_WAIT_2D_IDLECLEAN |				\
300
		   RADEON_WAIT_3D_IDLECLEAN |				\
301
		   RADEON_WAIT_HOST_IDLECLEAN) );			\
302
} while (0)
303
 
304
#define R300_ZB_ZCACHE_CTLSTAT                  0x4f18
305
#   define RADEON_RB3D_ZC_FLUSH     (1 << 0)
306
#	define RADEON_RB3D_ZC_FREE		(1 << 2)
307
#	define RADEON_RB3D_ZC_FLUSH_ALL		0x5
308
#   define RADEON_RB3D_ZC_BUSY      (1 << 31)
309
#   define R300_ZC_FLUSH                (1 << 0)
310
#	define R300_ZC_FREE		        (1 << 1)
311
#   define R300_ZC_BUSY             (1 << 31)
312
#   define RADEON_RB3D_DC_FLUSH     (3 << 0)
313
#	define RADEON_RB3D_DC_FREE		(3 << 2)
314
#	define RADEON_RB3D_DC_FLUSH_ALL		0xf
315
#   define RADEON_RB3D_DC_BUSY      (1 << 31)
316
#   define R300_RB3D_DC_FLUSH       (2 << 0)
317
#	define R300_RB3D_DC_FREE		(2 << 2)
318
#
319
#define RADEON_PURGE_CACHE() do {                                    \
320
    if ( rhd.ChipFamily <= CHIP_FAMILY_RV280) {                      \
321
            OUT_RING(CP_PACKET0( RADEON_RB3D_DSTCACHE_CTLSTAT, 1));  \
322
            OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE);    \
323
    } else {                                                         \
324
            OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 1));     \
325
            OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE );       \
326
        }                                                            \
327
} while (0)
328
 
329
#define RADEON_FLUSH_ZCACHE() do {                                   \
330
    if ( rhd.ChipFamily <= CHIP_FAMILY_RV280) {     \
331
            OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 1 ) ); \
332
            OUT_RING( RADEON_RB3D_ZC_FLUSH );                        \
333
    } else {                                                         \
334
            OUT_RING( CP_PACKET0( R300_ZB_ZCACHE_CTLSTAT, 1 ) );     \
335
            OUT_RING( R300_ZC_FLUSH );                               \
336
        }                                                            \
337
} while (0)
338
#define RADEON_PURGE_ZCACHE() do {                  \
339
    if (rhd.ChipFamily <= CHIP_FAMILY_RV280) { \
340
            OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 1));    \
341
	        OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE);	\
342
	} else {                                                        \
343
            OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 1));    \
344
	        OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE);			\
345
        }                                                               \
346
} while (0)
347
 
348
static int radeon_cp_start(RHDPtr info)
349
{
350
     u32_t *ring, write;
351
     u32_t ifl;
352
     radeon_do_wait_for_idle(64);
353
 
354
     OUTREG(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM);
355
 
356
     ifl = safe_cli();
357
 
358
     BEGIN_RING(8);
359
	/* isync can only be written through cp on r5xx write it here */
360
       OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 1));
361
       OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D |
362
                RADEON_ISYNC_ANY3D_IDLE2D |
363
                RADEON_ISYNC_WAIT_IDLEGUI |
364
                RADEON_ISYNC_CPSCRATCH_IDLEGUI);
365
       RADEON_PURGE_CACHE();
366
       RADEON_PURGE_ZCACHE();
367
       RADEON_WAIT_UNTIL_IDLE();
368
       ADVANCE_RING();
369
    COMMIT_RING();
370
 
371
    safe_sti(ifl);
372
 
373
    radeon_do_wait_for_idle();
374
};
375
 
376
 
377
Bool init_cp(RHDPtr info)
378
{
379
     load_microcode(&rhd);
380
 
381
     init_ring_buffer(&rhd);
382
 
383
     radeon_engine_reset(&rhd);
384
 
385
    /* setup the raster pipes */
386
     init_pipes(&rhd);
387
 
388
     rhd.ring_rp = rhd.ring_wp = INREG(RADEON_CP_RB_RPTR);
389
     OUTREG(RADEON_CP_RB_WPTR, rhd.ring_rp);
390
 
391
     radeon_cp_start(&rhd);
392
 
1002 serge 393
    return TRUE;
883 serge 394
};
395
 
396