summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authornick <nick@b3059339-0415-0410-9bf9-f77b7e298cf2>2001-10-01 18:15:25 +0000
committernick <nick@b3059339-0415-0410-9bf9-f77b7e298cf2>2001-10-01 18:15:25 +0000
commita2b944cef66aa0ce0b741641ab08241bf43242b1 (patch)
treeec085a81cca5e497b51fd1e3dd15619c5f3f1058 /drivers
parent7dc1b569dcde0989b7879b34098a66cf041245bc (diff)
downloadmpv-a2b944cef66aa0ce0b741641ab08241bf43242b1.tar.bz2
mpv-a2b944cef66aa0ce0b741641ab08241bf43242b1.tar.xz
Rage theatre detection
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@2038 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'drivers')
-rw-r--r--drivers/radeon/radeon.h6
-rw-r--r--drivers/radeon/radeonfb.c190
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;
}