summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/radeon.h13
-rw-r--r--src/radeon_bios.c462
-rw-r--r--src/radeon_reg.h30
3 files changed, 497 insertions, 8 deletions
diff --git a/src/radeon.h b/src/radeon.h
index 260c413c..f1b2fa3e 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -174,6 +174,18 @@ typedef enum {
#define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
#define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate)
+typedef struct {
+ int revision;
+ CARD16 rr1_offset;
+ CARD16 rr2_offset;
+ CARD16 dyn_clk_offset;
+ CARD16 pll_offset;
+ CARD16 mem_config_offset;
+ CARD16 mem_reset_offset;
+ CARD16 short_mem_offset;
+ CARD16 rr3_offset;
+ CARD16 rr4_offset;
+} RADEONBIOSInitTable;
typedef struct {
/* Common registers */
@@ -734,6 +746,7 @@ typedef struct {
Bool want_vblank_interrupts;
RADEONBIOSConnector BiosConnector[RADEON_MAX_BIOS_CONNECTOR];
+ RADEONBIOSInitTable BiosTable;
Rotation rotation;
void (*PointerMoved)(int, int, int);
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index 76b0a728..543ccb9b 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -612,3 +612,465 @@ Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output)
}
return FALSE;
}
+
+/* support for init from bios tables
+ *
+ * Based heavily on the netbsd radeonfb driver
+ * Written by Garrett D'Amore
+ * Copyright (c) 2006 Itronix Inc.
+ *
+ */
+
+/* bios table defines */
+
+#define RADEON_TABLE_ENTRY_FLAG_MASK 0xe000
+#define RADEON_TABLE_ENTRY_INDEX_MASK 0x1fff
+#define RADEON_TABLE_ENTRY_COMMAND_MASK 0x00ff
+
+#define RADEON_TABLE_FLAG_WRITE_INDEXED 0x0000
+#define RADEON_TABLE_FLAG_WRITE_DIRECT 0x2000
+#define RADEON_TABLE_FLAG_MASK_INDEXED 0x4000
+#define RADEON_TABLE_FLAG_MASK_DIRECT 0x6000
+#define RADEON_TABLE_FLAG_DELAY 0x8000
+#define RADEON_TABLE_FLAG_SCOMMAND 0xa000
+
+#define RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03
+#define RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08
+
+#define RADEON_PLL_FLAG_MASK 0xc0
+#define RADEON_PLL_INDEX_MASK 0x3f
+
+#define RADEON_PLL_FLAG_WRITE 0x00
+#define RADEON_PLL_FLAG_MASK_BYTE 0x40
+#define RADEON_PLL_FLAG_WAIT 0x80
+
+#define RADEON_PLL_WAIT_150MKS 1
+#define RADEON_PLL_WAIT_5MS 2
+#define RADEON_PLL_WAIT_MC_BUSY_MASK 3
+#define RADEON_PLL_WAIT_DLL_READY_MASK 4
+#define RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5
+
+static CARD16
+RADEONValidateBIOSOffset(ScrnInfoPtr pScrn, CARD16 offset)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ CARD8 revision = RADEON_BIOS8(offset - 1);
+
+ if (revision > 0x10) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Bad revision %d for BIOS table\n", revision);
+ return 0;
+ }
+
+ if (offset < 0x60) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Bad offset 0x%x for BIOS Table\n", offset);
+ return 0;
+ }
+
+ return offset;
+}
+
+Bool
+RADEONGetBIOSInitTableOffsets(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ CARD8 val;
+
+ if (!info->VBIOS) {
+ return FALSE;
+ } else {
+ if (info->IsAtomBios) {
+ return FALSE;
+ } else {
+ info->BiosTable.revision = RADEON_BIOS8(info->ROMHeaderStart + 4);
+ info->BiosTable.rr1_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x0c);
+ if (info->BiosTable.rr1_offset) {
+ info->BiosTable.rr1_offset =
+ RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr1_offset);
+ }
+ if (info->BiosTable.revision > 0x09)
+ return TRUE;
+ info->BiosTable.rr2_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x4e);
+ if (info->BiosTable.rr2_offset) {
+ info->BiosTable.rr2_offset =
+ RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr2_offset);
+ }
+ info->BiosTable.dyn_clk_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x52);
+ if (info->BiosTable.dyn_clk_offset) {
+ info->BiosTable.dyn_clk_offset =
+ RADEONValidateBIOSOffset(pScrn, info->BiosTable.dyn_clk_offset);
+ }
+ info->BiosTable.pll_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x46);
+ if (info->BiosTable.pll_offset) {
+ info->BiosTable.pll_offset =
+ RADEONValidateBIOSOffset(pScrn, info->BiosTable.pll_offset);
+ }
+ info->BiosTable.mem_config_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x48);
+ if (info->BiosTable.mem_config_offset) {
+ info->BiosTable.mem_config_offset =
+ RADEONValidateBIOSOffset(pScrn, info->BiosTable.mem_config_offset);
+ }
+ if (info->BiosTable.mem_config_offset) {
+ info->BiosTable.mem_reset_offset = RADEON_BIOS16(info->BiosTable.mem_config_offset);
+ if (info->BiosTable.mem_reset_offset) {
+ while (RADEON_BIOS8(info->BiosTable.mem_reset_offset))
+ info->BiosTable.mem_reset_offset++;
+ info->BiosTable.mem_reset_offset++;
+ info->BiosTable.mem_reset_offset += 2;
+ }
+ }
+ if (info->BiosTable.mem_config_offset) {
+ info->BiosTable.short_mem_offset = RADEON_BIOS16(info->BiosTable.mem_config_offset);
+ if ((info->BiosTable.short_mem_offset != 0) &&
+ (RADEON_BIOS8(info->BiosTable.short_mem_offset - 2) <= 64))
+ info->BiosTable.short_mem_offset +=
+ RADEON_BIOS8(info->BiosTable.short_mem_offset - 3);
+ }
+ if (info->BiosTable.rr2_offset) {
+ info->BiosTable.rr3_offset = RADEON_BIOS16(info->BiosTable.rr2_offset);
+ if (info->BiosTable.rr3_offset) {
+ while ((val = RADEON_BIOS8(info->BiosTable.rr3_offset + 1)) != 0) {
+ if (val & 0x40)
+ info->BiosTable.rr3_offset += 10;
+ else if (val & 0x80)
+ info->BiosTable.rr3_offset += 4;
+ else
+ info->BiosTable.rr3_offset += 6;
+ }
+ info->BiosTable.rr3_offset += 2;
+ }
+ }
+
+ if (info->BiosTable.rr3_offset) {
+ info->BiosTable.rr4_offset = RADEON_BIOS16(info->BiosTable.rr3_offset);
+ if (info->BiosTable.rr4_offset) {
+ while ((val = RADEON_BIOS8(info->BiosTable.rr4_offset + 1)) != 0) {
+ if (val & 0x40)
+ info->BiosTable.rr4_offset += 10;
+ else if (val & 0x80)
+ info->BiosTable.rr4_offset += 4;
+ else
+ info->BiosTable.rr4_offset += 6;
+ }
+ info->BiosTable.rr4_offset += 2;
+ }
+ }
+
+ if (info->BiosTable.rr3_offset + 1 == info->BiosTable.pll_offset) {
+ info->BiosTable.rr3_offset = 0;
+ info->BiosTable.rr4_offset = 0;
+ }
+
+ return TRUE;
+
+ }
+ }
+}
+
+static void
+RADEONRestoreBIOSRegBlock(ScrnInfoPtr pScrn, CARD16 table_offset)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD16 offset = table_offset;
+ CARD16 value, flag, index, count;
+ CARD32 andmask, ormask, val, channel_complete_mask;
+ CARD8 command;
+
+ if (offset == 0)
+ return;
+
+ while ((value = RADEON_BIOS16(offset)) != 0) {
+ flag = value & RADEON_TABLE_ENTRY_FLAG_MASK;
+ index = value & RADEON_TABLE_ENTRY_INDEX_MASK;
+ command = value & RADEON_TABLE_ENTRY_COMMAND_MASK;
+
+ offset += 2;
+
+ switch (flag) {
+ case RADEON_TABLE_FLAG_WRITE_INDEXED:
+ val = RADEON_BIOS32(offset);
+ ErrorF("WRITE INDEXED: 0x%x 0x%x\n",
+ index, val);
+ OUTREG(RADEON_MM_INDEX, index);
+ OUTREG(RADEON_MM_DATA, val);
+ offset += 4;
+ break;
+
+ case RADEON_TABLE_FLAG_WRITE_DIRECT:
+ val = RADEON_BIOS32(offset);
+ ErrorF("WRITE DIRECT: 0x%x 0x%x\n", index, val);
+ OUTREG(index, val);
+ offset += 4;
+ break;
+
+ case RADEON_TABLE_FLAG_MASK_INDEXED:
+ andmask = RADEON_BIOS32(offset);
+ offset += 4;
+ ormask = RADEON_BIOS32(offset);
+ offset += 4;
+ ErrorF("MASK INDEXED: 0x%x 0x%x 0x%x\n",
+ index, andmask, ormask);
+ OUTREG(RADEON_MM_INDEX, index);
+ val = INREG(RADEON_MM_DATA);
+ val = (val & andmask) | ormask;
+ OUTREG(RADEON_MM_DATA, val);
+ break;
+
+ case RADEON_TABLE_FLAG_MASK_DIRECT:
+ andmask = RADEON_BIOS32(offset);
+ offset += 4;
+ ormask = RADEON_BIOS32(offset);
+ offset += 4;
+ ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n",
+ index, andmask, ormask);
+ val = INREG(index);
+ val = (val & andmask) | ormask;
+ OUTREG(index, val);
+ break;
+
+ case RADEON_TABLE_FLAG_DELAY:
+ count = RADEON_BIOS16(offset);
+ ErrorF("delay: %d\n", count);
+ usleep(count);
+ offset += 2;
+ break;
+
+ case RADEON_TABLE_FLAG_SCOMMAND:
+ ErrorF("SCOMMAND 0x%x\n", command);
+ switch (command) {
+ case RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK:
+ count = RADEON_BIOS16(offset);
+ ErrorF("SCOMMAND_WAIT_MC_BUSY_MASK %d\n", count);
+ while (count--) {
+ if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) &
+ RADEON_MC_BUSY))
+ break;
+ }
+ break;
+
+ case RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE:
+ count = RADEON_BIOS16(offset);
+ ErrorF("SCOMMAND_WAIT_MEM_PWRUP_COMPLETE %d\n", count);
+ while (count--) {
+ /* XXX: may need indexed access */
+ /* may need to take into account how many memory channels
+ * each card has
+ */
+ if (IS_R300_VARIANT)
+ channel_complete_mask = R300_MEM_PWRUP_COMPLETE;
+ else
+ channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE;
+ if ((INREG(RADEON_MEM_STR_CNTL) &
+ channel_complete_mask) ==
+ channel_complete_mask)
+ break;
+ }
+ break;
+
+ }
+ offset += 2;
+ break;
+ }
+ }
+}
+
+static void
+RADEONRestoreBIOSMemBlock(ScrnInfoPtr pScrn, CARD16 table_offset)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD16 offset = table_offset;
+ CARD16 count;
+ CARD32 ormask, val, channel_complete_mask;
+ CARD8 index;
+
+ if (offset == 0)
+ return;
+
+ while ((index = RADEON_BIOS8(offset)) != 0xff) {
+ offset++;
+ if (index == 0x0f) {
+ count = 20000;
+ ErrorF("MEM_WAIT_MEM_PWRUP_COMPLETE %d\n", count);
+ while (count--) {
+ /* XXX: may need indexed access */
+ /* may need to take into account how many memory channels
+ * each card has
+ */
+ if (IS_R300_VARIANT)
+ channel_complete_mask = R300_MEM_PWRUP_COMPLETE;
+ else
+ channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE;
+ if ((INREG(RADEON_MEM_STR_CNTL) &
+ channel_complete_mask) ==
+ channel_complete_mask)
+ break;
+ }
+ } else {
+ ormask = RADEON_BIOS16(offset);
+ offset += 2;
+
+ ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n",
+ RADEON_SDRAM_MODE_MASK, ormask);
+
+ /* can this use direct access? */
+ OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG);
+ val = INREG(RADEON_MM_DATA);
+ val = (val & RADEON_SDRAM_MODE_MASK) | ormask;
+ OUTREG(RADEON_MM_DATA, val);
+
+ ormask = (CARD32)index << 24;
+
+ ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n",
+ RADEON_B3MEM_RESET_MASK, ormask);
+
+ /* can this use direct access? */
+ OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG);
+ val = INREG(RADEON_MM_DATA);
+ val = (val & RADEON_B3MEM_RESET_MASK) | ormask;
+ OUTREG(RADEON_MM_DATA, val);
+ }
+ }
+}
+
+static void
+RADEONRestoreBIOSPllBlock(ScrnInfoPtr pScrn, CARD16 table_offset)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD16 offset = table_offset;
+ CARD8 index, shift;
+ CARD32 andmask, ormask, val, clk_pwrmgt_cntl;
+ CARD16 count;
+
+ if (offset == 0)
+ return;
+
+ while ((index = BIOS8(offset)) != 0) {
+ offset++;
+
+ switch (index & RADEON_PLL_FLAG_MASK) {
+ case RADEON_PLL_FLAG_WAIT:
+ switch (index & RADEON_PLL_INDEX_MASK) {
+ case RADEON_PLL_WAIT_150MKS:
+ ErrorF("delay: 150 us\n");
+ usleep(150);
+ break;
+ case RADEON_PLL_WAIT_5MS:
+ usleep(5000);
+ ErrorF("delay: 5 ms\n");
+ break;
+
+ case RADEON_PLL_WAIT_MC_BUSY_MASK:
+ count = 1000;
+ ErrorF("PLL_WAIT_MC_BUSY_MASK %d\n", count);
+ while (count--) {
+ if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) &
+ RADEON_MC_BUSY))
+ break;
+ }
+ break;
+
+ case RADEON_PLL_WAIT_DLL_READY_MASK:
+ count = 1000;
+ ErrorF("PLL_WAIT_DLL_READY_MASK %d\n", count);
+ while (count--) {
+ if (INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) &
+ RADEON_DLL_READY)
+ break;
+ }
+ break;
+
+ case RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24:
+ ErrorF("PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24\n");
+ clk_pwrmgt_cntl = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL);
+ if (clk_pwrmgt_cntl & RADEON_CG_NO1_DEBUG_0) {
+ val = INPLL(pScrn, RADEON_MCLK_CNTL);
+ /* is this right? */
+ val = (val & 0xFFFF0000) | 0x1111; /* seems like we should clear these... */
+ OUTPLL(pScrn, RADEON_MCLK_CNTL, val);
+ usleep(10000);
+ OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL,
+ clk_pwrmgt_cntl & ~RADEON_CG_NO1_DEBUG_0);
+ usleep(10000);
+ }
+ break;
+ }
+ break;
+
+ case RADEON_PLL_FLAG_MASK_BYTE:
+ shift = BIOS8(offset) * 8;
+ offset++;
+
+ andmask =
+ (((CARD32)BIOS8(offset)) << shift) |
+ ~((CARD32)0xff << shift);
+ offset++;
+
+ ormask = ((CARD32)BIOS8(offset)) << shift;
+ offset++;
+
+ ErrorF("PLL_MASK_BYTE 0x%x 0x%x 0x%x 0x%x\n",
+ index, shift, andmask, ormask);
+ val = INPLL(pScrn, index);
+ val = (val & andmask) | ormask;
+ OUTPLL(pScrn, index, val);
+ break;
+
+ case RADEON_PLL_FLAG_WRITE:
+ val = RADEON_BIOS32(offset);
+ ErrorF("PLL_WRITE 0x%x 0x%x\n", index, val);
+ OUTPLL(pScrn, index, val);
+ offset += 4;
+ break;
+ }
+ }
+}
+
+Bool
+RADEONPostCardFromBIOSTables(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+
+ if (!info->VBIOS) {
+ return FALSE;
+ } else {
+ if (info->IsAtomBios) {
+ return FALSE;
+ } else {
+ if (info->BiosTable.rr1_offset) {
+ ErrorF("rr1 restore\n");
+ RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr1_offset);
+ }
+ if (info->BiosTable.revision < 0x09) {
+ if (info->BiosTable.pll_offset) {
+ ErrorF("pll restore\n");
+ RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.pll_offset);
+ }
+ if (info->BiosTable.rr2_offset) {
+ ErrorF("rr2 restore\n");
+ RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr2_offset);
+ }
+ if (info->BiosTable.rr4_offset) {
+ ErrorF("rr4 restore\n");
+ RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr4_offset);
+ }
+ if (info->BiosTable.mem_reset_offset) {
+ ErrorF("mem reset restore\n");
+ RADEONRestoreBIOSMemBlock(pScrn, info->BiosTable.mem_reset_offset);
+ }
+ if (info->BiosTable.rr3_offset) {
+ ErrorF("rr3 restore\n");
+ RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr3_offset);
+ }
+ if (info->BiosTable.dyn_clk_offset) {
+ ErrorF("dyn_clk restore\n");
+ RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.dyn_clk_offset);
+ }
+ }
+ }
+ }
+ return TRUE;
+}
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 72470a66..9423bca5 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -231,7 +231,13 @@
# define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13)
# define RADEON_ACTIVE_HILO_LAT_SHIFT 13
# define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12)
+# define RADEON_MC_BUSY (1 << 16)
+# define RADEON_DLL_READY (1 << 19)
+# define RADEON_CG_NO1_DEBUG_0 (1 << 24)
+# define RADEON_CG_NO1_DEBUG_MASK (0x1f << 24)
# define RADEON_DYN_STOP_MODE_MASK (7 << 21)
+# define RADEON_TVPLL_PWRMGT_OFF (1 << 30)
+# define RADEON_TVCLK_TURNOFF (1 << 31)
#define RADEON_PLL_PWRMGT_CNTL 0x0015
# define RADEON_TCL_BYPASS_DISABLE (1 << 20)
#define RADEON_CLR_CMP_CLR_3D 0x1a24
@@ -889,9 +895,6 @@
#define RADEON_MAX_LATENCY 0x0f3f /* PCI */
#define RADEON_MC_AGP_LOCATION 0x014c
#define RADEON_MC_FB_LOCATION 0x0148
-#define RADEON_MC_STATUS 0x0150
-# define RADEON_MC_IDLE (1 << 2)
-# define R300_MC_IDLE (1 << 4)
#define RADEON_DISPLAY_BASE_ADDR 0x23c
#define RADEON_DISPLAY2_BASE_ADDR 0x33c
#define RADEON_OV0_BASE_ADDR 0x43c
@@ -907,8 +910,8 @@
# define R300_DISABLE_MC_MCLKA (1 << 21)
# define R300_DISABLE_MC_MCLKB (1 << 21)
#define RADEON_MCLK_MISC 0x001f /* PLL */
-# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1<<12)
-# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13)
+# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1 << 12)
+# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13)
# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14)
# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15)
#define RADEON_LCD_GPIO_MASK 0x01a0
@@ -921,15 +924,26 @@
#define RADEON_MEM_BASE 0x0f10 /* PCI */
#define RADEON_MEM_CNTL 0x0140
# define RADEON_MEM_NUM_CHANNELS_MASK 0x01
-# define RADEON_MEM_USE_B_CH_ONLY (1<<1)
-# define RV100_HALF_MODE (1<<3)
+# define RADEON_MEM_USE_B_CH_ONLY (1 << 1)
+# define RV100_HALF_MODE (1 << 3)
# define R300_MEM_NUM_CHANNELS_MASK 0x03
-# define R300_MEM_USE_CD_CH_ONLY (1<<2)
+# define R300_MEM_USE_CD_CH_ONLY (1 << 2)
#define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */
#define RADEON_MEM_INIT_LAT_TIMER 0x0154
#define RADEON_MEM_INTF_CNTL 0x014c
#define RADEON_MEM_SDRAM_MODE_REG 0x0158
+# define RADEON_SDRAM_MODE_MASK 0xffff0000
+# define RADEON_B3MEM_RESET_MASK 0x6fffffff
#define RADEON_MEM_STR_CNTL 0x0150
+# define RADEON_MEM_PWRUP_COMPL_A (1 << 0)
+# define RADEON_MEM_PWRUP_COMPL_B (1 << 1)
+# define R300_MEM_PWRUP_COMPL_C (1 << 2)
+# define R300_MEM_PWRUP_COMPL_D (1 << 3)
+# define RADEON_MEM_PWRUP_COMPLETE 0x03
+# define R300_MEM_PWRUP_COMPLETE 0x0f
+#define RADEON_MC_STATUS 0x0150
+# define RADEON_MC_IDLE (1 << 2)
+# define R300_MC_IDLE (1 << 4)
#define RADEON_MEM_VGA_RP_SEL 0x003c
#define RADEON_MEM_VGA_WP_SEL 0x0038
#define RADEON_MIN_GRANT 0x0f3e /* PCI */