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=%" B_PRIx32 ", count=%" B_PRIu32 " ",
109		address, count );
110
111	Radeon_WaitForFifo( di, 2);
112	SHOW_FLOW0( 2, "1");
113	OUTREG( regs, RADEON_VIPH_REG_ADDR,  (channel << 14) | address | 0x3000);
114	SHOW_FLOW0( 2, "3");
115	while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
116	if(B_OK != status) return false;
117
118	//	disable VIPH_REGR_DIS to enable VIP cycle.
119	//	The LSB of VIPH_TIMEOUT_STAT are set to 0
120	//	because 1 would have acknowledged various VIP
121	//	interrupts unexpectedly
122
123	SHOW_FLOW0( 2, "4");
124	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
125	SHOW_FLOW0( 2, "5");
126	OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
127		INREG( regs, RADEON_VIPH_TIMEOUT_STAT) &
128			(0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS) );
129
130	//	the value returned here is garbage.  The read merely initiates
131	//	a register cycle
132	SHOW_FLOW0( 2, "6");
133	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
134	INREG( regs, RADEON_VIPH_REG_DATA);
135	SHOW_FLOW0( 2, "7");
136	while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
137	if(B_OK != status)  return false;
138
139	//	set VIPH_REGR_DIS so that the read won't take too long.
140	SHOW_FLOW0( 2, "8");
141	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
142	SHOW_FLOW0( 2, "9");
143	tmp = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
144	OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
145
146	SHOW_FLOW0( 2, "10");
147	Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
148	switch(count){
149	   case 1:
150	        *buffer=(uint8)(INREG( regs, RADEON_VIPH_REG_DATA) & 0xff);
151	        break;
152	   case 2:
153	        *(uint16 *)buffer=(uint16) (INREG( regs, RADEON_VIPH_REG_DATA) & 0xffff);
154	        break;
155	   case 4:
156	        *(uint32 *)buffer=(uint32) ( INREG( regs, RADEON_VIPH_REG_DATA) & 0xffffffff);
157	        break;
158	   }
159	SHOW_FLOW0( 2, "11");
160	while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
161	if(B_OK != status) return false;
162
163	// so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles.
164	SHOW_FLOW0( 2, "12");
165	OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
166		(INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
167	return true;
168
169}
170
171bool Radeon_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
172{
173	bool res;
174
175	if( lock )
176		ACQUIRE_BEN( di->si->cp.lock );
177
178	res = do_VIPFifoRead( di, channel, address, count, buffer );
179
180	if( lock )
181		RELEASE_BEN( di->si->cp.lock );
182
183	//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
184
185	return res;
186}
187
188// write data to VIP
189// CP must be hold
190static bool do_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data )
191{
192	vuint8 *regs = di->regs;
193
194	Radeon_WaitForFifo( di, 2 );
195	OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | (address & ~0x2000) );
196
197	if( !Radeon_VIPWaitForIdle( di )) return false;
198
199	//SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, data );
200
201	Radeon_WaitForFifo( di, 2 );
202	OUTREG( regs, RADEON_VIPH_REG_DATA, data );
203
204	return Radeon_VIPWaitForIdle( di );
205
206}
207
208// public function: write data to VIP
209bool Radeon_VIPWrite(device_info *di, uint8 channel, uint address, uint32 data, bool lock )
210{
211	bool res;
212
213	//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
214
215	if( lock )
216		ACQUIRE_BEN( di->si->cp.lock );
217
218	res = do_VIPWrite( di, channel, address, data );
219
220	if( lock )
221		RELEASE_BEN( di->si->cp.lock );
222
223	return res;
224}
225
226
227static bool do_VIPFifoWrite(device_info *di, uint8 channel, uint32 address,
228	uint32 count, uint8 *buffer)
229{
230	vuint8 *regs = di->regs;
231
232	uint32 status;
233	uint32 i;
234
235	SHOW_FLOW( 2, "address=%" B_PRIx32 ", count=%" B_PRIu32 ", ",
236		address, count );
237
238	Radeon_WaitForFifo( di, 2 );
239	OUTREG( regs, RADEON_VIPH_REG_ADDR,
240		((channel << 14) | address | 0x1000) & ~0x2000 );
241	SHOW_FLOW0( 2, "1");
242	do {
243		status = RADEON_VIPFifoIdle(di, 0x0f);
244	} while (status == B_BUSY);
245
246	if(B_OK != status){
247		SHOW_FLOW( 2 ,"cannot write %x to VIPH_REG_ADDR\n",
248			(unsigned int)address);
249		return false;
250	}
251
252	SHOW_FLOW0( 2, "2");
253	for (i = 0; i < count; i+=4)
254	{
255		Radeon_WaitForFifo( di, 2);
256		SHOW_FLOW( 2, "count %" B_PRIu32, count);
257		OUTREG( regs, RADEON_VIPH_REG_DATA, *(uint32*)(buffer + i));
258
259		do {
260			status = RADEON_VIPFifoIdle(di, 0x0f);
261		} while (status == B_BUSY);
262
263    	if(B_OK != status)
264		{
265    		SHOW_FLOW0( 2 , "cannot write to VIPH_REG_DATA\n");
266			return false;
267		}
268	}
269
270	return true;
271}
272
273bool Radeon_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
274{
275    bool res;
276
277	//SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
278
279	if( lock )
280		ACQUIRE_BEN( di->si->cp.lock );
281
282	Radeon_VIPReset( di, false);
283	res = do_VIPFifoWrite( di, channel, address, count, buffer );
284
285	if( lock )
286		RELEASE_BEN( di->si->cp.lock );
287
288	return res;
289}
290
291
292// reset VIP
293void Radeon_VIPReset(
294	device_info *di, bool lock )
295{
296	vuint8 *regs = di->regs;
297
298	if( lock )
299		ACQUIRE_BEN( di->si->cp.lock );
300
301	Radeon_WaitForFifo( di, 5 ); // Radeon_WaitForIdle( di, false, false );
302	switch(di->asic){
303	    case rt_r200:
304	    case rt_rs200:
305	    case rt_rv200:
306	    case rt_rs100:
307		case rt_rv100:
308		case rt_r100:
309	    OUTREG( regs, RADEON_VIPH_CONTROL, 4 | 	(15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) |
310			RADEON_VIPH_CONTROL_VIPH_DMA_MODE |	RADEON_VIPH_CONTROL_VIPH_EN ); // slowest, timeout in 16 phases
311	    OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) |
312	    	RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
313	    OUTREG( regs, RADEON_VIPH_DV_LAT,
314	    		0xff |
315				(4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) |
316				(4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) |
317				(4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) |
318				(4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT)); // set timeslice
319	    OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x151);
320	    OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN));
321	default:
322		    OUTREG( regs, RADEON_VIPH_CONTROL, 9 | 	(15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) |
323				RADEON_VIPH_CONTROL_VIPH_DMA_MODE |	RADEON_VIPH_CONTROL_VIPH_EN ); // slowest, timeout in 16 phases
324	    OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) |
325		    	RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
326	    OUTREG( regs, RADEON_VIPH_DV_LAT,
327			    0xff |
328				(4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) |
329				(4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) |
330				(4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) |
331				(4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT)); // set timeslice
332	    OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x0);
333	    OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN));
334	    break;
335
336	}
337
338	if( lock )
339		RELEASE_BEN( di->si->cp.lock );
340}
341
342
343// check whether VIP host is idle
344// lock must be hold
345static status_t Radeon_VIPIdle(
346	device_info *di )
347{
348	vuint8 *regs = di->regs;
349	uint32 timeout;
350
351	//Radeon_WaitForIdle( di, false, false );
352
353	// if there is a stuck transaction, acknowledge that
354	timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT );
355	if( (timeout & RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_STAT) != 0 )
356	{
357		OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
358			(timeout & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK);
359		return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR;
360	}
361	return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK;
362}
363
364static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel)
365{
366	vuint8 *regs = di->regs;
367	uint32 timeout;
368
369	timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
370	if((timeout & 0x0000000f) & channel) /* lockup ?? */
371	{
372		OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (timeout & 0xfffffff0) | channel);
373		return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR;
374	}
375	return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK ;
376}
377
378
379// wait until VIP host is idle
380// lock must be hold
381static bool Radeon_VIPWaitForIdle(
382	device_info *di )
383{
384	int i;
385
386	// wait 100x 1ms before giving up
387	for( i = 0; i < 100; ++i ) {
388		status_t res;
389
390		res = Radeon_VIPIdle( di );
391		if( res != B_BUSY ) {
392			if( res == B_OK )
393				return true;
394			else
395				return false;
396		}
397
398		snooze( 1000 );
399	}
400
401	return false;
402}
403
404
405// find VIP channel of a device
406// return:	>= 0 channel of device
407//			< 0 no device found
408int Radeon_FindVIPDevice(
409	device_info *di, uint32 device_id )
410{
411	uint channel;
412	uint32 cur_device_id;
413
414	// if card has no VIP port, let hardware detection fail;
415	// in this case, noone will bother us again
416	if( !di->has_vip ) {
417		SHOW_FLOW0( 3, "This Device has no VIP Bus.");
418		return -1;
419	}
420
421	ACQUIRE_BEN( di->si->cp.lock );
422
423	Radeon_VIPReset( di, false );
424
425	// there are up to 4 devices, connected to one of 4 channels
426	for( channel = 0; channel < 4; ++channel ) {
427
428		// read device id
429		if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id, false ))	{
430			SHOW_FLOW( 3, "No device found on channel %d", channel);
431			continue;
432		}
433
434		// compare device id directly
435		if( cur_device_id == device_id ) {
436			SHOW_FLOW( 3, "Device %08" B_PRIx32 " found on channel %d",
437				device_id, channel);
438			RELEASE_BEN( di->si->cp.lock );
439			return channel;
440		}
441	}
442
443	RELEASE_BEN( di->si->cp.lock );
444
445	// couldn't find device
446	return -1;
447}
448