diff -urN xc-COMMIT/programs/Xserver/hw/xfree86/drivers/ati/radeon.h xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon.h --- xc-COMMIT/programs/Xserver/hw/xfree86/drivers/ati/radeon.h 2005-10-10 15:42:37.000000000 +1000 +++ xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon.h 2005-10-24 10:41:14.000000000 +1000 @@ -146,10 +146,16 @@ CARD32 cap0_trig_cntl; CARD32 cap1_trig_cntl; CARD32 bus_cntl; - CARD32 surface_cntl; CARD32 bios_4_scratch; CARD32 bios_5_scratch; CARD32 bios_6_scratch; + CARD32 surface_cntl; + CARD32 surfaces[8][3]; + CARD32 mc_agp_location; + CARD32 mc_fb_location; + CARD32 display_base_addr; + CARD32 display2_base_addr; + CARD32 ov0_base_addr; /* Other registers to save for VT switches */ CARD32 dp_datatype; @@ -157,8 +163,6 @@ CARD32 clock_cntl_index; CARD32 amcgpio_en_reg; CARD32 amcgpio_mask; - - CARD32 surfaces[8][3]; /* CRTC registers */ CARD32 crtc_gen_cntl; diff -urN xc-COMMIT/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c --- xc-COMMIT/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2005-10-10 15:42:37.000000000 +1000 +++ xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2005-10-24 11:30:54.000000000 +1000 @@ -129,6 +129,7 @@ static int RADEONValidateMergeModes(ScrnInfoPtr pScrn); static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode); static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn); +static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); /* psuedo xinerama support */ @@ -2238,81 +2239,56 @@ } /* Set up MC_FB_LOCATION and related registers */ -static void -RADEONSetFBLocation(ScrnInfoPtr pScrn) +static void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn,RADEONSavePtr save, + RADEONInfoPtr info) { - RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 mc_fb_location; - CARD32 mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); - CARD32 bus_cntl = INREG(RADEON_BUS_CNTL); - - OUTREG (RADEON_BUS_CNTL, bus_cntl | RADEON_BUS_MASTER_DIS); - RADEONWaitForIdleMMIO(pScrn); - /* This function has many problems with newer cards. - * Even with older cards, all registers changed here are not - * restored properly when X quits, this will also cause - * various problems, especially with radeonfb. - * Since we don't have DRI support for R300 and above cards, - * we just hardcode these values for now. - * Need to revisit this whole function!!! - */ + /* Default to existing values */ + save->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); + save->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); + /* + * Warning: A lot of the stuff down there is fairly bogus. For example, + * we use CONFIG_APER_SIZE which is only _half_ of the PCI exposed area + * since we might expose our VRAM in 2 different non overlapping apertures + * depending on how the card is bootstrapped. + * + * This will have to be fixed some day ... + */ if (info->IsIGP) { - mc_fb_location = INREG(RADEON_NB_TOM); + save->mc_fb_location = INREG(RADEON_NB_TOM); + /* Hack ... FIXME or at least move elsewhere*/ OUTREG(RADEON_GRPH2_BUFFER_CNTL, INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000); } else #ifdef XF86DRI if ( info->directRenderingEnabled && info->drmMinor < 10 ) { - mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U; + save->mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U; } else #endif { CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE); - mc_fb_location = (aper0_base >> 16) - | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1) - ) & 0xffff0000U); + save->mc_fb_location = (aper0_base >> 16) + | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1) + ) & 0xffff0000U); } - info->fbLocation = (mc_fb_location & 0xffff) << 16; + info->fbLocation = (save->mc_fb_location & 0xffff) << 16; - if (((mc_agp_location & 0xffff) << 16) != - ((mc_fb_location & 0xffff0000U) + 0x10000)) { - mc_agp_location = mc_fb_location & 0xffff0000U; - mc_agp_location |= (mc_agp_location + 0x10000) >> 16; + if (((save->mc_agp_location & 0xffff) << 16) != + ((save->mc_fb_location & 0xffff0000U) + 0x10000)) { + save->mc_agp_location = save->mc_fb_location & 0xffff0000U; + save->mc_agp_location |= (save->mc_agp_location + 0x10000) >> 16; } - RADEONWaitForIdleMMIO(pScrn); - - OUTREG(RADEON_MC_FB_LOCATION, mc_fb_location); - OUTREG(RADEON_MC_AGP_LOCATION, mc_agp_location); - OUTREG(RADEON_DISPLAY_BASE_ADDR, info->fbLocation); - if (info->HasCRTC2) - OUTREG(RADEON_DISPLAY2_BASE_ADDR, info->fbLocation); - OUTREG(RADEON_OV0_BASE_ADDR, info->fbLocation); - - OUTREG (RADEON_BUS_CNTL, bus_cntl); - RADEONWaitForIdleMMIO(pScrn); - - /* Set display0/1 priority up on r3/4xx in the memory controller for - * high res modes if the user specifies HIGH for displaypriority - * option. - */ - if ((info->DispPriority == 2) && IS_R300_VARIANT) { - CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); - if (info->MergedFB || pRADEONEnt->HasSecondary) { - mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ - } else { - mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ - } - OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); - } + save->display_base_addr = info->fbLocation; + save->display2_base_addr = info->fbLocation; + save->ov0_base_addr = info->fbLocation; } @@ -5503,6 +5479,8 @@ unsigned char *RADEONMMIO = info->MMIO; if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; + RADEONSaveMemMapRegisters(pScrn, &info->ModeReg); + info->fbLocation = (info->ModeReg.mc_fb_location & 0xffff) << 16; info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); } else { if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; @@ -5590,8 +5568,6 @@ hasDRI = info->directRenderingEnabled; #endif - RADEONSetFBLocation(pScrn); - if (!fbScreenInit(pScreen, info->FB, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, @@ -5830,7 +5806,66 @@ return TRUE; } -/* Write common registers (initialized to 0) */ +/* Write memory mapping registers */ +static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i; + + /* Write memory mapping registers only if their value change + * since we must ensure no access is done while they are + * reprogrammed + */ + if (INREG(RADEON_MC_FB_LOCATION) != restore->mc_fb_location || + INREG(RADEON_MC_AGP_LOCATION) != restore->mc_agp_location) { + CARD32 tmp; + + /* Make sure engine is idle. We assume the CCE is stopped + * at this point + */ + RADEONWaitForIdleMMIO(pScrn); + + /* Stop display & memory access */ + tmp = INREG(RADEON_CRTC_EXT_CNTL); + OUTREG(RADEON_CRTC_EXT_CNTL, tmp | RADEON_CRTC_DISPLAY_DIS); + tmp = INREG(RADEON_CRTC_GEN_CNTL); + tmp &= ~RADEON_CRTC_CUR_EN; + tmp |= RADEON_CRTC_DISP_REQ_EN_B; + OUTREG(RADEON_CRTC_GEN_CNTL, tmp); + if (info->HasCRTC2) { + tmp = INREG(RADEON_CRTC2_GEN_CNTL); + tmp &= ~RADEON_CRTC2_CUR_EN; + tmp |= RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B; + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + } + tmp = INREG(RADEON_OV0_SCALE_CNTL); + tmp &= ~RADEON_SCALER_ENABLE; + + /* Clear all surfaces */ + for (i = 0; i < 8; i++) { + OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0); + } + + /* Make sure the chip settles down and set new map*/ + usleep(100000); + OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location); + OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location); + /* Make sure map fully reached the chip */ + (void)INREG(RADEON_MC_FB_LOCATION); + + } + + /* Restore base addresses */ + OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); + OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr); + OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr); +} + +/* Write common registers */ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { @@ -6450,6 +6485,7 @@ /* For Non-dual head card, we don't have private field in the Entity */ if (!info->HasCRTC2) { + RADEONRestoreMemMapRegisters(pScrn, restore); RADEONRestoreCommonRegisters(pScrn, restore); RADEONRestoreCrtcRegisters(pScrn, restore); RADEONRestoreFPRegisters(pScrn, restore); @@ -6467,10 +6503,12 @@ * order. Regardless the order of X server issuing the calls, we * have to ensure we set registers in the right order!!! Otherwise * we may get a blank screen. + * + * We always restore MemMap first, the saverec should be up to date + * in all cases */ if (info->IsSecondary) { - if (!pRADEONEnt->RestorePrimary && !info->IsSwitching) - RADEONRestoreCommonRegisters(pScrn, restore); + RADEONRestoreMemMapRegisters(pScrn, restore); RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); @@ -6481,15 +6519,14 @@ if (pRADEONEnt->RestorePrimary) { pRADEONEnt->RestorePrimary = FALSE; + RADEONRestoreCommonRegisters(pScrn, &restore0); RADEONRestoreCrtcRegisters(pScrn, &restore0); RADEONRestoreFPRegisters(pScrn, &restore0); RADEONRestorePLLRegisters(pScrn, &restore0); pRADEONEnt->IsSecondaryRestored = FALSE; } } else { - if (!pRADEONEnt->IsSecondaryRestored) - RADEONRestoreCommonRegisters(pScrn, restore); - + RADEONRestoreMemMapRegisters(pScrn, restore); if (info->MergedFB) { RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); @@ -6499,6 +6536,7 @@ info->IsSwitching) { pRADEONEnt->IsSecondaryRestored = FALSE; + RADEONRestoreCommonRegisters(pScrn, restore); RADEONRestoreCrtcRegisters(pScrn, restore); RADEONRestoreFPRegisters(pScrn, restore); RADEONRestorePLLRegisters(pScrn, restore); @@ -6513,6 +6551,19 @@ #endif } +/* Read memory map */ +static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + save->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); + save->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); + save->display_base_addr = INREG(RADEON_DISPLAY_BASE_ADDR); + save->display2_base_addr = INREG(RADEON_DISPLAY2_BASE_ADDR); + save->ov0_base_addr = INREG(RADEON_OV0_BASE_ADDR); +} + /* Read common registers */ static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { @@ -6696,6 +6747,7 @@ RADEONInfoPtr info = RADEONPTR(pScrn); RADEONTRACE(("RADEONSaveMode(%p)\n", save)); + RADEONSaveMemMapRegisters(pScrn, save); RADEONSaveCommonRegisters(pScrn, save); if (info->IsSecondary) { RADEONSaveCrtc2Registers(pScrn, save); @@ -6724,6 +6776,7 @@ RADEONTRACE(("RADEONSave\n")); if (info->FBDev) { + RADEONSaveMemMapRegisters(pScrn, save); fbdevHWSave(pScrn); return; } @@ -6907,6 +6960,22 @@ int stop_req, max_stop_req; float read_return_rate, time_disp1_drop_priority; + /* + * Set display0/1 priority up on r3/4xx in the memory controller for + * high res modes if the user specifies HIGH for displaypriority + * option. + */ + if ((info->DispPriority == 2) && IS_R300_VARIANT) { + CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); + if (info->MergedFB || pRADEONEnt->HasSecondary) { + mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ + } else { + mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ + } + OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); + } + + /* R420 family not supported yet */ if (info->ChipFamily == CHIP_FAMILY_R420) return; @@ -8009,6 +8078,7 @@ info->Flags = mode->Flags; + RADEONInitMemMapRegisters(pScrn, save, info); RADEONInitCommonRegisters(save, info); if (info->IsSecondary) { if (!RADEONInitCrtc2Registers(pScrn, save, mode, info)) @@ -8389,7 +8459,6 @@ } else if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; - RADEONSetFBLocation(pScrn); if (!info->IsSecondary) RADEONRestoreSurfaces(pScrn, &info->ModeReg); #ifdef XF86DRI