summaryrefslogtreecommitdiff
path: root/src/radeon_vip.c
diff options
context:
space:
mode:
authorVladimir Dergachev <volodya@mindspring.com>2004-10-02 20:55:42 +0000
committerVladimir Dergachev <volodya@mindspring.com>2004-10-02 20:55:42 +0000
commit6c1996174b9f7afc8f4e33c35e4864b31696d4d6 (patch)
treedc6d8a4bc89a7fe8f14d617fb509bfa53b360c25 /src/radeon_vip.c
parent136649a1c2065624a9cf17386054c6595aa6d85e (diff)
Modified:
xc/programs/Xserver/hw/xfree86/drivers/ati/Imakefile xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.[c,h] xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_vip.c Add VIP bus access code, hook it into initialization system.
Diffstat (limited to 'src/radeon_vip.c')
-rw-r--r--src/radeon_vip.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/src/radeon_vip.c b/src/radeon_vip.c
new file mode 100644
index 0000000..d1ac15f
--- /dev/null
+++ b/src/radeon_vip.c
@@ -0,0 +1,200 @@
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_reg.h"
+#include "Xv.h"
+#include "radeon_video.h"
+
+#include "xf86.h"
+#include "xf86PciInfo.h"
+
+#include "generic_bus.h"
+
+#define VIP_NAME "RADEON VIP BUS"
+#define VIP_TYPE "ATI VIP BUS"
+
+/* Status defines */
+#define VIP_BUSY 0
+#define VIP_IDLE 1
+#define VIP_RESET 2
+
+static Bool RADEONVIP_ioctl(GENERIC_BUS_Ptr b, long ioctl, long arg1, char *arg2)
+{
+ long count;
+ switch(ioctl){
+ case GB_IOCTL_GET_NAME:
+ count=strlen(VIP_NAME)+1;
+ if(count>arg1)return FALSE;
+ memcpy(arg2,VIP_NAME,count);
+ return TRUE;
+
+ case GB_IOCTL_GET_TYPE:
+ count=strlen(VIP_TYPE)+1;
+ if(count>arg1)return FALSE;
+ memcpy(arg2,VIP_TYPE,count);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static CARD32 RADEONVIP_idle(GENERIC_BUS_Ptr b)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ CARD32 timeout;
+
+ RADEONWaitForIdleMMIO(pScrn);
+ timeout = INREG(RADEON_VIPH_TIMEOUT_STAT);
+ if(timeout & RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT) /* lockup ?? */
+ {
+ RADEONWaitForFifo(pScrn, 2);
+ OUTREG(RADEON_VIPH_TIMEOUT_STAT, (timeout & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK);
+ RADEONWaitForIdleMMIO(pScrn);
+ return (INREG(RADEON_VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_RESET;
+ }
+ RADEONWaitForIdleMMIO(pScrn);
+ return (INREG(RADEON_VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_IDLE ;
+}
+
+/* address format:
+ ((device & 0x3)<<14) | (fifo << 12) | (addr)
+*/
+
+static Bool RADEONVIP_read(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD8 *buffer)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 status,tmp;
+
+ if((count!=1) && (count!=2) && (count!=4))
+ {
+ xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Attempt to access VIP bus with non-stadard transaction length\n");
+ return FALSE;
+ }
+
+ RADEONWaitForFifo(pScrn, 2);
+ OUTREG(RADEON_VIPH_REG_ADDR, address | 0x2000);
+ write_mem_barrier();
+ while(VIP_BUSY == (status = RADEONVIP_idle(b)));
+ if(VIP_IDLE != status) return FALSE;
+
+/*
+ disable RADEON_VIPH_REGR_DIS to enable VIP cycle.
+ The LSB of RADEON_VIPH_TIMEOUT_STAT are set to 0
+ because 1 would have acknowledged various VIP
+ interrupts unexpectedly
+*/
+ RADEONWaitForIdleMMIO(pScrn);
+ OUTREG(RADEON_VIPH_TIMEOUT_STAT, INREG(RADEON_VIPH_TIMEOUT_STAT) & (0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS) );
+ write_mem_barrier();
+/*
+ the value returned here is garbage. The read merely initiates
+ a register cycle
+*/
+ RADEONWaitForIdleMMIO(pScrn);
+ INREG(RADEON_VIPH_REG_DATA);
+
+ while(VIP_BUSY == (status = RADEONVIP_idle(b)));
+ if(VIP_IDLE != status) return FALSE;
+/*
+ set RADEON_VIPH_REGR_DIS so that the read won't take too long.
+*/
+ RADEONWaitForIdleMMIO(pScrn);
+ tmp=INREG(RADEON_VIPH_TIMEOUT_STAT);
+ OUTREG(RADEON_VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
+ write_mem_barrier();
+ RADEONWaitForIdleMMIO(pScrn);
+ switch(count){
+ case 1:
+ *buffer=(CARD8)(INREG(RADEON_VIPH_REG_DATA) & 0xff);
+ break;
+ case 2:
+ *(CARD16 *)buffer=(CARD16) (INREG(RADEON_VIPH_REG_DATA) & 0xffff);
+ break;
+ case 4:
+ *(CARD32 *)buffer=(CARD32) ( INREG(RADEON_VIPH_REG_DATA) & 0xffffffff);
+ break;
+ }
+ while(VIP_BUSY == (status = RADEONVIP_idle(b)));
+ if(VIP_IDLE != status) return FALSE;
+ /*
+ so that reading RADEON_VIPH_REG_DATA would not trigger unnecessary vip cycles.
+*/
+ OUTREG(RADEON_VIPH_TIMEOUT_STAT, (INREG(RADEON_VIPH_TIMEOUT_STAT) & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
+ write_mem_barrier();
+ return TRUE;
+}
+
+static Bool RADEONVIP_write(GENERIC_BUS_Ptr b, CARD32 address, CARD32 count, CARD8 *buffer)
+{
+ ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ CARD32 status;
+
+
+ if((count!=4))
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Attempt to access VIP bus with non-stadard transaction length\n");
+ return FALSE;
+ }
+
+ RADEONWaitForFifo(pScrn, 2);
+ OUTREG(RADEON_VIPH_REG_ADDR, address & (~0x2000));
+ while(VIP_BUSY == (status = RADEONVIP_idle(b)));
+
+ if(VIP_IDLE != status) return FALSE;
+
+ RADEONWaitForFifo(pScrn, 2);
+ switch(count){
+ case 4:
+ OUTREG(RADEON_VIPH_REG_DATA, *(CARD32 *)buffer);
+ break;
+ }
+ write_mem_barrier();
+ while(VIP_BUSY == (status = RADEONVIP_idle(b)));
+ if(VIP_IDLE != status) return FALSE;
+ return TRUE;
+}
+
+void RADEONVIP_reset(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+
+ RADEONWaitForIdleMMIO(pScrn);
+ switch(info->ChipFamily){
+ case CHIP_FAMILY_RV250:
+ OUTREG(RADEON_VIPH_CONTROL, 0x003F0009); /* slowest, timeout in 16 phases */
+ OUTREG(RADEON_VIPH_TIMEOUT_STAT, (INREG(RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
+ OUTREG(RADEON_VIPH_DV_LAT, 0x444400FF); /* set timeslice */
+ OUTREG(RADEON_VIPH_BM_CHUNK, 0x0);
+ OUTREG(RADEON_TEST_DEBUG_CNTL, INREG(RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN));
+ break;
+ default:
+ OUTREG(RADEON_VIPH_CONTROL, 0x003F0004); /* slowest, timeout in 16 phases */
+ OUTREG(RADEON_VIPH_TIMEOUT_STAT, (INREG(RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) | RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS);
+ OUTREG(RADEON_VIPH_DV_LAT, 0x444400FF); /* set timeslice */
+ OUTREG(RADEON_VIPH_BM_CHUNK, 0x151);
+ OUTREG(RADEON_TEST_DEBUG_CNTL, INREG(RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN));
+ }
+}
+
+void RADEONVIP_init(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
+{
+ pPriv->VIP=xcalloc(1,sizeof(GENERIC_BUS_Rec));
+ pPriv->VIP->scrnIndex=pScrn->scrnIndex;
+ pPriv->VIP->DriverPrivate.ptr=pPriv;
+ pPriv->VIP->ioctl=RADEONVIP_ioctl;
+ pPriv->VIP->read=RADEONVIP_read;
+ pPriv->VIP->write=RADEONVIP_write;
+
+ RADEONVIP_reset(pScrn, pPriv);
+}