diff options
author | Vladimir Dergachev <volodya@mindspring.com> | 2004-10-02 20:55:42 +0000 |
---|---|---|
committer | Vladimir Dergachev <volodya@mindspring.com> | 2004-10-02 20:55:42 +0000 |
commit | 6c1996174b9f7afc8f4e33c35e4864b31696d4d6 (patch) | |
tree | dc6d8a4bc89a7fe8f14d617fb509bfa53b360c25 /src/radeon_vip.c | |
parent | 136649a1c2065624a9cf17386054c6595aa6d85e (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.c | 200 |
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); +} |