mirror of
https://github.com/mpv-player/mpv
synced 2025-03-09 23:58:06 +00:00
Rage theatre detection
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@2038 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
7dc1b569dc
commit
a2b944cef6
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user