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
23static bool Radeon_VIPWaitForIdle( device_info *di );
24static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel);
25
26
27// read data from VIP
28// CP lock must be hold
29static 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
79bool 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
97static 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
170bool 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
189static 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
208bool 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
226static 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
263bool 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
283void 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
335static 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
354static 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
371static 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
398int 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