diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/radeon_reg.h | 33 | ||||
-rw-r--r-- | src/radeon_video.c | 3 | ||||
-rw-r--r-- | src/radeon_video.h | 10 | ||||
-rw-r--r-- | src/radeon_vip.c | 200 | ||||
-rw-r--r-- | src/theatre_reg.h | 35 |
5 files changed, 244 insertions, 37 deletions
diff --git a/src/radeon_reg.h b/src/radeon_reg.h index c53d173f..6e2a4431 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -1277,6 +1277,8 @@ #define RADEON_SW_SEMAPHORE 0x013c #define RADEON_TEST_DEBUG_CNTL 0x0120 +#define RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN 0x00000001 + #define RADEON_TEST_DEBUG_MUX 0x0124 #define RADEON_TEST_DEBUG_OUT 0x012c #define RADEON_TMDS_PLL_CNTL 0x02a8 @@ -1304,7 +1306,36 @@ #define RADEON_VGA_DDA_ON_OFF 0x02ec #define RADEON_VID_BUFFER_CONTROL 0x0900 #define RADEON_VIDEOMUX_CNTL 0x0190 -#define RADEON_VIPH_CONTROL 0x0c40 /* ? */ + + /* VIP bus */ +#define RADEON_VIPH_CH0_DATA 0x0c00 +#define RADEON_VIPH_CH1_DATA 0x0c04 +#define RADEON_VIPH_CH2_DATA 0x0c08 +#define RADEON_VIPH_CH3_DATA 0x0c0c +#define RADEON_VIPH_CH0_ADDR 0x0c10 +#define RADEON_VIPH_CH1_ADDR 0x0c14 +#define RADEON_VIPH_CH2_ADDR 0x0c18 +#define RADEON_VIPH_CH3_ADDR 0x0c1c +#define RADEON_VIPH_CH0_SBCNT 0x0c20 +#define RADEON_VIPH_CH1_SBCNT 0x0c24 +#define RADEON_VIPH_CH2_SBCNT 0x0c28 +#define RADEON_VIPH_CH3_SBCNT 0x0c2c +#define RADEON_VIPH_CH0_ABCNT 0x0c30 +#define RADEON_VIPH_CH1_ABCNT 0x0c34 +#define RADEON_VIPH_CH2_ABCNT 0x0c38 +#define RADEON_VIPH_CH3_ABCNT 0x0c3c +#define RADEON_VIPH_CONTROL 0x0c40 +#define RADEON_VIPH_DV_LAT 0x0c44 +#define RADEON_VIPH_BM_CHUNK 0x0c48 +#define RADEON_VIPH_DV_INT 0x0c4c +#define RADEON_VIPH_TIMEOUT_STAT 0x0c50 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK 0x00000010 +#define RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000 + +#define RADEON_VIPH_REG_DATA 0x0084 +#define RADEON_VIPH_REG_ADDR 0x0080 + #define RADEON_WAIT_UNTIL 0x1720 # define RADEON_WAIT_CRTC_PFLIP (1 << 0) diff --git a/src/radeon_video.c b/src/radeon_video.c index d079c898..4512e472 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -895,6 +895,9 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) /* Initialize I2C bus */ RADEONInitI2C(pScrn, pPriv); if(pPriv->i2c != NULL)RADEON_board_setmisc(pPriv); + + /* Initialize VIP bus */ + RADEONVIP_init(pScrn, pPriv); #if 0 /* this is just here for easy debugging - normally off */ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Scanning I2C Bus\n"); diff --git a/src/radeon_video.h b/src/radeon_video.h index 24016851..781b54c2 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -7,6 +7,8 @@ #include "tda9885.h" #include "i2c_def.h" +#include "generic_bus.h" + /* Xvideo port struct */ typedef struct { CARD32 transform_index; @@ -32,7 +34,10 @@ typedef struct { CARD8 tuner_type; MSP3430Ptr msp3430; TDA9885Ptr tda9885; - + + /* VIP bus and devices */ + GENERIC_BUS_Ptr VIP; + Bool video_stream_active; int encoding; CARD32 frequency; @@ -73,5 +78,8 @@ typedef struct { void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); void RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); +void RADEONVIP_init(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); +void RADEONVIP_reset(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv); + #endif diff --git a/src/radeon_vip.c b/src/radeon_vip.c new file mode 100644 index 00000000..d1ac15f2 --- /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); +} diff --git a/src/theatre_reg.h b/src/theatre_reg.h index cb1f92bd..8a8a1624 100644 --- a/src/theatre_reg.h +++ b/src/theatre_reg.h @@ -2,31 +2,6 @@ #define __THEATRE_REGS_H__ -#define VIPH_CH0_DATA 0x0c00 -#define VIPH_CH1_DATA 0x0c04 -#define VIPH_CH2_DATA 0x0c08 -#define VIPH_CH3_DATA 0x0c0c -#define VIPH_CH0_ADDR 0x0c10 -#define VIPH_CH1_ADDR 0x0c14 -#define VIPH_CH2_ADDR 0x0c18 -#define VIPH_CH3_ADDR 0x0c1c -#define VIPH_CH0_SBCNT 0x0c20 -#define VIPH_CH1_SBCNT 0x0c24 -#define VIPH_CH2_SBCNT 0x0c28 -#define VIPH_CH3_SBCNT 0x0c2c -#define VIPH_CH0_ABCNT 0x0c30 -#define VIPH_CH1_ABCNT 0x0c34 -#define VIPH_CH2_ABCNT 0x0c38 -#define VIPH_CH3_ABCNT 0x0c3c -#define VIPH_CONTROL 0x0c40 -#define VIPH_DV_LAT 0x0c44 -#define VIPH_BM_CHUNK 0x0c48 -#define VIPH_DV_INT 0x0c4c -#define VIPH_TIMEOUT_STAT 0x0c50 - -#define VIPH_REG_DATA 0x0084 -#define VIPH_REG_ADDR 0x0080 - /* Address Space Rage Theatre Registers (VIP Access) */ #define VIP_VIP_VENDOR_DEVICE_ID 0x0000 #define VIP_VIP_SUB_VENDOR_DEVICE_ID 0x0004 @@ -219,16 +194,6 @@ #define VIP_SPDIF_TX_CNT_REG 0x0820 #define VIP_IIS_TX_CNT_REG 0x0824 -/* Status defines */ -#define VIP_BUSY 0 -#define VIP_IDLE 1 -#define VIP_RESET 2 - -#define VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010 -#define VIPH_TIMEOUT_STAT__VIPH_REG_AK 0x00000010 -#define VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000 -#define TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN 0x00000001 - #define RT100_ATI_ID 0x4D541002 #define RT200_ATI_ID 0x4f4a1002 |