From a2b944cef66aa0ce0b741641ab08241bf43242b1 Mon Sep 17 00:00:00 2001 From: nick Date: Mon, 1 Oct 2001 18:15:25 +0000 Subject: Rage theatre detection git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@2038 b3059339-0415-0410-9bf9-f77b7e298cf2 --- drivers/radeon/radeon.h | 6 ++ drivers/radeon/radeonfb.c | 190 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 2 deletions(-) diff --git a/drivers/radeon/radeon.h b/drivers/radeon/radeon.h index 68506fb251..bb29c7316d 100644 --- a/drivers/radeon/radeon.h +++ b/drivers/radeon/radeon.h @@ -268,6 +268,8 @@ #define ISYNC_CNTL 0x1724 #define RBBM_GUICNTL 0x172C #define RBBM_STATUS 0x0E40 +# define RBBM_FIFOCNT_MASK 0x007f +# define RBBM_ACTIVE (1 << 31) #define RBBM_STATUS_alt_1 0x1740 #define RBBM_CNTL 0x00EC #define RBBM_CNTL_alt_1 0x0E44 @@ -484,6 +486,7 @@ #define AUX_WINDOW_VERT_CNTL 0x02DC #define DDA_CONFIG 0x02e0 #define DDA_ON_OFF 0x02e4 + #define GRPH_BUFFER_CNTL 0x02F0 #define VGA_BUFFER_CNTL 0x02F4 /* first overlay unit (there is only one) */ @@ -723,6 +726,7 @@ #define DP_SRC_ENDIAN 0x15D4 #define DP_SRC_FRGD_CLR 0x15D8 #define DP_SRC_BKGD_CLR 0x15DC +#define DP_WRITE_MASK 0x16cc #define SC_LEFT 0x1640 #define SC_RIGHT 0x1644 #define SC_TOP 0x1648 @@ -809,6 +813,7 @@ # define RB2D_DC_FLUSH (3 << 0) # define RB2D_DC_FLUSH_ALL 0xf # define RB2D_DC_BUSY (1 << 31) +#define DEFAULT_OFFSET 0x16e0 #define DEFAULT_PITCH_OFFSET 0x16E0 #define DEFAULT_SC_BOTTOM_RIGHT 0x16E8 /* DEFAULT_SC_BOTTOM_RIGHT bit constants */ @@ -882,6 +887,7 @@ #define SC_BOTTOM_RIGHT 0x16F0 #define SRC_SC_BOTTOM_RIGHT 0x16F4 #define RB2D_DSTCACHE_CTLSTAT 0x342C +#define RB2D_DSTCACHE_MODE 0x3428 #define RADEON_BASE_CODE 0x0f0b #define RADEON_BIOS_0_SCRATCH 0x0010 diff --git a/drivers/radeon/radeonfb.c b/drivers/radeon/radeonfb.c index b92f319c4f..3201211ca3 100644 --- a/drivers/radeon/radeonfb.c +++ b/drivers/radeon/radeonfb.c @@ -261,6 +261,7 @@ struct radeonfb_info { int hasTVout; int isM7; int isR200; + int theatre_num; u32 mmio_base_phys; u32 fb_base_phys; @@ -400,6 +401,7 @@ static __inline__ void _radeon_engine_idle (struct radeonfb_info *rinfo) } + #define radeon_engine_idle() _radeon_engine_idle(rinfo) #define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries) @@ -620,6 +622,106 @@ static struct pci_driver radeonfb_driver = { remove: radeonfb_pci_unregister, }; +static void _radeon_wait_for_idle(struct radeonfb_info *rinfo); +/* Restore the acceleration hardware to its previous state. */ +static void _radeon_engine_restore(struct radeonfb_info *rinfo) +{ + int pitch64; + + radeon_fifo_wait(1); + /* turn of all automatic flushing - we'll do it all */ + OUTREG(RB2D_DSTCACHE_MODE, 0); + + pitch64 = ((rinfo->xres * (rinfo->bpp / 8) + 0x3f)) >> 6; + + radeon_fifo_wait(1); + OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) | + (pitch64 << 22)); + + radeon_fifo_wait(1); +#if defined(__BIG_ENDIAN) + OUTREGP(DP_DATATYPE, + HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); +#else + OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); +#endif + + radeon_fifo_wait(1); + OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX + | DEFAULT_SC_BOTTOM_MAX)); + radeon_fifo_wait(1); + OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL) + | GMC_BRUSH_SOLID_COLOR + | GMC_SRC_DATATYPE_COLOR)); + + radeon_fifo_wait(7); + OUTREG(DST_LINE_START, 0); + OUTREG(DST_LINE_END, 0); + OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); + OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); + OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); + OUTREG(DP_SRC_BKGD_CLR, 0x00000000); + OUTREG(DP_WRITE_MASK, 0xffffffff); + + _radeon_wait_for_idle(rinfo); +} + +/* The FIFO has 64 slots. This routines waits until at least `entries' of + these slots are empty. */ +#define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */ +static void _radeon_wait_for_fifo_function(struct radeonfb_info *rinfo, int entries) +{ + int i; + + for (;;) { + for (i = 0; i < RADEON_TIMEOUT; i++) { + if((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries) return; + } + radeon_engine_reset(); + _radeon_engine_restore(rinfo); + /* it might be that DRI has been compiled in, but corresponding + library was not loaded.. */ + } +} +/* Wait for the graphics engine to be completely idle: the FIFO has + drained, the Pixel Cache is flushed, and the engine is idle. This is a + standard "sync" function that will make the hardware "quiescent". */ +static void _radeon_wait_for_idle(struct radeonfb_info *rinfo) +{ + int i; + + _radeon_wait_for_fifo_function(rinfo, 64); + + for (;;) { + for (i = 0; i < RADEON_TIMEOUT; i++) { + if (!(INREG(RBBM_STATUS) & RBBM_ACTIVE)) { + radeon_engine_flush(rinfo); + return; + } + } + _radeon_engine_reset(rinfo); + _radeon_engine_restore(rinfo); + } +} + + +static u32 RADEONVIP_idle(struct radeonfb_info *rinfo) +{ + u32 timeout; + + _radeon_wait_for_idle(rinfo); + timeout = INREG(VIPH_TIMEOUT_STAT); + if(timeout & VIPH_TIMEOUT_STAT__VIPH_REG_STAT) /* lockup ?? */ + { + radeon_fifo_wait(2); + OUTREG(VIPH_TIMEOUT_STAT, (timeout & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REG_AK); + _radeon_wait_for_idle(rinfo); + return (INREG(VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_RESET; + } + _radeon_wait_for_idle(rinfo); + return (INREG(VIPH_CONTROL) & 0x2000) ? VIP_BUSY : VIP_IDLE ; +} + int __init radeonfb_init (void) { @@ -684,6 +786,75 @@ MODULE_PARM(nomtrr, "i"); MODULE_PARM_DESC(nomtrr, "Don't touch MTRR (touch=0(default))"); #endif +/* address format: + ((device & 0x3)<<14) | (fifo << 12) | (addr) +*/ + +static int RADEONVIP_read(struct radeonfb_info *rinfo, u32 address, u32 count, u8 *buffer) +{ + u32 status,tmp; + + if((count!=1) && (count!=2) && (count!=4)) + { + printk("radeonfb: Attempt to access VIP bus with non-stadard transaction length\n"); + return 0; + } + + radeon_fifo_wait(2); + OUTREG(VIPH_REG_ADDR, address | 0x2000); + while(VIP_BUSY == (status = RADEONVIP_idle(rinfo))); + if(VIP_IDLE != status) return 0; + +/* + disable VIPH_REGR_DIS to enable VIP cycle. + The LSB of VIPH_TIMEOUT_STAT are set to 0 + because 1 would have acknowledged various VIP + interrupts unexpectedly +*/ + radeon_fifo_wait(2); + OUTREG(VIPH_TIMEOUT_STAT, INREG(VIPH_TIMEOUT_STAT) & (0xffffff00 & ~VIPH_TIMEOUT_STAT__VIPH_REGR_DIS) ); +/* + the value returned here is garbage. The read merely initiates + a register cycle +*/ + _radeon_wait_for_idle(rinfo); + INREG(VIPH_REG_DATA); + + while(VIP_BUSY == (status = RADEONVIP_idle(rinfo))); + if(VIP_IDLE != status) return 0; +/* + set VIPH_REGR_DIS so that the read won't take too long. +*/ + _radeon_wait_for_idle(rinfo); + tmp=INREG(VIPH_TIMEOUT_STAT); + OUTREG(VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REGR_DIS); + _radeon_wait_for_idle(rinfo); + switch(count){ + case 1: + *buffer=(u8)(INREG(VIPH_REG_DATA) & 0xff); + break; + case 2: + *(u16 *)buffer=(u16) (INREG(VIPH_REG_DATA) & 0xffff); + break; + case 4: + *(u32 *)buffer=(u32) ( INREG(VIPH_REG_DATA) & 0xffffffff); + break; + } + while(VIP_BUSY == (status = RADEONVIP_idle(rinfo))); + if(VIP_IDLE != status) return 0; + /* + so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles. +*/ + OUTREG(VIPH_TIMEOUT_STAT, (INREG(VIPH_TIMEOUT_STAT) & 0xffffff00) | VIPH_TIMEOUT_STAT__VIPH_REGR_DIS); + return 1; +} + +static int theatre_read(struct radeonfb_info *rinfo,u32 reg, u32 *data) +{ + if(rinfo->theatre_num<0) return 0; + return RADEONVIP_read(rinfo, ((rinfo->theatre_num & 0x3)<<14) | reg,4, (u8 *) data); +} + static char * GET_MON_NAME(int type) { char *pret; @@ -1002,8 +1173,23 @@ static int radeonfb_pci_register (struct pci_dev *pdev, printk("radeonfb: MTRR set to ON\n"); } #endif /* CONFIG_MTRR */ - - return 0; + rinfo->theatre_num = -1; + for(i=0;i<4;i++) + { + if(RADEONVIP_read(rinfo, ((i & 0x03)<<14) | VIP_VIP_VENDOR_DEVICE_ID, 4, (u8 *)&tmp) && + (tmp==RT_ATI_ID)) + { + rinfo->theatre_num=i; + break; + } + } + if(rinfo->theatre_num >= 0) { + printk("radeonfb: Device %d on VIP bus ids as %x\n",i,tmp); + theatre_read(rinfo,VIP_VIP_REVISION_ID, &tmp); + printk("radeonfb: Detected Rage Theatre revision %8.8X\n", tmp); + } + else printk("radeonfb: Rage Theatre not detected\n"); + return 0; } -- cgit v1.2.3