xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/vip.c (revision 893988af824e65e49e55f517b157db8386e8002b)
1 /*
2 	Copyright (c) 2002-05, Thomas Kurschel
3 
4 
5 	Part of Radeon accelerant
6 
7 	Access to VIP
8 
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
12 	the lock with it)
13 */
14 
15 #include "radeon_driver.h"
16 #include "mmio.h"
17 #include "vip_regs.h"
18 #include "bios_regs.h"
19 #include "theatre_regs.h"
20 
21 
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);
25 
26 
27 // read data from VIP
28 // CP lock must be hold
29 static bool do_VIPRead(
30 	device_info *di, uint channel, uint address, uint32 *data )
31 {
32 	vuint8 *regs = di->regs;
33 
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 );
37 
38 	if( !Radeon_VIPWaitForIdle( di ))
39 		return false;
40 
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 );
46 
47 	// this read starts a register cycle; the returned value has no meaning
48 	INREG( regs, RADEON_VIPH_REG_DATA );
49 
50 	if( !Radeon_VIPWaitForIdle( di ))
51 		return false;
52 
53 	//Radeon_WaitForIdle( di, false, false );
54 
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 );
60 
61 	// get the data
62 	*data = INREG( regs, RADEON_VIPH_REG_DATA );
63 
64 	//SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, *data );
65 
66 	if( !Radeon_VIPWaitForIdle( di ))
67 		return false;
68 
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 );
74 
75 	return true;
76 }
77 
78 // public function: read data from VIP
79 bool Radeon_VIPRead(
80 	device_info *di, uint channel, uint address, uint32 *data, bool lock )
81 {
82 	bool res;
83 
84 	if( lock )
85 		ACQUIRE_BEN( di->si->cp.lock );
86 
87 	res = do_VIPRead( di, channel, address, data );
88 
89 	if( lock )
90 		RELEASE_BEN( di->si->cp.lock );
91 
92 //	SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
93 
94 	return res;
95 }
96 
97 static bool do_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer)
98 {
99    	vuint8 *regs = di->regs;
100 	uint32 status, tmp;
101 
102 	if(count!=1)
103 	{
104 		SHOW_FLOW0( 2, "Attempt to access VIP bus with non-stadard transaction length\n");
105 		return false;
106 	}
107 
108 	SHOW_FLOW( 2, "address=%lx, count=%ld ", address, count );
109 
110 	Radeon_WaitForFifo( di, 2);
111 	SHOW_FLOW0( 2, "1");
112 	OUTREG( regs, RADEON_VIPH_REG_ADDR,  (channel << 14) | address | 0x3000);
113 	SHOW_FLOW0( 2, "3");
114 	while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
115 	if(B_OK != status) return false;
116 
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
121 
122 	SHOW_FLOW0( 2, "4");
123 	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
124 	SHOW_FLOW0( 2, "5");
125 	OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
126 		INREG( regs, RADEON_VIPH_TIMEOUT_STAT) &
127 			(0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS) );
128 
129 	//	the value returned here is garbage.  The read merely initiates
130 	//	a register cycle
131 	SHOW_FLOW0( 2, "6");
132 	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
133 	INREG( regs, RADEON_VIPH_REG_DATA);
134 	SHOW_FLOW0( 2, "7");
135 	while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
136 	if(B_OK != status)  return false;
137 
138 	//	set VIPH_REGR_DIS so that the read won't take too long.
139 	SHOW_FLOW0( 2, "8");
140 	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
141 	SHOW_FLOW0( 2, "9");
142 	tmp = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
143 	OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
144 
145 	SHOW_FLOW0( 2, "10");
146 	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
147 	switch(count){
148 	   case 1:
149 	        *buffer=(uint8)(INREG( regs, RADEON_VIPH_REG_DATA) & 0xff);
150 	        break;
151 	   case 2:
152 	        *(uint16 *)buffer=(uint16) (INREG( regs, RADEON_VIPH_REG_DATA) & 0xffff);
153 	        break;
154 	   case 4:
155 	        *(uint32 *)buffer=(uint32) ( INREG( regs, RADEON_VIPH_REG_DATA) & 0xffffffff);
156 	        break;
157 	   }
158 	SHOW_FLOW0( 2, "11");
159 	while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
160 	if(B_OK != status) return false;
161 
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);
166 	return true;
167 
168 }
169 
170 bool Radeon_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
171 {
172 	bool res;
173 
174 	if( lock )
175 		ACQUIRE_BEN( di->si->cp.lock );
176 
177 	res = do_VIPFifoRead( di, channel, address, count, buffer );
178 
179 	if( lock )
180 		RELEASE_BEN( di->si->cp.lock );
181 
182 	//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
183 
184 	return res;
185 }
186 
187 // write data to VIP
188 // CP must be hold
189 static bool do_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data )
190 {
191 	vuint8 *regs = di->regs;
192 
193 	Radeon_WaitForFifo( di, 2 );
194 	OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | (address & ~0x2000) );
195 
196 	if( !Radeon_VIPWaitForIdle( di )) return false;
197 
198 	//SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, data );
199 
200 	Radeon_WaitForFifo( di, 2 );
201 	OUTREG( regs, RADEON_VIPH_REG_DATA, data );
202 
203 	return Radeon_VIPWaitForIdle( di );
204 
205 }
206 
207 // public function: write data to VIP
208 bool Radeon_VIPWrite(device_info *di, uint8 channel, uint address, uint32 data, bool lock )
209 {
210 	bool res;
211 
212 	//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
213 
214 	if( lock )
215 		ACQUIRE_BEN( di->si->cp.lock );
216 
217 	res = do_VIPWrite( di, channel, address, data );
218 
219 	if( lock )
220 		RELEASE_BEN( di->si->cp.lock );
221 
222 	return res;
223 }
224 
225 
226 static bool do_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer)
227 {
228 	vuint8 *regs = di->regs;
229 
230     uint32 status;
231 	uint32 i;
232 
233 	SHOW_FLOW( 2, "address=%lx, count=%ld, ", address, count );
234 
235     Radeon_WaitForFifo( di, 2 );
236     OUTREG( regs, RADEON_VIPH_REG_ADDR, ((channel << 14) | address | 0x1000) & ~0x2000 );
237    	SHOW_FLOW0( 2, "1");
238     while(B_BUSY == (status = RADEON_VIPFifoIdle( di, 0x0f)));
239 
240 
241     if(B_OK != status){
242 		SHOW_FLOW( 2 ,"cannot write %x to VIPH_REG_ADDR\n", (unsigned int)address);
243 		return false;
244 	}
245 
246     SHOW_FLOW0( 2, "2");
247 	for (i = 0; i < count; i+=4)
248 	{
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)));
253     	if(B_OK != status)
254 		{
255     		SHOW_FLOW0( 2 , "cannot write to VIPH_REG_DATA\n");
256 			return false;
257 	 	}
258 	}
259 
260     return true;
261 }
262 
263 bool Radeon_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
264 {
265     bool res;
266 
267 	//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
268 
269 	if( lock )
270 		ACQUIRE_BEN( di->si->cp.lock );
271 
272 	Radeon_VIPReset( di, false);
273 	res = do_VIPFifoWrite( di, channel, address, count, buffer );
274 
275 	if( lock )
276 		RELEASE_BEN( di->si->cp.lock );
277 
278 	return res;
279 }
280 
281 
282 // reset VIP
283 void Radeon_VIPReset(
284 	device_info *di, bool lock )
285 {
286 	vuint8 *regs = di->regs;
287 
288 	if( lock )
289 		ACQUIRE_BEN( di->si->cp.lock );
290 
291 	Radeon_WaitForFifo( di, 5 ); // Radeon_WaitForIdle( di, false, false );
292 	switch(di->asic){
293 	    case rt_r200:
294 	    case rt_rs200:
295 	    case rt_rv200:
296 	    case rt_rs100:
297 		case rt_rv100:
298 		case rt_r100:
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,
304 	    		0xff |
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));
311 	default:
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,
317 			    0xff |
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));
324 	    break;
325 
326 	}
327 
328 	if( lock )
329 		RELEASE_BEN( di->si->cp.lock );
330 }
331 
332 
333 // check whether VIP host is idle
334 // lock must be hold
335 static status_t Radeon_VIPIdle(
336 	device_info *di )
337 {
338 	vuint8 *regs = di->regs;
339 	uint32 timeout;
340 
341 	//Radeon_WaitForIdle( di, false, false );
342 
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 )
346 	{
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;
350 	}
351 	return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK;
352 }
353 
354 static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel)
355 {
356 	vuint8 *regs = di->regs;
357 	uint32 timeout;
358 
359 	timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
360 	if((timeout & 0x0000000f) & channel) /* lockup ?? */
361 	{
362 		OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (timeout & 0xfffffff0) | channel);
363 		return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR;
364 	}
365 	return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK ;
366 }
367 
368 
369 // wait until VIP host is idle
370 // lock must be hold
371 static bool Radeon_VIPWaitForIdle(
372 	device_info *di )
373 {
374 	int i;
375 
376 	// wait 100x 1ms before giving up
377 	for( i = 0; i < 100; ++i ) {
378 		status_t res;
379 
380 		res = Radeon_VIPIdle( di );
381 		if( res != B_BUSY ) {
382 			if( res == B_OK )
383 				return true;
384 			else
385 				return false;
386 		}
387 
388 		snooze( 1000 );
389 	}
390 
391 	return false;
392 }
393 
394 
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 )
400 {
401 	uint channel;
402 	uint32 cur_device_id;
403 
404 	// if card has no VIP port, let hardware detection fail;
405 	// in this case, noone will bother us again
406 	if( !di->has_vip ) {
407 		SHOW_FLOW0( 3, "This Device has no VIP Bus.");
408 		return -1;
409 	}
410 
411 	ACQUIRE_BEN( di->si->cp.lock );
412 
413 	Radeon_VIPReset( di, false );
414 
415 	// there are up to 4 devices, connected to one of 4 channels
416 	for( channel = 0; channel < 4; ++channel ) {
417 
418 		// read device id
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);
421 			continue;
422 		}
423 
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 );
428 			return channel;
429 		}
430 	}
431 
432 	RELEASE_BEN( di->si->cp.lock );
433 
434 	// couldn't find device
435 	return -1;
436 }
437