2 Copyright (c) 2002-05, Thomas Kurschel
5 Part of Radeon accelerant
9 This code must be in kernel because we need for FIFO to become empty
10 during VIP access (which in turn requires locking the card, and locking
11 is a dangerous thing in user mode as the app can suddenly die, taking
15 #include "radeon_driver.h"
18 #include "bios_regs.h"
19 #include "theatre_regs.h"
22 // moved to bottom to avoid inlining
23 static bool Radeon_VIPWaitForIdle( device_info
*di
);
24 static status_t
RADEON_VIPFifoIdle(device_info
*di
, uint8 channel
);
28 // CP lock must be hold
29 static bool do_VIPRead(
30 device_info
*di
, uint channel
, uint address
, uint32
*data
)
32 vuint8
*regs
= di
->regs
;
34 Radeon_WaitForFifo( di
, 2 );
35 // the 0x2000 is the nameless "register-read" flag
36 OUTREG( regs
, RADEON_VIPH_REG_ADDR
, (channel
<< 14) | address
| 0x2000 );
38 if( !Radeon_VIPWaitForIdle( di
))
41 // enable VIP register cycle reads
42 Radeon_WaitForFifo( di
, 2 );
43 OUTREGP( regs
, RADEON_VIPH_TIMEOUT_STAT
, 0,
44 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK
& ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
);
45 //Radeon_WaitForIdle( di, false, false );
47 // this read starts a register cycle; the returned value has no meaning
48 INREG( regs
, RADEON_VIPH_REG_DATA
);
50 if( !Radeon_VIPWaitForIdle( di
))
53 //Radeon_WaitForIdle( di, false, false );
55 // register cycle is done, so disable any further cycle
56 Radeon_WaitForFifo( di
, 2 );
57 OUTREGP( regs
, RADEON_VIPH_TIMEOUT_STAT
, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
,
58 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK
& ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
);
59 //Radeon_WaitForIdle( di, false, false );
62 *data
= INREG( regs
, RADEON_VIPH_REG_DATA
);
64 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, *data );
66 if( !Radeon_VIPWaitForIdle( di
))
69 // disable register cycle again (according to sample code)
70 // IMHO, this is not necessary as it has been done before
71 Radeon_WaitForFifo( di
, 2 );
72 OUTREGP( regs
, RADEON_VIPH_TIMEOUT_STAT
, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
,
73 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK
& ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
);
78 // public function: read data from VIP
80 device_info
*di
, uint channel
, uint address
, uint32
*data
, bool lock
)
85 ACQUIRE_BEN( di
->si
->cp
.lock
);
87 res
= do_VIPRead( di
, channel
, address
, data
);
90 RELEASE_BEN( di
->si
->cp
.lock
);
92 // SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
97 static bool do_VIPFifoRead(device_info
*di
, uint8 channel
, uint32 address
, uint32 count
, uint8
*buffer
)
99 vuint8
*regs
= di
->regs
;
104 SHOW_FLOW0( 2, "Attempt to access VIP bus with non-stadard transaction length\n");
108 SHOW_FLOW( 2, "address=%lx, count=%ld ", address
, count
);
110 Radeon_WaitForFifo( di
, 2);
112 OUTREG( regs
, RADEON_VIPH_REG_ADDR
, (channel
<< 14) | address
| 0x3000);
114 while(B_BUSY
== (status
= RADEON_VIPFifoIdle( di
, 0xff)));
115 if(B_OK
!= status
) return false;
117 // disable VIPH_REGR_DIS to enable VIP cycle.
118 // The LSB of VIPH_TIMEOUT_STAT are set to 0
119 // because 1 would have acknowledged various VIP
120 // interrupts unexpectedly
123 Radeon_WaitForFifo( di
, 2 ); // Radeon_WaitForIdle( di, false, false );
125 OUTREG( regs
, RADEON_VIPH_TIMEOUT_STAT
,
126 INREG( regs
, RADEON_VIPH_TIMEOUT_STAT
) &
127 (0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
) );
129 // the value returned here is garbage. The read merely initiates
132 Radeon_WaitForFifo( di
, 2 ); // Radeon_WaitForIdle( di, false, false );
133 INREG( regs
, RADEON_VIPH_REG_DATA
);
135 while(B_BUSY
== (status
= RADEON_VIPFifoIdle( di
, 0xff)));
136 if(B_OK
!= status
) return false;
138 // set VIPH_REGR_DIS so that the read won't take too long.
140 Radeon_WaitForFifo( di
, 2 ); // Radeon_WaitForIdle( di, false, false );
142 tmp
= INREG( regs
, RADEON_VIPH_TIMEOUT_STAT
);
143 OUTREG( regs
, RADEON_VIPH_TIMEOUT_STAT
, (tmp
& 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
);
145 SHOW_FLOW0( 2, "10");
146 Radeon_WaitForFifo( di
, 2 ); // Radeon_WaitForIdle( di, false, false );
149 *buffer
=(uint8
)(INREG( regs
, RADEON_VIPH_REG_DATA
) & 0xff);
152 *(uint16
*)buffer
=(uint16
) (INREG( regs
, RADEON_VIPH_REG_DATA
) & 0xffff);
155 *(uint32
*)buffer
=(uint32
) ( INREG( regs
, RADEON_VIPH_REG_DATA
) & 0xffffffff);
158 SHOW_FLOW0( 2, "11");
159 while(B_BUSY
== (status
= RADEON_VIPFifoIdle( di
, 0xff)));
160 if(B_OK
!= status
) return false;
162 // so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles.
163 SHOW_FLOW0( 2, "12");
164 OUTREG( regs
, RADEON_VIPH_TIMEOUT_STAT
,
165 (INREG( regs
, RADEON_VIPH_TIMEOUT_STAT
) & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
);
170 bool Radeon_VIPFifoRead(device_info
*di
, uint8 channel
, uint32 address
, uint32 count
, uint8
*buffer
, bool lock
)
175 ACQUIRE_BEN( di
->si
->cp
.lock
);
177 res
= do_VIPFifoRead( di
, channel
, address
, count
, buffer
);
180 RELEASE_BEN( di
->si
->cp
.lock
);
182 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
189 static bool do_VIPWrite( device_info
*di
, uint8 channel
, uint address
, uint32 data
)
191 vuint8
*regs
= di
->regs
;
193 Radeon_WaitForFifo( di
, 2 );
194 OUTREG( regs
, RADEON_VIPH_REG_ADDR
, (channel
<< 14) | (address
& ~0x2000) );
196 if( !Radeon_VIPWaitForIdle( di
)) return false;
198 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, data );
200 Radeon_WaitForFifo( di
, 2 );
201 OUTREG( regs
, RADEON_VIPH_REG_DATA
, data
);
203 return Radeon_VIPWaitForIdle( di
);
207 // public function: write data to VIP
208 bool Radeon_VIPWrite(device_info
*di
, uint8 channel
, uint address
, uint32 data
, bool lock
)
212 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
215 ACQUIRE_BEN( di
->si
->cp
.lock
);
217 res
= do_VIPWrite( di
, channel
, address
, data
);
220 RELEASE_BEN( di
->si
->cp
.lock
);
226 static bool do_VIPFifoWrite(device_info
*di
, uint8 channel
, uint32 address
, uint32 count
, uint8
*buffer
)
228 vuint8
*regs
= di
->regs
;
233 SHOW_FLOW( 2, "address=%lx, count=%ld, ", address
, count
);
235 Radeon_WaitForFifo( di
, 2 );
236 OUTREG( regs
, RADEON_VIPH_REG_ADDR
, ((channel
<< 14) | address
| 0x1000) & ~0x2000 );
238 while(B_BUSY
== (status
= RADEON_VIPFifoIdle( di
, 0x0f)));
242 SHOW_FLOW( 2 ,"cannot write %x to VIPH_REG_ADDR\n", (unsigned int)address
);
247 for (i
= 0; i
< count
; i
+=4)
249 Radeon_WaitForFifo( di
, 2);
250 SHOW_FLOW( 2, "count %ld", count
);
251 OUTREG( regs
, RADEON_VIPH_REG_DATA
, *(uint32
*)(buffer
+ i
));
252 while(B_BUSY
== (status
= RADEON_VIPFifoIdle( di
, 0x0f)));
255 SHOW_FLOW0( 2 , "cannot write to VIPH_REG_DATA\n");
263 bool Radeon_VIPFifoWrite(device_info
*di
, uint8 channel
, uint32 address
, uint32 count
, uint8
*buffer
, bool lock
)
267 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
270 ACQUIRE_BEN( di
->si
->cp
.lock
);
272 Radeon_VIPReset( di
, false);
273 res
= do_VIPFifoWrite( di
, channel
, address
, count
, buffer
);
276 RELEASE_BEN( di
->si
->cp
.lock
);
283 void Radeon_VIPReset(
284 device_info
*di
, bool lock
)
286 vuint8
*regs
= di
->regs
;
289 ACQUIRE_BEN( di
->si
->cp
.lock
);
291 Radeon_WaitForFifo( di
, 5 ); // Radeon_WaitForIdle( di, false, false );
299 OUTREG( regs
, RADEON_VIPH_CONTROL
, 4 | (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT
) |
300 RADEON_VIPH_CONTROL_VIPH_DMA_MODE
| RADEON_VIPH_CONTROL_VIPH_EN
); // slowest, timeout in 16 phases
301 OUTREG( regs
, RADEON_VIPH_TIMEOUT_STAT
, (INREG( regs
, RADEON_VIPH_TIMEOUT_STAT
) & 0xFFFFFF00) |
302 RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
);
303 OUTREG( regs
, RADEON_VIPH_DV_LAT
,
305 (4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT
) |
306 (4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT
) |
307 (4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT
) |
308 (4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT
)); // set timeslice
309 OUTREG( regs
, RADEON_VIPH_DMA_CHUNK
, 0x151);
310 OUTREG( regs
, RADEON_TEST_DEBUG_CNTL
, INREG( regs
, RADEON_TEST_DEBUG_CNTL
) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN
));
312 OUTREG( regs
, RADEON_VIPH_CONTROL
, 9 | (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT
) |
313 RADEON_VIPH_CONTROL_VIPH_DMA_MODE
| RADEON_VIPH_CONTROL_VIPH_EN
); // slowest, timeout in 16 phases
314 OUTREG( regs
, RADEON_VIPH_TIMEOUT_STAT
, (INREG( regs
, RADEON_VIPH_TIMEOUT_STAT
) & 0xFFFFFF00) |
315 RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS
);
316 OUTREG( regs
, RADEON_VIPH_DV_LAT
,
318 (4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT
) |
319 (4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT
) |
320 (4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT
) |
321 (4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT
)); // set timeslice
322 OUTREG( regs
, RADEON_VIPH_DMA_CHUNK
, 0x0);
323 OUTREG( regs
, RADEON_TEST_DEBUG_CNTL
, INREG( regs
, RADEON_TEST_DEBUG_CNTL
) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN
));
329 RELEASE_BEN( di
->si
->cp
.lock
);
333 // check whether VIP host is idle
335 static status_t
Radeon_VIPIdle(
338 vuint8
*regs
= di
->regs
;
341 //Radeon_WaitForIdle( di, false, false );
343 // if there is a stuck transaction, acknowledge that
344 timeout
= INREG( regs
, RADEON_VIPH_TIMEOUT_STAT
);
345 if( (timeout
& RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_STAT
) != 0 )
347 OUTREG( regs
, RADEON_VIPH_TIMEOUT_STAT
,
348 (timeout
& 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK
);
349 return (INREG( regs
, RADEON_VIPH_CONTROL
) & 0x2000) ? B_BUSY
: B_ERROR
;
351 return (INREG( regs
, RADEON_VIPH_CONTROL
) & 0x2000) ? B_BUSY
: B_OK
;
354 static status_t
RADEON_VIPFifoIdle(device_info
*di
, uint8 channel
)
356 vuint8
*regs
= di
->regs
;
359 timeout
= INREG( regs
, RADEON_VIPH_TIMEOUT_STAT
);
360 if((timeout
& 0x0000000f) & channel
) /* lockup ?? */
362 OUTREG( regs
, RADEON_VIPH_TIMEOUT_STAT
, (timeout
& 0xfffffff0) | channel
);
363 return (INREG( regs
, RADEON_VIPH_CONTROL
) & 0x2000) ? B_BUSY
: B_ERROR
;
365 return (INREG( regs
, RADEON_VIPH_CONTROL
) & 0x2000) ? B_BUSY
: B_OK
;
369 // wait until VIP host is idle
371 static bool Radeon_VIPWaitForIdle(
376 // wait 100x 1ms before giving up
377 for( i
= 0; i
< 100; ++i
) {
380 res
= Radeon_VIPIdle( di
);
381 if( res
!= B_BUSY
) {
395 // find VIP channel of a device
396 // return: >= 0 channel of device
397 // < 0 no device found
398 int Radeon_FindVIPDevice(
399 device_info
*di
, uint32 device_id
)
402 uint32 cur_device_id
;
404 // if card has no VIP port, let hardware detection fail;
405 // in this case, noone will bother us again
407 SHOW_FLOW0( 3, "This Device has no VIP Bus.");
411 ACQUIRE_BEN( di
->si
->cp
.lock
);
413 Radeon_VIPReset( di
, false );
415 // there are up to 4 devices, connected to one of 4 channels
416 for( channel
= 0; channel
< 4; ++channel
) {
419 if( !Radeon_VIPRead( di
, channel
, RADEON_VIP_VENDOR_DEVICE_ID
, &cur_device_id
, false )) {
420 SHOW_FLOW( 3, "No device found on channel %d", channel
);
424 // compare device id directly
425 if( cur_device_id
== device_id
) {
426 SHOW_FLOW( 3, "Device %08lx found on channel %d", device_id
, channel
);
427 RELEASE_BEN( di
->si
->cp
.lock
);
432 RELEASE_BEN( di
->si
->cp
.lock
);
434 // couldn't find device