Rage theatre detection

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@2038 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
nick 2001-10-01 18:15:25 +00:00
parent 7dc1b569dc
commit a2b944cef6
2 changed files with 194 additions and 2 deletions

View File

@ -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

View File

@ -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;
}