radeon_vip.c revision 68105dcb
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <string.h>
6
7#include "radeon.h"
8#include "radeon_reg.h"
9#include "radeon_macros.h"
10#include "radeon_probe.h"
11#include <X11/extensions/Xv.h>
12#include "radeon_video.h"
13
14#include "xf86.h"
15#include "atipciids.h"
16
17#include "generic_bus.h"
18#include "theatre_reg.h"
19
20#define VIP_NAME      "RADEON VIP BUS"
21#define VIP_TYPE      "ATI VIP BUS"
22
23/* Status defines */
24#define VIP_BUSY  0
25#define VIP_IDLE  1
26#define VIP_RESET 2
27
28static Bool RADEONVIP_ioctl(GENERIC_BUS_Ptr b, long ioctl, long arg1, char *arg2)
29{
30    long count;
31    switch(ioctl){
32        case GB_IOCTL_GET_NAME:
33                  count=strlen(VIP_NAME)+1;
34                  if(count>arg1)return FALSE;
35                  memcpy(arg2,VIP_NAME,count);
36                  return TRUE;
37
38        case GB_IOCTL_GET_TYPE:
39                  count=strlen(VIP_TYPE)+1;
40                  if(count>arg1)return FALSE;
41                  memcpy(arg2,VIP_TYPE,count);
42                  return TRUE;
43
44        default:
45                  return FALSE;
46    }
47}
48
49static uint32_t RADEONVIP_idle(GENERIC_BUS_Ptr b)
50{
51   ScrnInfoPtr pScrn = b->pScrn;
52   RADEONInfoPtr info = RADEONPTR(pScrn);
53   unsigned char *RADEONMMIO = info->MMIO;
54
55   uint32_t timeout;
56
57   RADEONWaitForIdleMMIO(pScrn);
58   timeout = INREG(RADEON_VIPH_TIMEOUT_STAT);
59   if(timeout & RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT) /* lockup ?? */
60   {
61       RADEONWaitForFifo(pScrn, 2);
62       OUTREG(RADEON_VIPH_TIMEOUT_STAT, (timeout & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK);
63       RADEONWaitForIdleMMIO(pScrn);
64       return (INREG(RADEON_VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_RESET;
65   }
66   RADEONWaitForIdleMMIO(pScrn);
67   return (INREG(RADEON_VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_IDLE ;
68}
69
70static uint32_t RADEONVIP_fifo_idle(GENERIC_BUS_Ptr b, uint8_t channel)
71{
72   ScrnInfoPtr pScrn = b->pScrn;
73   RADEONInfoPtr info = RADEONPTR(pScrn);
74   unsigned char *RADEONMMIO = info->MMIO;
75
76   uint32_t timeout;
77
78   RADEONWaitForIdleMMIO(pScrn);
79   timeout = INREG(VIPH_TIMEOUT_STAT);
80   if((timeout & 0x0000000f) & channel) /* lockup ?? */
81   {
82       xf86DrvMsg(b->pScrn->scrnIndex, X_INFO, "RADEON_fifo_idle\n");
83       RADEONWaitForFifo(pScrn, 2);
84       OUTREG(VIPH_TIMEOUT_STAT, (timeout & 0xfffffff0) | channel);
85       RADEONWaitForIdleMMIO(pScrn);
86       return (INREG(VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_RESET;
87   }
88   RADEONWaitForIdleMMIO(pScrn);
89   return (INREG(VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_IDLE ;
90}
91
92/* address format:
93     ((device & 0x3)<<14)   | (fifo << 12) | (addr)
94*/
95
96#define VIP_WAIT_FOR_IDLE() {			\
97    int i2ctries = 0;				\
98    while (i2ctries < 10) {			\
99      status = RADEONVIP_idle(b);		\
100      if (status==VIP_BUSY)			\
101      {						\
102	usleep(1000);				\
103	i2ctries++;				\
104      } else break;				\
105    }						\
106  }
107
108static Bool RADEONVIP_read(GENERIC_BUS_Ptr b, uint32_t address, uint32_t count, uint8_t *buffer)
109{
110   ScrnInfoPtr pScrn = b->pScrn;
111   RADEONInfoPtr info = RADEONPTR(pScrn);
112   unsigned char *RADEONMMIO = info->MMIO;
113   uint32_t status,tmp;
114
115   if((count!=1) && (count!=2) && (count!=4))
116   {
117   xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Attempt to access VIP bus with non-stadard transaction length\n");
118   return FALSE;
119   }
120
121   RADEONWaitForFifo(pScrn, 2);
122   OUTREG(RADEON_VIPH_REG_ADDR, address | 0x2000);
123   write_mem_barrier();
124   VIP_WAIT_FOR_IDLE();
125   if(VIP_IDLE != status) return FALSE;
126
127/*
128         disable RADEON_VIPH_REGR_DIS to enable VIP cycle.
129         The LSB of RADEON_VIPH_TIMEOUT_STAT are set to 0
130         because 1 would have acknowledged various VIP
131         interrupts unexpectedly
132*/
133   RADEONWaitForIdleMMIO(pScrn);
134   OUTREG(RADEON_VIPH_TIMEOUT_STAT, INREG(RADEON_VIPH_TIMEOUT_STAT) & (0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS) );
135   write_mem_barrier();
136/*
137         the value returned here is garbage.  The read merely initiates
138         a register cycle
139*/
140    RADEONWaitForIdleMMIO(pScrn);
141    INREG(RADEON_VIPH_REG_DATA);
142
143    VIP_WAIT_FOR_IDLE();
144    if(VIP_IDLE != status) return FALSE;
145/*
146        set RADEON_VIPH_REGR_DIS so that the read won't take too long.
147*/
148    RADEONWaitForIdleMMIO(pScrn);
149    tmp=INREG(RADEON_VIPH_TIMEOUT_STAT);
150    OUTREG(RADEON_VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
151    write_mem_barrier();
152    RADEONWaitForIdleMMIO(pScrn);
153    switch(count){
154        case 1:
155             *buffer=(uint8_t)(INREG(RADEON_VIPH_REG_DATA) & 0xff);
156             break;
157        case 2:
158             *(uint16_t *)buffer=(uint16_t) (INREG(RADEON_VIPH_REG_DATA) & 0xffff);
159             break;
160        case 4:
161             *(uint32_t *)buffer=(uint32_t) ( INREG(RADEON_VIPH_REG_DATA) & 0xffffffff);
162             break;
163        }
164     VIP_WAIT_FOR_IDLE();
165     if(VIP_IDLE != status) return FALSE;
166 /*
167 so that reading RADEON_VIPH_REG_DATA would not trigger unnecessary vip cycles.
168*/
169     OUTREG(RADEON_VIPH_TIMEOUT_STAT, (INREG(RADEON_VIPH_TIMEOUT_STAT) & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
170     write_mem_barrier();
171     return TRUE;
172}
173
174static Bool RADEONVIP_fifo_read(GENERIC_BUS_Ptr b, uint32_t address, uint32_t count, uint8_t *buffer)
175{
176   ScrnInfoPtr pScrn = b->pScrn;
177   RADEONInfoPtr info = RADEONPTR(pScrn);
178   unsigned char *RADEONMMIO = info->MMIO;
179   uint32_t status,tmp;
180
181   if(count!=1)
182   {
183   xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Attempt to access VIP bus with non-stadard transaction length\n");
184   return FALSE;
185   }
186
187   RADEONWaitForFifo(pScrn, 2);
188   OUTREG(VIPH_REG_ADDR, address | 0x3000);
189   write_mem_barrier();
190   while(VIP_BUSY == (status = RADEONVIP_fifo_idle(b, 0xff)));
191   if(VIP_IDLE != status) return FALSE;
192
193/*
194         disable VIPH_REGR_DIS to enable VIP cycle.
195         The LSB of VIPH_TIMEOUT_STAT are set to 0
196         because 1 would have acknowledged various VIP
197         interrupts unexpectedly
198*/
199
200   RADEONWaitForIdleMMIO(pScrn);
201   OUTREG(VIPH_TIMEOUT_STAT, INREG(VIPH_TIMEOUT_STAT) & (0xffffff00 & ~VIPH_TIMEOUT_STAT__VIPH_REGR_DIS) );
202   write_mem_barrier();
203
204/*
205         the value returned here is garbage.  The read merely initiates
206         a register cycle
207*/
208    RADEONWaitForIdleMMIO(pScrn);
209    INREG(VIPH_REG_DATA);
210
211    while(VIP_BUSY == (status = RADEONVIP_fifo_idle(b, 0xff)));
212    if(VIP_IDLE != status) return FALSE;
213
214/*
215        set VIPH_REGR_DIS so that the read won't take too long.
216*/
217    RADEONWaitForIdleMMIO(pScrn);
218    tmp=INREG(VIPH_TIMEOUT_STAT);
219    OUTREG(VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
220    write_mem_barrier();
221
222    RADEONWaitForIdleMMIO(pScrn);
223    switch(count){
224        case 1:
225             *buffer=(uint8_t)(INREG(VIPH_REG_DATA) & 0xff);
226             break;
227        case 2:
228             *(uint16_t *)buffer=(uint16_t) (INREG(VIPH_REG_DATA) & 0xffff);
229             break;
230        case 4:
231             *(uint32_t *)buffer=(uint32_t) ( INREG(VIPH_REG_DATA) & 0xffffffff);
232             break;
233        }
234     while(VIP_BUSY == (status = RADEONVIP_fifo_idle(b, 0xff)));
235     if(VIP_IDLE != status) return FALSE;
236
237 /*
238 so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles.
239*/
240     OUTREG(VIPH_TIMEOUT_STAT, (INREG(VIPH_TIMEOUT_STAT) & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
241     write_mem_barrier();
242     return TRUE;
243
244
245}
246
247
248static Bool RADEONVIP_write(GENERIC_BUS_Ptr b, uint32_t address, uint32_t count, uint8_t *buffer)
249{
250    ScrnInfoPtr pScrn = b->pScrn;
251    RADEONInfoPtr info = RADEONPTR(pScrn);
252    unsigned char *RADEONMMIO = info->MMIO;
253
254    uint32_t status;
255
256
257    if((count!=4))
258    {
259    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Attempt to access VIP bus with non-stadard transaction length\n");
260    return FALSE;
261    }
262
263    RADEONWaitForFifo(pScrn, 2);
264    OUTREG(RADEON_VIPH_REG_ADDR, address & (~0x2000));
265    while(VIP_BUSY == (status = RADEONVIP_idle(b)));
266
267    if(VIP_IDLE != status) return FALSE;
268
269    RADEONWaitForFifo(pScrn, 2);
270    switch(count){
271        case 4:
272             OUTREG(RADEON_VIPH_REG_DATA, *(uint32_t *)buffer);
273             break;
274        }
275    write_mem_barrier();
276    while(VIP_BUSY == (status = RADEONVIP_idle(b)));
277    if(VIP_IDLE != status) return FALSE;
278    return TRUE;
279}
280
281static Bool RADEONVIP_fifo_write(GENERIC_BUS_Ptr b, uint32_t address, uint32_t count, uint8_t *buffer)
282{
283    ScrnInfoPtr pScrn = b->pScrn;
284    RADEONInfoPtr info = RADEONPTR(pScrn);
285    unsigned char *RADEONMMIO = info->MMIO;
286
287    uint32_t status;
288	uint32_t i;
289
290    RADEONWaitForFifo(pScrn, 2);
291    OUTREG(VIPH_REG_ADDR, (address & (~0x2000)) | 0x1000);
292    while(VIP_BUSY == (status = RADEONVIP_fifo_idle(b, 0x0f)));
293
294
295    if(VIP_IDLE != status){
296		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "cannot write %x to VIPH_REG_ADDR\n", (unsigned int)address);
297		return FALSE;
298	}
299
300	RADEONWaitForFifo(pScrn, 2);
301	for (i = 0; i < count; i+=4)
302	{
303		OUTREG(VIPH_REG_DATA, *(uint32_t*)(buffer + i));
304    	write_mem_barrier();
305		while(VIP_BUSY == (status = RADEONVIP_fifo_idle(b, 0x0f)));
306    	if(VIP_IDLE != status)
307		{
308    		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "cannot write to VIPH_REG_DATA\n");
309			return FALSE;
310	 	}
311	}
312
313    return TRUE;
314}
315
316void RADEONVIP_reset(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
317{
318    RADEONInfoPtr info = RADEONPTR(pScrn);
319    unsigned char *RADEONMMIO = info->MMIO;
320
321
322    RADEONWaitForIdleMMIO(pScrn);
323    switch(info->ChipFamily){
324		case CHIP_FAMILY_RV250:
325		case CHIP_FAMILY_RV350:
326		case CHIP_FAMILY_R350:
327		case CHIP_FAMILY_R300:
328	    OUTREG(RADEON_VIPH_CONTROL, 0x003F0009); /* slowest, timeout in 16 phases */
329	    OUTREG(RADEON_VIPH_TIMEOUT_STAT, (INREG(RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
330	    OUTREG(RADEON_VIPH_DV_LAT, 0x444400FF); /* set timeslice */
331	    OUTREG(RADEON_VIPH_BM_CHUNK, 0x0);
332	    OUTREG(RADEON_TEST_DEBUG_CNTL, INREG(RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN));
333	    break;
334		case CHIP_FAMILY_RV380:
335	    OUTREG(RADEON_VIPH_CONTROL, 0x003F000D); /* slowest, timeout in 16 phases */
336	    OUTREG(RADEON_VIPH_TIMEOUT_STAT, (INREG(RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
337	    OUTREG(RADEON_VIPH_DV_LAT, 0x444400FF); /* set timeslice */
338	    OUTREG(RADEON_VIPH_BM_CHUNK, 0x0);
339	    OUTREG(RADEON_TEST_DEBUG_CNTL, INREG(RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN));
340	    break;
341	default:
342	    OUTREG(RADEON_VIPH_CONTROL, 0x003F0004); /* slowest, timeout in 16 phases */
343	    OUTREG(RADEON_VIPH_TIMEOUT_STAT, (INREG(RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
344	    OUTREG(RADEON_VIPH_DV_LAT, 0x444400FF); /* set timeslice */
345	    OUTREG(RADEON_VIPH_BM_CHUNK, 0x151);
346	    OUTREG(RADEON_TEST_DEBUG_CNTL, INREG(RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN));
347	}
348}
349
350void RADEONVIP_init(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
351{
352    pPriv->VIP=calloc(1,sizeof(GENERIC_BUS_Rec));
353    pPriv->VIP->pScrn=pScrn;
354    pPriv->VIP->DriverPrivate.ptr=pPriv;
355    pPriv->VIP->ioctl=RADEONVIP_ioctl;
356    pPriv->VIP->read=RADEONVIP_read;
357    pPriv->VIP->write=RADEONVIP_write;
358    pPriv->VIP->fifo_read=RADEONVIP_fifo_read;
359    pPriv->VIP->fifo_write=RADEONVIP_fifo_write;
360
361    RADEONVIP_reset(pScrn, pPriv);
362}
363