diff options
Diffstat (limited to 'src/radeon_driver.c')
-rw-r--r-- | src/radeon_driver.c | 1341 |
1 files changed, 1067 insertions, 274 deletions
diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 9f9fd901..e65e446e 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -97,6 +97,7 @@ #include "xf86cmap.h" #include "vbe.h" +#include "shadow.h" /* vgaHW definitions */ #ifdef WITH_VGAHW #include "vgaHW.h" @@ -347,6 +348,15 @@ static const char *i2cSymbols[] = { NULL }; +static const char *shadowSymbols[] = { + "shadowAdd", + "shadowInit", + "shadowSetup", + "shadowUpdatePacked", + "shadowUpdatePackedWeak", + NULL +}; + void RADEONLoaderRefSymLists(void) { /* @@ -405,23 +415,41 @@ struct RADEONInt10Save { static Bool RADEONMapMMIO(ScrnInfoPtr pScrn); static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn); -#if 0 +static void * +radeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, + CARD32 *size, void *closure) +{ + ScrnInfoPtr pScrn = xf86Screens[screen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + int stride; + + stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; + *size = stride; + + return ((CARD8 *)info->FB + pScrn->fbOffset + + row * stride + offset); +} static Bool RADEONCreateScreenResources (ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); + PixmapPtr pixmap; pScreen->CreateScreenResources = info->CreateScreenResources; if (!(*pScreen->CreateScreenResources)(pScreen)) return FALSE; + pScreen->CreateScreenResources = RADEONCreateScreenResources; - if (!xf86RandR12CreateScreenResources(pScreen)) - return FALSE; + if (info->r600_shadow_fb) { + pixmap = pScreen->GetScreenPixmap(pScreen); - return TRUE; + if (!shadowAdd(pScreen, pixmap, shadowUpdatePackedWeak(), + radeonShadowWindow, 0, NULL)) + return FALSE; + } + return TRUE; } -#endif RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) { @@ -440,18 +468,20 @@ RADEONPreInt10Save(ScrnInfoPtr pScrn, void **pPtr) CARD32 CardTmp; static struct RADEONInt10Save SaveStruct = { 0, 0, 0 }; - /* Save the values and zap MEM_CNTL */ - SaveStruct.MEM_CNTL = INREG(RADEON_MEM_CNTL); - SaveStruct.MEMSIZE = INREG(RADEON_CONFIG_MEMSIZE); - SaveStruct.MPP_TB_CONFIG = INREG(RADEON_MPP_TB_CONFIG); + if (!IS_AVIVO_VARIANT) { + /* Save the values and zap MEM_CNTL */ + SaveStruct.MEM_CNTL = INREG(RADEON_MEM_CNTL); + SaveStruct.MEMSIZE = INREG(RADEON_CONFIG_MEMSIZE); + SaveStruct.MPP_TB_CONFIG = INREG(RADEON_MPP_TB_CONFIG); - /* - * Zap MEM_CNTL and set MPP_TB_CONFIG<31:24> to 4 - */ - OUTREG(RADEON_MEM_CNTL, 0); - CardTmp = SaveStruct.MPP_TB_CONFIG & 0x00ffffffu; - CardTmp |= 0x04 << 24; - OUTREG(RADEON_MPP_TB_CONFIG, CardTmp); + /* + * Zap MEM_CNTL and set MPP_TB_CONFIG<31:24> to 4 + */ + OUTREG(RADEON_MEM_CNTL, 0); + CardTmp = SaveStruct.MPP_TB_CONFIG & 0x00ffffffu; + CardTmp |= 0x04 << 24; + OUTREG(RADEON_MPP_TB_CONFIG, CardTmp); + } *pPtr = (void *)&SaveStruct; } @@ -468,6 +498,9 @@ RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr) if (!pSave || !pSave->MEM_CNTL) return; + if (IS_AVIVO_VARIANT) + return; + /* * If either MEM_CNTL is currently zero or inconistent (configured for * two channels with the two channels configured differently), restore @@ -718,6 +751,141 @@ void RADEONOUTPLL(ScrnInfoPtr pScrn, int addr, CARD32 data) RADEONPllErrataAfterData(info); } +/* Read MC register */ +unsigned RADEONINMC(ScrnInfoPtr pScrn, int addr) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 data; + + if (IS_AVIVO_VARIANT) { + OUTREG(AVIVO_MC_INDEX, (addr & 0xff) | 0x7f0000); + (void)INREG(AVIVO_MC_INDEX); + data = INREG(AVIVO_MC_DATA); + + OUTREG(AVIVO_MC_INDEX, 0); + (void)INREG(AVIVO_MC_INDEX); + } else { + OUTREG(R300_MC_IND_INDEX, addr & 0x3f); + (void)INREG(R300_MC_IND_INDEX); + data = INREG(R300_MC_IND_DATA); + + OUTREG(R300_MC_IND_INDEX, 0); + (void)INREG(R300_MC_IND_INDEX); + } + + return data; +} + +/* Write MC information */ +void RADEONOUTMC(ScrnInfoPtr pScrn, int addr, CARD32 data) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (IS_AVIVO_VARIANT) { + OUTREG(AVIVO_MC_INDEX, (addr & 0xff) | 0xff0000); + (void)INREG(AVIVO_MC_INDEX); + OUTREG(AVIVO_MC_DATA, data); + OUTREG(AVIVO_MC_INDEX, 0); + (void)INREG(AVIVO_MC_INDEX); + } else { + OUTREG(R300_MC_IND_INDEX, (((addr) & 0x3f) | + R300_MC_IND_WR_EN)); + (void)INREG(R300_MC_IND_INDEX); + OUTREG(R300_MC_IND_DATA, data); + OUTREG(R300_MC_IND_INDEX, 0); + (void)INREG(R300_MC_IND_INDEX); + } +} + +Bool avivo_get_mc_idle(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (info->ChipFamily >= CHIP_FAMILY_R600) { + /* no idea where this is on r600 yet */ + return TRUE; + } else if (info->ChipFamily == CHIP_FAMILY_RV515) { + if (INMC(pScrn, RV515_MC_STATUS) & RV515_MC_STATUS_IDLE) + return TRUE; + else + return FALSE; + } else { + if (INMC(pScrn, R520_MC_STATUS) & R520_MC_STATUS_IDLE) + return TRUE; + else + return FALSE; + } +} + +#define LOC_FB 0x1 +#define LOC_AGP 0x2 +void radeon_write_mc_fb_agp_location(ScrnInfoPtr pScrn, int mask, CARD32 fb_loc, CARD32 agp_loc, CARD32 agp_loc_hi) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (info->ChipFamily >= CHIP_FAMILY_R600) { + if (mask & LOC_FB) + OUTREG(R600_MC_VM_FB_LOCATION, fb_loc); + if (mask & LOC_AGP) { + OUTREG(R600_MC_VM_AGP_BOT, agp_loc); + OUTREG(R600_MC_VM_AGP_TOP, agp_loc_hi); + } + } else if (info->ChipFamily == CHIP_FAMILY_RV515) { + if (mask & LOC_FB) + OUTMC(pScrn, RV515_MC_FB_LOCATION, fb_loc); + if (mask & LOC_AGP) + OUTMC(pScrn, RV515_MC_AGP_LOCATION, agp_loc); + (void)INMC(pScrn, RV515_MC_AGP_LOCATION); + } else if (info->ChipFamily >= CHIP_FAMILY_R520) { + if (mask & LOC_FB) + OUTMC(pScrn, R520_MC_FB_LOCATION, fb_loc); + if (mask & LOC_AGP) + OUTMC(pScrn, R520_MC_AGP_LOCATION, agp_loc); + (void)INMC(pScrn, R520_MC_FB_LOCATION); + } else { + if (mask & LOC_FB) + OUTREG(RADEON_MC_FB_LOCATION, fb_loc); + if (mask & LOC_AGP) + OUTREG(RADEON_MC_AGP_LOCATION, agp_loc); + } +} + +void radeon_read_mc_fb_agp_location(ScrnInfoPtr pScrn, int mask, CARD32 *fb_loc, CARD32 *agp_loc, CARD32 *agp_loc_hi) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + if (info->ChipFamily >= CHIP_FAMILY_R600) { + if (mask & LOC_FB) + *fb_loc = INREG(R600_MC_VM_FB_LOCATION); + if (mask & LOC_AGP) { + *agp_loc = INREG(R600_MC_VM_AGP_BOT); + *agp_loc_hi = INREG(R600_MC_VM_AGP_TOP); + } + } else if (info->ChipFamily == CHIP_FAMILY_RV515) { + if (mask & LOC_FB) + *fb_loc = INMC(pScrn, RV515_MC_FB_LOCATION); + if (mask & LOC_AGP) { + *agp_loc = INMC(pScrn, RV515_MC_AGP_LOCATION); + *agp_loc_hi = 0; + } + } else if (info->ChipFamily >= CHIP_FAMILY_R520) { + if (mask & LOC_FB) + *fb_loc = INMC(pScrn, R520_MC_FB_LOCATION); + if (mask & LOC_AGP) { + *agp_loc = INMC(pScrn, R520_MC_AGP_LOCATION); + *agp_loc_hi = 0; + } + } else { + if (mask & LOC_FB) + *fb_loc = INREG(RADEON_MC_FB_LOCATION); + if (mask & LOC_AGP) + *agp_loc = INREG(RADEON_MC_AGP_LOCATION); + } +} #if 0 /* Read PAL information (only used for debugging) */ @@ -1022,22 +1190,25 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) if (pll->reference_div < 2) pll->reference_div = 12; } - } else { xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Video BIOS not detected, using default clock settings!\n"); /* Default min/max PLL values */ if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) { - pll->min_pll_freq = 20000; - pll->max_pll_freq = 50000; + pll->pll_in_min = 100; + pll->pll_in_max = 1350; + pll->pll_out_min = 20000; + pll->pll_out_max = 50000; } else { - pll->min_pll_freq = 12500; - pll->max_pll_freq = 35000; + pll->pll_in_min = 40; + pll->pll_in_max = 500; + pll->pll_out_min = 12500; + pll->pll_out_max = 35000; } if (RADEONProbePLLParameters(pScrn)) - return; + return; if (info->IsIGP) pll->reference_freq = 1432; @@ -1051,20 +1222,37 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) info->mclk = 200.00; } + if (info->ChipFamily == CHIP_FAMILY_RV100 && !pRADEONEnt->HasCRTC2) { + /* Avoid RN50 corruption due to memory bandwidth starvation. + * 18 is an empirical value based on the databook and Windows driver. + * + * Empirical value changed to 24 to raise pixel clock limit and + * allow higher resolution modes on capable monitors + */ + pll->pll_out_max = min(pll->pll_out_max, + 24 * info->mclk * 100 / pScrn->bitsPerPixel * + info->RamWidth / 16); + } + /* card limits for computing PLLs */ + if (IS_AVIVO_VARIANT) { + pll->min_post_div = 2; + pll->max_post_div = 0x7f; + } else { + pll->min_post_div = 1; + pll->max_post_div = 12; //16 on crtc0 + } pll->min_ref_div = 2; pll->max_ref_div = 0x3ff; pll->min_feedback_div = 4; pll->max_feedback_div = 0x7ff; - pll->pll_in_min = 40; - pll->pll_in_max = 500; pll->best_vco = 0; xf86DrvMsg (pScrn->scrnIndex, X_INFO, "PLL parameters: rf=%u rd=%u min=%u max=%u; xclk=%u\n", pll->reference_freq, pll->reference_div, - (unsigned)pll->min_pll_freq, (unsigned)pll->max_pll_freq, + (unsigned)pll->pll_out_min, (unsigned)pll->pll_out_max, pll->xclk); /* (Some?) Radeon BIOSes seem too lie about their minimum dot @@ -1073,7 +1261,7 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) */ if (xf86GetOptValFreq(info->Options, OPTION_MIN_DOTCLOCK, OPTUNITS_MHZ, &min_dotclock)) { - if (min_dotclock < 12 || min_dotclock*100 >= pll->max_pll_freq) { + if (min_dotclock < 12 || min_dotclock*100 >= pll->pll_out_max) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Illegal minimum dotclock specified %.2f MHz " "(option ignored)\n", @@ -1082,8 +1270,8 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Forced minimum dotclock to %.2f MHz " "(instead of detected %.2f MHz)\n", - min_dotclock, ((double)pll->min_pll_freq/1000)); - pll->min_pll_freq = min_dotclock * 1000; + min_dotclock, ((double)pll->pll_out_min/1000)); + pll->pll_out_min = min_dotclock * 1000; } } } @@ -1184,9 +1372,14 @@ void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, { save->mc_fb_location = info->mc_fb_location; save->mc_agp_location = info->mc_agp_location; - save->display_base_addr = info->fbLocation; - save->display2_base_addr = info->fbLocation; - save->ov0_base_addr = info->fbLocation; + + if (IS_AVIVO_VARIANT) { + save->mc_agp_location_hi = info->mc_agp_location_hi; + } else { + save->display_base_addr = info->fbLocation; + save->display2_base_addr = info->fbLocation; + save->ov0_base_addr = info->fbLocation; + } } static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) @@ -1196,15 +1389,20 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) CARD32 mem_size; CARD32 aper_size; - /* Default to existing values */ - info->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); - info->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); + radeon_read_mc_fb_agp_location(pScrn, LOC_FB | LOC_AGP, &info->mc_fb_location, + &info->mc_agp_location, &info->mc_agp_location_hi); /* We shouldn't use info->videoRam here which might have been clipped * but the real video RAM instead */ - mem_size = INREG(RADEON_CONFIG_MEMSIZE); - aper_size = INREG(RADEON_CONFIG_APER_SIZE); + if (info->ChipFamily >= CHIP_FAMILY_R600) { + mem_size = INREG(R600_CONFIG_MEMSIZE); + aper_size = INREG(R600_CONFIG_APER_SIZE); + } else { + mem_size = INREG(RADEON_CONFIG_MEMSIZE); + aper_size = INREG(RADEON_CONFIG_APER_SIZE); + } + if (mem_size == 0) mem_size = 0x800000; @@ -1233,7 +1431,13 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) else #endif { - CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE); + CARD32 aper0_base; + + if (info->ChipFamily >= CHIP_FAMILY_R600) { + aper0_base = INREG(R600_CONFIG_F0_BASE); + } else { + aper0_base = INREG(RADEON_CONFIG_APER_0_BASE); + } /* Recent chips have an "issue" with the memory controller, the * location must be aligned to the size. We just align it down, @@ -1250,17 +1454,30 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) info->ChipFamily == CHIP_FAMILY_RV410) aper0_base &= ~(mem_size - 1); - info->mc_fb_location = (aper0_base >> 16) | + if (info->ChipFamily >= CHIP_FAMILY_R600) { + info->mc_fb_location = (aper0_base >> 24) | + (((aper0_base + mem_size - 1) & 0xff000000U) >> 8); + ErrorF("mc fb loc is %08x\n", info->mc_fb_location); + } else { + info->mc_fb_location = (aper0_base >> 16) | ((aper0_base + mem_size - 1) & 0xffff0000U); + } } } - info->fbLocation = (info->mc_fb_location & 0xffff) << 16; - + if (info->ChipFamily >= CHIP_FAMILY_R600) { + info->fbLocation = (info->mc_fb_location & 0xffff) << 24; + } else { + info->fbLocation = (info->mc_fb_location & 0xffff) << 16; + } /* Just disable the damn AGP apertures for now, it may be * re-enabled later by the DRM */ - info->mc_agp_location = 0xffffffc0; + if (IS_AVIVO_VARIANT) { + OUTREG(AVIVO_HDP_FB_LOCATION, info->mc_fb_location); + info->mc_agp_location = 0x003f0000; + } else + info->mc_agp_location = 0xffffffc0; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RADEONInitMemoryMap() : \n"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1322,9 +1539,14 @@ static CARD32 RADEONGetAccessibleVRAM(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 aper_size = INREG(RADEON_CONFIG_APER_SIZE) / 1024; + CARD32 aper_size; unsigned char byte; + if (info->ChipFamily >= CHIP_FAMILY_R600) + aper_size = INREG(R600_CONFIG_APER_SIZE) / 1024; + else + aper_size = INREG(RADEON_CONFIG_APER_SIZE) / 1024; + #ifdef XF86DRI /* If we use the DRI, we need to check if it's a version that has the * bug of always cropping MC_FB_LOCATION to one aperture, in which case @@ -1352,7 +1574,8 @@ static CARD32 RADEONGetAccessibleVRAM(ScrnInfoPtr pScrn) info->ChipFamily == CHIP_FAMILY_RV350 || info->ChipFamily == CHIP_FAMILY_RV380 || info->ChipFamily == CHIP_FAMILY_R420 || - info->ChipFamily == CHIP_FAMILY_RV410) { + info->ChipFamily == CHIP_FAMILY_RV410 || + IS_AVIVO_VARIANT) { OUTREGP (RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, ~RADEON_HDP_APER_CNTL); xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1399,13 +1622,18 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024); } else { - /* Read VRAM size from card */ - pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; - - /* Some production boards of m6 will return 0 if it's 8 MB */ - if (pScrn->videoRam == 0) { - pScrn->videoRam = 8192; - OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000); + + if (info->ChipFamily >= CHIP_FAMILY_R600) + pScrn->videoRam = INREG(R600_CONFIG_MEMSIZE) / 1024; + else { + /* Read VRAM size from card */ + pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; + + /* Some production boards of m6 will return 0 if it's 8 MB */ + if (pScrn->videoRam == 0) { + pScrn->videoRam = 8192; + OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000); + } } } @@ -1425,7 +1653,8 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) if (pScrn->videoRam > accessible) pScrn->videoRam = accessible; - info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); + if (!IS_AVIVO_VARIANT) + info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); info->BusCntl = INREG(RADEON_BUS_CNTL); RADEONGetVRamType(pScrn); @@ -1442,6 +1671,21 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, from, "Mapped VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); + if (info->IsPrimary) { + pScrn->videoRam /= 2; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for primary head\n", + pScrn->videoRam); + } + + if (info->IsSecondary) { + pScrn->videoRam /= 2; + info->LinearAddr += pScrn->videoRam * 1024; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Using %dk of videoram for secondary head\n", + pScrn->videoRam); + } + pScrn->videoRam &= ~1023; info->FbMapSize = pScrn->videoRam * 1024; @@ -1550,6 +1794,15 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) break; } + if (info->ChipFamily >= CHIP_FAMILY_R600) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "R600 support is mostly incomplete and very experimental\n"); + } + + if ((info->ChipFamily >= CHIP_FAMILY_RV515) && (info->ChipFamily < CHIP_FAMILY_R600)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "R500 support is under development. Please report any issues to xorg-driver-ati@lists.x.org\n"); + } from = X_PROBED; info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffUL; @@ -1705,6 +1958,14 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) info->Chipset != PCI_CHIP_RN50_5969); #endif + if (info->ChipFamily >= CHIP_FAMILY_R600) { + info->r600_shadow_fb = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "using shadow framebuffer\n"); + if (!xf86LoadSubModule(pScrn, "shadow")) + return FALSE; + xf86LoaderReqSymLists(shadowSymbols, NULL); + } return TRUE; } @@ -1765,6 +2026,12 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) info->useEXA = FALSE; + if (info->ChipFamily >= CHIP_FAMILY_R600) { + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, + "No acceleration support available on R600 yet.\n"); + return TRUE; + } + if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { int errmaj = 0, errmin = 0; @@ -1877,19 +2144,32 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) info->pLibDRMVersion = NULL; info->pKernelDRMVersion = NULL; + if (xf86IsEntityShared(info->pEnt->index)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Direct Rendering Disabled -- " + "Dual-head configuration is not working with " + "DRI at present.\n" + "Please use the radeon MergedFB option if you " + "want Dual-head with DRI.\n"); + return FALSE; + } + if (info->IsSecondary) + return FALSE; + if (info->Chipset == PCI_CHIP_RN50_515E || info->Chipset == PCI_CHIP_RN50_5969 || info->Chipset == PCI_CHIP_RC410_5A61 || info->Chipset == PCI_CHIP_RC410_5A62 || - info->Chipset == PCI_CHIP_RS485_5975) { + info->Chipset == PCI_CHIP_RS485_5975 || + info->ChipFamily >= CHIP_FAMILY_R600) { if (xf86ReturnOptValBool(info->Options, OPTION_DRI, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Direct rendering for RN50/RC410/RS485 forced on -- " + "Direct rendering for RN50/RC410/RS485/R600 forced on -- " "This is NOT officially supported at the hardware level " "and may cause instability or lockups\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Direct rendering not officially supported on RN50/RC410\n"); + "Direct rendering not officially supported on RN50/RC410/R600\n"); return FALSE; } } @@ -2075,7 +2355,7 @@ static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) info->allowColorTiling = xf86ReturnOptValBool(info->Options, OPTION_COLOR_TILING, TRUE); - if (IS_R300_VARIANT) { + if (IS_R300_VARIANT || IS_AVIVO_VARIANT) { /* this may be 4096 on r4xx -- need to double check */ info->MaxSurfaceWidth = 3968; /* one would have thought 4096...*/ info->MaxLines = 4096; @@ -2087,6 +2367,13 @@ static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) if (!info->allowColorTiling) return; + if (info->ChipFamily >= CHIP_FAMILY_R600) + info->allowColorTiling = FALSE; + + /* for zaphod disable tiling for now */ + if (info->IsPrimary || info->IsSecondary) + info->allowColorTiling = FALSE; + #ifdef XF86DRI if (info->directRenderingEnabled && info->pKernelDRMVersion->version_minor < 14) { @@ -2307,12 +2594,41 @@ static void RADEONPreInitBIOS(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) #endif } +static void RADEONFixZaphodOutputs(ScrnInfoPtr pScrn) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + if (info->IsPrimary) { + xf86OutputDestroy(config->output[0]); + while(config->num_output > 1) { + xf86OutputDestroy(config->output[1]); + } + } else { + while(config->num_output > 1) { + xf86OutputDestroy(config->output[1]); + } + } +} + static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); int i; + int mask; - if (!RADEONAllocateControllers(pScrn)) + if (!info->IsPrimary && !info->IsSecondary) + mask = 3; + else if (info->IsPrimary) + mask = 1; + else + mask = 2; + + if (!RADEONAllocateControllers(pScrn, mask)) return FALSE; RADEONGetClockInfo(pScrn); @@ -2320,6 +2636,11 @@ static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn) if (!RADEONSetupConnectors(pScrn)) { return FALSE; } + + if (info->IsPrimary || info->IsSecondary) { + /* fixup outputs for zaphod */ + RADEONFixZaphodOutputs(pScrn); + } RADEONPrintPortMap(pScrn); @@ -2329,6 +2650,10 @@ static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn) output->status = (*output->funcs->detect) (output); ErrorF("finished output detect: %d\n", i); + if (info->IsPrimary || info->IsSecondary) { + if (output->status != XF86OutputStatusConnected) + return FALSE; + } } ErrorF("finished all detect\n"); return TRUE; @@ -2366,6 +2691,8 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) void *int10_save = NULL; const char *s; int crtc_max_X, crtc_max_Y; + RADEONEntPtr pRADEONEnt; + DevUnion* pPriv; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONPreInit\n"); @@ -2376,9 +2703,39 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info = RADEONPTR(pScrn); info->MMIO = NULL; + info->IsSecondary = FALSE; + info->IsPrimary = FALSE; + info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); if (info->pEnt->location.type != BUS_PCI) goto fail; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + getRADEONEntityIndex()); + pRADEONEnt = pPriv->ptr; + + if(xf86IsEntityShared(pScrn->entityList[0])) + { + if(xf86IsPrimInitDone(pScrn->entityList[0])) + { + info->IsSecondary = TRUE; + pRADEONEnt->pSecondaryScrn = pScrn; + info->SavedReg = &pRADEONEnt->SavedReg; + info->ModeReg = &pRADEONEnt->ModeReg; + } + else + { + info->IsPrimary = TRUE; + xf86SetPrimInitDone(pScrn->entityList[0]); + pRADEONEnt->pPrimaryScrn = pScrn; + pRADEONEnt->HasSecondary = FALSE; + info->SavedReg = &pRADEONEnt->SavedReg; + info->ModeReg = &pRADEONEnt->ModeReg; + } + } else { + info->SavedReg = &pRADEONEnt->SavedReg; + info->ModeReg = &pRADEONEnt->ModeReg; + } + info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); info->PciTag = pciTag(PCI_DEV_BUS(info->PciInfo), PCI_DEV_DEV(info->PciInfo), @@ -2545,7 +2902,7 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) crtc_max_X = 1600; crtc_max_Y = 1200; } else { - if (IS_R300_VARIANT) { + if (IS_R300_VARIANT || IS_AVIVO_VARIANT) { crtc_max_X = 2560; crtc_max_Y = 1200; } else { @@ -2726,10 +3083,11 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, /* Make the change through RandR */ #ifdef RANDR_12_INTERFACE - RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); -#else - crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); + if (crtc->randr_crtc) + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); + else #endif + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); } } @@ -3140,15 +3498,6 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, char* s; #endif -#ifdef XF86DRI - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "RADEONScreenInit %lx %ld %d\n", - pScrn->memPhysBase, pScrn->fbOffset, info->frontOffset); -#else - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "RADEONScreenInit %lx %ld\n", - pScrn->memPhysBase, pScrn->fbOffset); -#endif info->accelOn = FALSE; #ifdef USE_XAA @@ -3158,6 +3507,16 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, pScrn->fbOffset = info->frontOffset; #endif + if (info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; +#ifdef XF86DRI + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "RADEONScreenInit %lx %ld %d\n", + pScrn->memPhysBase, pScrn->fbOffset, info->frontOffset); +#else + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONScreenInit %lx %ld\n", + pScrn->memPhysBase, pScrn->fbOffset); +#endif if (!RADEONMapMem(pScrn)) return FALSE; #ifdef XF86DRI @@ -3172,9 +3531,10 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, RADEONSave(pScrn); - RADEONDisableDisplays(pScrn); + if (!IS_AVIVO_VARIANT) + RADEONDisableDisplays(pScrn); - if (info->IsMobility) { + if (info->IsMobility && !IS_AVIVO_VARIANT) { if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { RADEONSetDynamicClock(pScrn, 1); } else { @@ -3373,13 +3733,32 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Initializing fb layer\n"); + + if (info->r600_shadow_fb) { + info->fb_shadow = xcalloc(1, + pScrn->displayWidth * pScrn->virtualY * + ((pScrn->bitsPerPixel + 7) >> 3)); + if (info->fb_shadow == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate shadow framebuffer\n"); + info->r600_shadow_fb = FALSE; + } else { + if (!fbScreenInit(pScreen, info->fb_shadow, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, + pScrn->bitsPerPixel)) + return FALSE; + } + } - /* Init fb layer */ - if (!fbScreenInit(pScreen, info->FB + pScrn->fbOffset, - pScrn->virtualX, pScrn->virtualY, - pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, - pScrn->bitsPerPixel)) - return FALSE; + if (info->r600_shadow_fb == FALSE) { + /* Init fb layer */ + if (!fbScreenInit(pScreen, info->FB, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, + pScrn->bitsPerPixel)) + return FALSE; + } xf86SetBlackWhitePixels(pScreen); @@ -3465,7 +3844,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, * our local image to make sure we restore them properly on mode * changes or VT switches */ - RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg); + RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); if ((info->DispPriority == 1) && (info->cardType==CARD_AGP)) { /* we need to re-calculate bandwidth because of AGPMode difference. */ @@ -3491,6 +3870,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, RADEONChangeSurfaces(pScrn); + /* Enable aceleration */ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, @@ -3553,9 +3933,17 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, RADEONDGAInit(pScreen); /* Init Xv */ - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "Initializing Xv\n"); - RADEONInitVideo(pScreen); + if (!IS_AVIVO_VARIANT) { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Xv\n"); + RADEONInitVideo(pScreen); + } + + if (info->r600_shadow_fb == TRUE) { + if (!shadowSetup(pScreen)) { + return FALSE; + } + } /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ /* Wrap CloseScreen */ @@ -3564,6 +3952,8 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, pScreen->SaveScreen = RADEONSaveScreen; info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; + info->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = RADEONCreateScreenResources; if (!xf86CrtcScreenInit (pScreen)) return FALSE; @@ -3602,184 +3992,252 @@ void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; int timeout; + CARD32 mc_fb_loc, mc_agp_loc, mc_agp_loc_hi; + + radeon_read_mc_fb_agp_location(pScrn, LOC_FB | LOC_AGP, &mc_fb_loc, + &mc_agp_loc, &mc_agp_loc_hi); + if (info->IsSecondary) + return; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RADEONRestoreMemMapRegisters() : \n"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - " MC_FB_LOCATION : 0x%08x\n", - (unsigned)restore->mc_fb_location); + " MC_FB_LOCATION : 0x%08x 0x%08x\n", + (unsigned)restore->mc_fb_location, mc_fb_loc); xf86DrvMsg(pScrn->scrnIndex, X_INFO, " MC_AGP_LOCATION : 0x%08x\n", (unsigned)restore->mc_agp_location); - /* 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 crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl=0, ov0_scale_cntl; - CARD32 old_mc_status, status_idle; + if (IS_AVIVO_VARIANT) { - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - " Map Changed ! Applying ...\n"); + if (mc_fb_loc != restore->mc_fb_location || + mc_agp_loc != restore->mc_agp_location) { + CARD32 tmp; - /* Make sure engine is idle. We assume the CCE is stopped - * at this point - */ - RADEONWaitForIdleMMIO(pScrn); + RADEONWaitForIdleMMIO(pScrn); - if (info->IsIGP) - goto igp_no_mcfb; + OUTREG(AVIVO_D1VGA_CONTROL, INREG(AVIVO_D1VGA_CONTROL) & ~AVIVO_DVGA_CONTROL_MODE_ENABLE); + OUTREG(AVIVO_D2VGA_CONTROL, INREG(AVIVO_D2VGA_CONTROL) & ~AVIVO_DVGA_CONTROL_MODE_ENABLE); - /* Capture MC_STATUS in case things go wrong ... */ - old_mc_status = INREG(RADEON_MC_STATUS); - - /* Stop display & memory access */ - ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL); - OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); - crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); - OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); - crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); - RADEONWaitForVerticalSync(pScrn); - OUTREG(RADEON_CRTC_GEN_CNTL, - (crtc_gen_cntl - & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) - | RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); - - if (pRADEONEnt->HasCRTC2) { - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); - RADEONWaitForVerticalSync2(pScrn); - OUTREG(RADEON_CRTC2_GEN_CNTL, - (crtc2_gen_cntl - & ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) - | RADEON_CRTC2_DISP_REQ_EN_B); - } + /* Stop display & memory access */ + tmp = INREG(AVIVO_D1CRTC_CONTROL); + OUTREG(AVIVO_D1CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN); - /* Make sure the chip settles down (paranoid !) */ - usleep(100000); + tmp = INREG(AVIVO_D2CRTC_CONTROL); + OUTREG(AVIVO_D2CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN); - /* Wait for MC idle */ - if (IS_R300_VARIANT) - status_idle = R300_MC_IDLE; - else - status_idle = RADEON_MC_IDLE; + tmp = INREG(AVIVO_D2CRTC_CONTROL); - timeout = 0; - while (!(INREG(RADEON_MC_STATUS) & status_idle)) { - if (++timeout > 1000000) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Timeout trying to update memory controller settings !\n"); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "MC_STATUS = 0x%08x (on entry = 0x%08x)\n", - INREG(RADEON_MC_STATUS), (unsigned int)old_mc_status); - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "You will probably crash now ... \n"); - /* Nothing we can do except maybe try to kill the server, - * let's wait 2 seconds to leave the above message a chance - * to maybe hit the disk and continue trying to setup despite - * the MC being non-idle - */ - usleep(2000000); + usleep(10000); + timeout = 0; + while (!(avivo_get_mc_idle(pScrn))) { + if (++timeout > 1000000) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Timeout trying to update memory controller settings !\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "You will probably crash now ... \n"); + /* Nothing we can do except maybe try to kill the server, + * let's wait 2 seconds to leave the above message a chance + * to maybe hit the disk and continue trying to setup despite + * the MC being non-idle + */ + usleep(2000000); + } + usleep(10); } - usleep(10); + + radeon_write_mc_fb_agp_location(pScrn, LOC_FB | LOC_AGP, + restore->mc_fb_location, + restore->mc_agp_location, + restore->mc_agp_location_hi); + + if (info->ChipFamily < CHIP_FAMILY_R600) { + OUTREG(AVIVO_HDP_FB_LOCATION, restore->mc_fb_location); + } + + /* Reset the engine and HDP */ + RADEONEngineReset(pScrn); } + } else { - /* Update maps, first clearing out AGP to make sure we don't get - * a temporary overlap + /* Write memory mapping registers only if their value change + * since we must ensure no access is done while they are + * reprogrammed */ - OUTREG(RADEON_MC_AGP_LOCATION, 0xfffffffc); - OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location); - igp_no_mcfb: - OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location); - /* Make sure map fully reached the chip */ - (void)INREG(RADEON_MC_FB_LOCATION); + if (mc_fb_loc != restore->mc_fb_location || + mc_agp_loc != restore->mc_agp_location) { + CARD32 crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl=0, ov0_scale_cntl; + CARD32 old_mc_status, status_idle; - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - " Map applied, resetting engine ...\n"); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + " Map Changed ! Applying ...\n"); - /* Reset the engine and HDP */ - RADEONEngineReset(pScrn); + /* Make sure engine is idle. We assume the CCE is stopped + * at this point + */ + RADEONWaitForIdleMMIO(pScrn); - /* Make sure we have sane offsets before re-enabling the CRTCs, disable - * stereo, clear offsets, and wait for offsets to catch up with hw - */ + if (info->IsIGP) + goto igp_no_mcfb; - OUTREG(RADEON_CRTC_OFFSET_CNTL, RADEON_CRTC_OFFSET_FLIP_CNTL); - OUTREG(RADEON_CRTC_OFFSET, 0); - OUTREG(RADEON_CUR_OFFSET, 0); - timeout = 0; - while(INREG(RADEON_CRTC_OFFSET) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) { - if (timeout++ > 1000000) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Timeout waiting for CRTC offset to update !\n"); - break; + /* Capture MC_STATUS in case things go wrong ... */ + old_mc_status = INREG(RADEON_MC_STATUS); + + /* Stop display & memory access */ + ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL); + OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); + crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); + OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); + crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); + RADEONWaitForVerticalSync(pScrn); + OUTREG(RADEON_CRTC_GEN_CNTL, + (crtc_gen_cntl + & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) + | RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); + + if (pRADEONEnt->HasCRTC2) { + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + RADEONWaitForVerticalSync2(pScrn); + OUTREG(RADEON_CRTC2_GEN_CNTL, + (crtc2_gen_cntl + & ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) + | RADEON_CRTC2_DISP_REQ_EN_B); } - usleep(1000); - } - if (pRADEONEnt->HasCRTC2) { - OUTREG(RADEON_CRTC2_OFFSET_CNTL, RADEON_CRTC2_OFFSET_FLIP_CNTL); - OUTREG(RADEON_CRTC2_OFFSET, 0); - OUTREG(RADEON_CUR2_OFFSET, 0); + + /* Make sure the chip settles down (paranoid !) */ + usleep(100000); + + /* Wait for MC idle */ + if (IS_R300_VARIANT) + status_idle = R300_MC_IDLE; + else + status_idle = RADEON_MC_IDLE; + + timeout = 0; + while (!(INREG(RADEON_MC_STATUS) & status_idle)) { + if (++timeout > 1000000) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Timeout trying to update memory controller settings !\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MC_STATUS = 0x%08x (on entry = 0x%08x)\n", + INREG(RADEON_MC_STATUS), (unsigned int)old_mc_status); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "You will probably crash now ... \n"); + /* Nothing we can do except maybe try to kill the server, + * let's wait 2 seconds to leave the above message a chance + * to maybe hit the disk and continue trying to setup despite + * the MC being non-idle + */ + usleep(2000000); + } + usleep(10); + } + + /* Update maps, first clearing out AGP to make sure we don't get + * a temporary overlap + */ + OUTREG(RADEON_MC_AGP_LOCATION, 0xfffffffc); + OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location); + radeon_write_mc_fb_agp_location(pScrn, LOC_FB | LOC_AGP, restore->mc_fb_location, + 0xfffffffc, 0); + igp_no_mcfb: + radeon_write_mc_fb_agp_location(pScrn, LOC_AGP, 0, + restore->mc_agp_location, 0); + /* Make sure map fully reached the chip */ + (void)INREG(RADEON_MC_FB_LOCATION); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + " Map applied, resetting engine ...\n"); + + /* Reset the engine and HDP */ + RADEONEngineReset(pScrn); + + /* Make sure we have sane offsets before re-enabling the CRTCs, disable + * stereo, clear offsets, and wait for offsets to catch up with hw + */ + + OUTREG(RADEON_CRTC_OFFSET_CNTL, RADEON_CRTC_OFFSET_FLIP_CNTL); + OUTREG(RADEON_CRTC_OFFSET, 0); + OUTREG(RADEON_CUR_OFFSET, 0); timeout = 0; - while(INREG(RADEON_CRTC2_OFFSET) & RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET) { + while(INREG(RADEON_CRTC_OFFSET) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) { if (timeout++ > 1000000) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Timeout waiting for CRTC2 offset to update !\n"); + "Timeout waiting for CRTC offset to update !\n"); break; } usleep(1000); } + if (pRADEONEnt->HasCRTC2) { + OUTREG(RADEON_CRTC2_OFFSET_CNTL, RADEON_CRTC2_OFFSET_FLIP_CNTL); + OUTREG(RADEON_CRTC2_OFFSET, 0); + OUTREG(RADEON_CUR2_OFFSET, 0); + timeout = 0; + while(INREG(RADEON_CRTC2_OFFSET) & RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET) { + if (timeout++ > 1000000) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Timeout waiting for CRTC2 offset to update !\n"); + break; + } + usleep(1000); + } + } } - } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "Updating display base addresses...\n"); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Updating display base addresses...\n"); - OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); - if (pRADEONEnt->HasCRTC2) - OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr); - OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr); - (void)INREG(RADEON_OV0_BASE_ADDR); + OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); + if (pRADEONEnt->HasCRTC2) + OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr); + OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr); + (void)INREG(RADEON_OV0_BASE_ADDR); - /* More paranoia delays, wait 100ms */ - usleep(100000); + /* More paranoia delays, wait 100ms */ + usleep(100000); - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "Memory map updated.\n"); - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Memory map updated.\n"); + } +} #ifdef XF86DRI static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD32 fb, agp; - - fb = INREG(RADEON_MC_FB_LOCATION); - agp = INREG(RADEON_MC_AGP_LOCATION); + CARD32 fb, agp, agp_hi; + int changed; - if (fb != info->mc_fb_location || agp != info->mc_agp_location) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "DRI init changed memory map, adjusting ...\n"); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - " MC_FB_LOCATION was: 0x%08x is: 0x%08x\n", - (unsigned)info->mc_fb_location, (unsigned)fb); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - " MC_AGP_LOCATION was: 0x%08x is: 0x%08x\n", - (unsigned)info->mc_agp_location, (unsigned)agp); - info->mc_fb_location = fb; - info->mc_agp_location = agp; - info->fbLocation = (save->mc_fb_location & 0xffff) << 16; - info->dst_pitch_offset = - (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) - << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10)); + if (info->IsSecondary) + return; + radeon_read_mc_fb_agp_location(pScrn, LOC_FB | LOC_AGP, &fb, &agp, &agp_hi); + + if (fb != info->mc_fb_location || agp != info->mc_agp_location || + agp_hi || info->mc_agp_location_hi) + changed = 1; - RADEONInitMemMapRegisters(pScrn, save, info); + if (changed) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRI init changed memory map, adjusting ...\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " MC_FB_LOCATION was: 0x%08lx is: 0x%08lx\n", + info->mc_fb_location, fb); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " MC_AGP_LOCATION was: 0x%08lx is: 0x%08lx\n", + info->mc_agp_location, agp); + info->mc_fb_location = fb; + info->mc_agp_location = agp; + if (info->ChipFamily >= CHIP_FAMILY_R600) + info->fbLocation = (info->mc_fb_location & 0xffff) << 24; + else + info->fbLocation = (info->mc_fb_location & 0xffff) << 16; - /* Adjust the various offsets */ - RADEONRestoreMemMapRegisters(pScrn, save); + info->dst_pitch_offset = + (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) + << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10)); + RADEONInitMemMapRegisters(pScrn, save, info); + RADEONRestoreMemMapRegisters(pScrn, save); } #ifdef USE_EXA @@ -3814,6 +4272,9 @@ void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; + if (info->IsSecondary) + return; + OUTREG(RADEON_OVR_CLR, restore->ovr_clr); OUTREG(RADEON_OVR_WID_LEFT_RIGHT, restore->ovr_wid_left_right); OUTREG(RADEON_OVR_WID_TOP_BOTTOM, restore->ovr_wid_top_bottom); @@ -4680,7 +5141,7 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) #endif if (info->ChipFamily < CHIP_FAMILY_R200) { color_pattern = RADEON_SURF_TILE_COLOR_MACRO; - } else if (IS_R300_VARIANT) { + } else if (IS_R300_VARIANT || IS_AVIVO_VARIANT) { color_pattern = R300_SURF_TILE_COLOR_MACRO; } else { color_pattern = R200_SURF_TILE_COLOR_MACRO; @@ -4719,7 +5180,7 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) drmsurfalloc.flags = swap_pattern; if (info->tilingEnabled) { - if (IS_R300_VARIANT) + if (IS_R300_VARIANT || IS_AVIVO_VARIANT) drmsurfalloc.flags |= (width_bytes / 8) | color_pattern; else drmsurfalloc.flags |= (width_bytes / 16) | color_pattern; @@ -4744,7 +5205,7 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) depth_pattern = RADEON_SURF_TILE_DEPTH_16BPP; else depth_pattern = RADEON_SURF_TILE_DEPTH_32BPP; - } else if (IS_R300_VARIANT) { + } else if (IS_R300_VARIANT || IS_AVIVO_VARIANT) { if (depthCpp == 2) depth_pattern = R300_SURF_TILE_COLOR_MACRO; else @@ -4764,7 +5225,7 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) drmRadeonSurfaceAlloc drmsurfalloc; drmsurfalloc.size = depthBufferSize; drmsurfalloc.address = info->depthOffset; - if (IS_R300_VARIANT) + if (IS_R300_VARIANT || IS_AVIVO_VARIANT) drmsurfalloc.flags = swap_pattern | (depth_width_bytes / 8) | depth_pattern; else drmsurfalloc.flags = swap_pattern | (depth_width_bytes / 16) | depth_pattern; @@ -4782,7 +5243,7 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) unsigned char *RADEONMMIO = info->MMIO; /* we don't need anything like WaitForFifo, no? */ if (info->tilingEnabled) { - if (IS_R300_VARIANT) + if (IS_R300_VARIANT || IS_AVIVO_VARIANT) surf_info |= (width_bytes / 8) | color_pattern; else surf_info |= (width_bytes / 16) | color_pattern; @@ -4796,7 +5257,7 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) } /* Update surface images */ - RADEONSaveSurfaces(pScrn, &info->ModeReg); + RADEONSaveSurfaces(pScrn, info->ModeReg); } /* Read memory map */ @@ -4805,11 +5266,14 @@ 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); + radeon_read_mc_fb_agp_location(pScrn, LOC_FB | LOC_AGP, &save->mc_fb_location, + &save->mc_agp_location, &save->mc_agp_location_hi); + + if (!IS_AVIVO_VARIANT) { + 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 */ @@ -5118,13 +5582,326 @@ static void RADEONSavePalette(ScrnInfoPtr pScrn, RADEONSavePtr save) } #endif +void avivo_save(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + struct avivo_state *state = &save->avivo; + + // state->vga_memory_base = INREG(AVIVO_VGA_MEMORY_BASE); + // state->vga_fb_start = INREG(AVIVO_VGA_FB_START); + state->vga1_cntl = INREG(AVIVO_D1VGA_CONTROL); + state->vga2_cntl = INREG(AVIVO_D2VGA_CONTROL); + + state->crtc_master_en = INREG(AVIVO_DC_CRTC_MASTER_EN); + state->crtc_tv_control = INREG(AVIVO_DC_CRTC_TV_CONTROL); + + state->pll1.ref_div_src = INREG(AVIVO_EXT1_PPLL_REF_DIV_SRC); + state->pll1.ref_div = INREG(AVIVO_EXT1_PPLL_REF_DIV); + state->pll1.fb_div = INREG(AVIVO_EXT1_PPLL_FB_DIV); + state->pll1.post_div_src = INREG(AVIVO_EXT1_PPLL_POST_DIV_SRC); + state->pll1.post_div = INREG(AVIVO_EXT1_PPLL_POST_DIV); + state->pll1.ext_ppll_cntl = INREG(AVIVO_EXT1_PPLL_CNTL); + state->pll1.pll_cntl = INREG(AVIVO_P1PLL_CNTL); + state->pll1.int_ss_cntl = INREG(AVIVO_P1PLL_INT_SS_CNTL); + + state->pll2.ref_div_src = INREG(AVIVO_EXT1_PPLL_REF_DIV_SRC); + state->pll2.ref_div = INREG(AVIVO_EXT2_PPLL_REF_DIV); + state->pll2.fb_div = INREG(AVIVO_EXT2_PPLL_FB_DIV); + state->pll2.post_div_src = INREG(AVIVO_EXT2_PPLL_POST_DIV_SRC); + state->pll2.post_div = INREG(AVIVO_EXT2_PPLL_POST_DIV); + state->pll2.ext_ppll_cntl = INREG(AVIVO_EXT2_PPLL_CNTL); + state->pll2.pll_cntl = INREG(AVIVO_P2PLL_CNTL); + state->pll2.int_ss_cntl = INREG(AVIVO_P2PLL_INT_SS_CNTL); + + state->crtc1.pll_source = INREG(AVIVO_PCLK_CRTC1_CNTL); + + state->crtc1.h_total = INREG(AVIVO_D1CRTC_H_TOTAL); + state->crtc1.h_blank_start_end = INREG(AVIVO_D1CRTC_H_BLANK_START_END); + state->crtc1.h_sync_a = INREG(AVIVO_D1CRTC_H_SYNC_A); + state->crtc1.h_sync_a_cntl = INREG(AVIVO_D1CRTC_H_SYNC_A_CNTL); + state->crtc1.h_sync_b = INREG(AVIVO_D1CRTC_H_SYNC_B); + state->crtc1.h_sync_b_cntl = INREG(AVIVO_D1CRTC_H_SYNC_B_CNTL); + + state->crtc1.v_total = INREG(AVIVO_D1CRTC_V_TOTAL); + state->crtc1.v_blank_start_end = INREG(AVIVO_D1CRTC_V_BLANK_START_END); + state->crtc1.v_sync_a = INREG(AVIVO_D1CRTC_V_SYNC_A); + state->crtc1.v_sync_a_cntl = INREG(AVIVO_D1CRTC_V_SYNC_A_CNTL); + state->crtc1.v_sync_b = INREG(AVIVO_D1CRTC_V_SYNC_B); + state->crtc1.v_sync_b_cntl = INREG(AVIVO_D1CRTC_V_SYNC_B_CNTL); + + state->crtc1.control = INREG(AVIVO_D1CRTC_CONTROL); + state->crtc1.blank_control = INREG(AVIVO_D1CRTC_BLANK_CONTROL); + state->crtc1.interlace_control = INREG(AVIVO_D1CRTC_INTERLACE_CONTROL); + state->crtc1.stereo_control = INREG(AVIVO_D1CRTC_STEREO_CONTROL); + + state->crtc1.cursor_control = INREG(AVIVO_D1CUR_CONTROL); + + state->grph1.enable = INREG(AVIVO_D1GRPH_ENABLE); + state->grph1.control = INREG(AVIVO_D1GRPH_CONTROL); + state->grph1.control = INREG(AVIVO_D1GRPH_CONTROL); + state->grph1.prim_surf_addr = INREG(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS); + state->grph1.sec_surf_addr = INREG(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS); + state->grph1.pitch = INREG(AVIVO_D1GRPH_PITCH); + state->grph1.x_offset = INREG(AVIVO_D1GRPH_SURFACE_OFFSET_X); + state->grph1.y_offset = INREG(AVIVO_D1GRPH_SURFACE_OFFSET_Y); + state->grph1.x_start = INREG(AVIVO_D1GRPH_X_START); + state->grph1.y_start = INREG(AVIVO_D1GRPH_Y_START); + state->grph1.x_end = INREG(AVIVO_D1GRPH_X_END); + state->grph1.y_end = INREG(AVIVO_D1GRPH_Y_END); + + state->grph1.viewport_start = INREG(AVIVO_D1MODE_VIEWPORT_START); + state->grph1.viewport_size = INREG(AVIVO_D1MODE_VIEWPORT_SIZE); + state->grph1.scl_enable = INREG(AVIVO_D1SCL_SCALER_ENABLE); + + state->crtc2.pll_source = INREG(AVIVO_PCLK_CRTC2_CNTL); + + state->crtc2.h_total = INREG(AVIVO_D2CRTC_H_TOTAL); + state->crtc2.h_blank_start_end = INREG(AVIVO_D2CRTC_H_BLANK_START_END); + state->crtc2.h_sync_a = INREG(AVIVO_D2CRTC_H_SYNC_A); + state->crtc2.h_sync_a_cntl = INREG(AVIVO_D2CRTC_H_SYNC_A_CNTL); + state->crtc2.h_sync_b = INREG(AVIVO_D2CRTC_H_SYNC_B); + state->crtc2.h_sync_b_cntl = INREG(AVIVO_D2CRTC_H_SYNC_B_CNTL); + + state->crtc2.v_total = INREG(AVIVO_D2CRTC_V_TOTAL); + state->crtc2.v_blank_start_end = INREG(AVIVO_D2CRTC_V_BLANK_START_END); + state->crtc2.v_sync_a = INREG(AVIVO_D2CRTC_V_SYNC_A); + state->crtc2.v_sync_a_cntl = INREG(AVIVO_D2CRTC_V_SYNC_A_CNTL); + state->crtc2.v_sync_b = INREG(AVIVO_D2CRTC_V_SYNC_B); + state->crtc2.v_sync_b_cntl = INREG(AVIVO_D2CRTC_V_SYNC_B_CNTL); + + state->crtc2.control = INREG(AVIVO_D2CRTC_CONTROL); + state->crtc2.blank_control = INREG(AVIVO_D2CRTC_BLANK_CONTROL); + state->crtc2.interlace_control = INREG(AVIVO_D2CRTC_INTERLACE_CONTROL); + state->crtc2.stereo_control = INREG(AVIVO_D2CRTC_STEREO_CONTROL); + + state->crtc2.cursor_control = INREG(AVIVO_D2CUR_CONTROL); + + state->grph2.enable = INREG(AVIVO_D2GRPH_ENABLE); + state->grph2.control = INREG(AVIVO_D2GRPH_CONTROL); + state->grph2.control = INREG(AVIVO_D2GRPH_CONTROL); + state->grph2.prim_surf_addr = INREG(AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS); + state->grph2.sec_surf_addr = INREG(AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS); + state->grph2.pitch = INREG(AVIVO_D2GRPH_PITCH); + state->grph2.x_offset = INREG(AVIVO_D2GRPH_SURFACE_OFFSET_X); + state->grph2.y_offset = INREG(AVIVO_D2GRPH_SURFACE_OFFSET_Y); + state->grph2.x_start = INREG(AVIVO_D2GRPH_X_START); + state->grph2.y_start = INREG(AVIVO_D2GRPH_Y_START); + state->grph2.x_end = INREG(AVIVO_D2GRPH_X_END); + state->grph2.y_end = INREG(AVIVO_D2GRPH_Y_END); + + state->grph2.viewport_start = INREG(AVIVO_D2MODE_VIEWPORT_START); + state->grph2.viewport_size = INREG(AVIVO_D2MODE_VIEWPORT_SIZE); + state->grph2.scl_enable = INREG(AVIVO_D2SCL_SCALER_ENABLE); + + state->daca.enable = INREG(AVIVO_DACA_ENABLE); + state->daca.source_select = INREG(AVIVO_DACA_SOURCE_SELECT); + state->daca.force_output_cntl = INREG(AVIVO_DACA_FORCE_OUTPUT_CNTL); + state->daca.powerdown = INREG(AVIVO_DACA_POWERDOWN); + + state->dacb.enable = INREG(AVIVO_DACB_ENABLE); + state->dacb.source_select = INREG(AVIVO_DACB_SOURCE_SELECT); + state->dacb.force_output_cntl = INREG(AVIVO_DACB_FORCE_OUTPUT_CNTL); + state->dacb.powerdown = INREG(AVIVO_DACB_POWERDOWN); + + state->tmds1.cntl = INREG(AVIVO_TMDSA_CNTL); + state->tmds1.source_select = INREG(AVIVO_TMDSA_SOURCE_SELECT); + state->tmds1.bit_depth_cntl = INREG(AVIVO_TMDSA_BIT_DEPTH_CONTROL); + state->tmds1.data_sync = INREG(AVIVO_TMDSA_DATA_SYNCHRONIZATION); + state->tmds1.transmitter_enable = INREG(AVIVO_TMDSA_TRANSMITTER_ENABLE); + state->tmds1.transmitter_cntl = INREG(AVIVO_TMDSA_TRANSMITTER_CONTROL); + + state->tmds2.cntl = INREG(AVIVO_LVTMA_CNTL); + state->tmds2.source_select = INREG(AVIVO_LVTMA_SOURCE_SELECT); + state->tmds2.bit_depth_cntl = INREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL); + state->tmds2.data_sync = INREG(AVIVO_LVTMA_DATA_SYNCHRONIZATION); + + if (info->ChipFamily >= CHIP_FAMILY_R600) { + state->tmds2.transmitter_enable = INREG(R600_LVTMA_TRANSMITTER_ENABLE); + state->tmds2.transmitter_cntl = INREG(R600_LVTMA_TRANSMITTER_CONTROL); + state->lvtma_pwrseq_cntl = INREG(R600_LVTMA_PWRSEQ_CNTL); + state->lvtma_pwrseq_state = INREG(R600_LVTMA_PWRSEQ_STATE); + } else { + state->tmds2.transmitter_enable = INREG(R500_LVTMA_TRANSMITTER_ENABLE); + state->tmds2.transmitter_cntl = INREG(R500_LVTMA_TRANSMITTER_CONTROL); + state->lvtma_pwrseq_cntl = INREG(R500_LVTMA_PWRSEQ_CNTL); + state->lvtma_pwrseq_state = INREG(R500_LVTMA_PWRSEQ_STATE); + } + + if (state->crtc1.control & AVIVO_CRTC_EN) + info->crtc_on = TRUE; + + if (state->crtc2.control & AVIVO_CRTC_EN) + info->crtc2_on = TRUE; + +} + +void avivo_restore(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + struct avivo_state *state = &restore->avivo; + + // OUTMC(pScrn, AVIVO_MC_MEMORY_MAP, state->mc_memory_map); + // OUTREG(AVIVO_VGA_MEMORY_BASE, state->vga_memory_base); + // OUTREG(AVIVO_VGA_FB_START, state->vga_fb_start); + + + OUTREG(AVIVO_DC_CRTC_MASTER_EN, state->crtc_master_en); + OUTREG(AVIVO_DC_CRTC_TV_CONTROL, state->crtc_tv_control); + + OUTREG(AVIVO_EXT1_PPLL_REF_DIV_SRC, state->pll1.ref_div_src); + OUTREG(AVIVO_EXT1_PPLL_REF_DIV, state->pll1.ref_div); + OUTREG(AVIVO_EXT1_PPLL_FB_DIV, state->pll1.fb_div); + OUTREG(AVIVO_EXT1_PPLL_POST_DIV_SRC, state->pll1.post_div_src); + OUTREG(AVIVO_EXT1_PPLL_POST_DIV, state->pll1.post_div); + OUTREG(AVIVO_EXT1_PPLL_CNTL, state->pll1.ext_ppll_cntl); + OUTREG(AVIVO_P1PLL_CNTL, state->pll1.pll_cntl); + OUTREG(AVIVO_P1PLL_INT_SS_CNTL, state->pll1.int_ss_cntl); + + OUTREG(AVIVO_EXT2_PPLL_REF_DIV_SRC, state->pll2.ref_div_src); + OUTREG(AVIVO_EXT2_PPLL_REF_DIV, state->pll2.ref_div); + OUTREG(AVIVO_EXT2_PPLL_FB_DIV, state->pll2.fb_div); + OUTREG(AVIVO_EXT2_PPLL_POST_DIV_SRC, state->pll2.post_div_src); + OUTREG(AVIVO_EXT2_PPLL_POST_DIV, state->pll2.post_div); + OUTREG(AVIVO_EXT2_PPLL_CNTL, state->pll2.ext_ppll_cntl); + OUTREG(AVIVO_P2PLL_CNTL, state->pll2.pll_cntl); + OUTREG(AVIVO_P2PLL_INT_SS_CNTL, state->pll2.int_ss_cntl); + + OUTREG(AVIVO_PCLK_CRTC1_CNTL, state->crtc1.pll_source); + + OUTREG(AVIVO_D1CRTC_H_TOTAL, state->crtc1.h_total); + OUTREG(AVIVO_D1CRTC_H_BLANK_START_END, state->crtc1.h_blank_start_end); + OUTREG(AVIVO_D1CRTC_H_SYNC_A, state->crtc1.h_sync_a); + OUTREG(AVIVO_D1CRTC_H_SYNC_A_CNTL, state->crtc1.h_sync_a_cntl); + OUTREG(AVIVO_D1CRTC_H_SYNC_B, state->crtc1.h_sync_b); + OUTREG(AVIVO_D1CRTC_H_SYNC_B_CNTL, state->crtc1.h_sync_b_cntl); + + OUTREG(AVIVO_D1CRTC_V_TOTAL, state->crtc1.v_total); + OUTREG(AVIVO_D1CRTC_V_BLANK_START_END, state->crtc1.v_blank_start_end); + OUTREG(AVIVO_D1CRTC_V_SYNC_A, state->crtc1.v_sync_a); + OUTREG(AVIVO_D1CRTC_V_SYNC_A_CNTL, state->crtc1.v_sync_a_cntl); + OUTREG(AVIVO_D1CRTC_V_SYNC_B, state->crtc1.v_sync_b); + OUTREG(AVIVO_D1CRTC_V_SYNC_B_CNTL, state->crtc1.v_sync_b_cntl); + + OUTREG(AVIVO_D1CRTC_CONTROL, state->crtc1.control); + OUTREG(AVIVO_D1CRTC_BLANK_CONTROL, state->crtc1.blank_control); + OUTREG(AVIVO_D1CRTC_INTERLACE_CONTROL, state->crtc1.interlace_control); + OUTREG(AVIVO_D1CRTC_STEREO_CONTROL, state->crtc1.stereo_control); + + OUTREG(AVIVO_D1CUR_CONTROL, state->crtc1.cursor_control); + + OUTREG(AVIVO_D1GRPH_ENABLE, state->grph1.enable); + OUTREG(AVIVO_D1GRPH_CONTROL, state->grph1.control); + OUTREG(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS, state->grph1.prim_surf_addr); + OUTREG(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS, state->grph1.sec_surf_addr); + OUTREG(AVIVO_D1GRPH_PITCH, state->grph1.pitch); + OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_X, state->grph1.x_offset); + OUTREG(AVIVO_D1GRPH_SURFACE_OFFSET_Y, state->grph1.y_offset); + OUTREG(AVIVO_D1GRPH_X_START, state->grph1.x_start); + OUTREG(AVIVO_D1GRPH_Y_START, state->grph1.y_start); + OUTREG(AVIVO_D1GRPH_X_END, state->grph1.x_end); + OUTREG(AVIVO_D1GRPH_Y_END, state->grph1.y_end); + + OUTREG(AVIVO_D1MODE_VIEWPORT_START, state->grph1.viewport_start); + OUTREG(AVIVO_D1MODE_VIEWPORT_SIZE, state->grph1.viewport_size); + OUTREG(AVIVO_D1SCL_SCALER_ENABLE, state->grph1.scl_enable); + + OUTREG(AVIVO_PCLK_CRTC2_CNTL, state->crtc2.pll_source); + + OUTREG(AVIVO_D2CRTC_H_TOTAL, state->crtc2.h_total); + OUTREG(AVIVO_D2CRTC_H_BLANK_START_END, state->crtc2.h_blank_start_end); + OUTREG(AVIVO_D2CRTC_H_SYNC_A, state->crtc2.h_sync_a); + OUTREG(AVIVO_D2CRTC_H_SYNC_A_CNTL, state->crtc2.h_sync_a_cntl); + OUTREG(AVIVO_D2CRTC_H_SYNC_B, state->crtc2.h_sync_b); + OUTREG(AVIVO_D2CRTC_H_SYNC_B_CNTL, state->crtc2.h_sync_b_cntl); + + OUTREG(AVIVO_D2CRTC_V_TOTAL, state->crtc2.v_total); + OUTREG(AVIVO_D2CRTC_V_BLANK_START_END, state->crtc2.v_blank_start_end); + OUTREG(AVIVO_D2CRTC_V_SYNC_A, state->crtc2.v_sync_a); + OUTREG(AVIVO_D2CRTC_V_SYNC_A_CNTL, state->crtc2.v_sync_a_cntl); + OUTREG(AVIVO_D2CRTC_V_SYNC_B, state->crtc2.v_sync_b); + OUTREG(AVIVO_D2CRTC_V_SYNC_B_CNTL, state->crtc2.v_sync_b_cntl); + + OUTREG(AVIVO_D2CRTC_CONTROL, state->crtc2.control); + OUTREG(AVIVO_D2CRTC_BLANK_CONTROL, state->crtc2.blank_control); + OUTREG(AVIVO_D2CRTC_INTERLACE_CONTROL, state->crtc2.interlace_control); + OUTREG(AVIVO_D2CRTC_STEREO_CONTROL, state->crtc2.stereo_control); + + OUTREG(AVIVO_D2CUR_CONTROL, state->crtc2.cursor_control); + + OUTREG(AVIVO_D2GRPH_ENABLE, state->grph2.enable); + OUTREG(AVIVO_D2GRPH_CONTROL, state->grph2.control); + OUTREG(AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS, state->grph2.prim_surf_addr); + OUTREG(AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS, state->grph2.sec_surf_addr); + OUTREG(AVIVO_D2GRPH_PITCH, state->grph2.pitch); + OUTREG(AVIVO_D2GRPH_SURFACE_OFFSET_X, state->grph2.x_offset); + OUTREG(AVIVO_D2GRPH_SURFACE_OFFSET_Y, state->grph2.y_offset); + OUTREG(AVIVO_D2GRPH_X_START, state->grph2.x_start); + OUTREG(AVIVO_D2GRPH_Y_START, state->grph2.y_start); + OUTREG(AVIVO_D2GRPH_X_END, state->grph2.x_end); + OUTREG(AVIVO_D2GRPH_Y_END, state->grph2.y_end); + + OUTREG(AVIVO_D2MODE_VIEWPORT_START, state->grph2.viewport_start); + OUTREG(AVIVO_D2MODE_VIEWPORT_SIZE, state->grph2.viewport_size); + OUTREG(AVIVO_D2SCL_SCALER_ENABLE, state->grph2.scl_enable); + + + OUTREG(AVIVO_DACA_ENABLE, state->daca.enable); + OUTREG(AVIVO_DACA_SOURCE_SELECT, state->daca.source_select); + OUTREG(AVIVO_DACA_FORCE_OUTPUT_CNTL, state->daca.force_output_cntl); + OUTREG(AVIVO_DACA_POWERDOWN, state->daca.powerdown); + + OUTREG(AVIVO_TMDSA_CNTL, state->tmds1.cntl); + OUTREG(AVIVO_TMDSA_BIT_DEPTH_CONTROL, state->tmds1.bit_depth_cntl); + OUTREG(AVIVO_TMDSA_DATA_SYNCHRONIZATION, state->tmds1.data_sync); + OUTREG(AVIVO_TMDSA_TRANSMITTER_ENABLE, state->tmds1.transmitter_enable); + OUTREG(AVIVO_TMDSA_TRANSMITTER_CONTROL, state->tmds1.transmitter_cntl); + OUTREG(AVIVO_TMDSA_SOURCE_SELECT, state->tmds1.source_select); + + OUTREG(AVIVO_DACB_ENABLE, state->dacb.enable); + OUTREG(AVIVO_DACB_SOURCE_SELECT, state->dacb.source_select); + OUTREG(AVIVO_DACB_FORCE_OUTPUT_CNTL, state->dacb.force_output_cntl); + OUTREG(AVIVO_DACB_POWERDOWN, state->dacb.powerdown); + + OUTREG(AVIVO_LVTMA_CNTL, state->tmds2.cntl); + OUTREG(AVIVO_LVTMA_BIT_DEPTH_CONTROL, state->tmds2.bit_depth_cntl); + OUTREG(AVIVO_LVTMA_DATA_SYNCHRONIZATION, state->tmds2.data_sync); + OUTREG(AVIVO_LVTMA_SOURCE_SELECT, state->tmds2.source_select); + + if (info->ChipFamily >= CHIP_FAMILY_R600) { + OUTREG(R600_LVTMA_TRANSMITTER_ENABLE, state->tmds2.transmitter_enable); + OUTREG(R600_LVTMA_TRANSMITTER_CONTROL, state->tmds2.transmitter_cntl); + OUTREG(R600_LVTMA_PWRSEQ_CNTL, state->lvtma_pwrseq_cntl); + OUTREG(R600_LVTMA_PWRSEQ_STATE, state->lvtma_pwrseq_state); + } else { + OUTREG(R500_LVTMA_TRANSMITTER_ENABLE, state->tmds2.transmitter_enable); + OUTREG(R500_LVTMA_TRANSMITTER_CONTROL, state->tmds2.transmitter_cntl); + OUTREG(R500_LVTMA_PWRSEQ_CNTL, state->lvtma_pwrseq_cntl); + OUTREG(R500_LVTMA_PWRSEQ_STATE, state->lvtma_pwrseq_state); + } + + OUTREG(AVIVO_D1VGA_CONTROL, state->vga1_cntl); + OUTREG(AVIVO_D2VGA_CONTROL, state->vga2_cntl); +} + +void avivo_restore_vga_regs(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + struct avivo_state *state = &restore->avivo; + + OUTREG(AVIVO_D1VGA_CONTROL, state->vga1_cntl); + OUTREG(AVIVO_D2VGA_CONTROL, state->vga2_cntl); +} + /* Save everything needed to restore the original VC state */ static void RADEONSave(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONSavePtr save = &info->SavedReg; + RADEONSavePtr save = info->SavedReg; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONSave\n"); @@ -5148,26 +5925,33 @@ static void RADEONSave(ScrnInfoPtr pScrn) vgaHWLock(hwp); } #endif - save->dp_datatype = INREG(RADEON_DP_DATATYPE); - save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); - RADEONPllErrataAfterIndex(info); - RADEONSaveMemMapRegisters(pScrn, save); - RADEONSaveCommonRegisters(pScrn, save); - RADEONSavePLLRegisters(pScrn, save); - RADEONSaveCrtcRegisters(pScrn, save); - RADEONSaveFPRegisters(pScrn, save); - RADEONSaveBIOSRegisters(pScrn, save); - RADEONSaveDACRegisters(pScrn, save); - if (pRADEONEnt->HasCRTC2) { - RADEONSaveCrtc2Registers(pScrn, save); - RADEONSavePLL2Registers(pScrn, save); - } - if (info->InternalTVOut) - RADEONSaveTVRegisters(pScrn, save); - - RADEONSaveSurfaces(pScrn, save); + if (IS_AVIVO_VARIANT) { + RADEONSaveMemMapRegisters(pScrn, save); + avivo_save(pScrn, save); + } else { + save->dp_datatype = INREG(RADEON_DP_DATATYPE); + save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); + save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); + RADEONPllErrataAfterIndex(info); + + RADEONSaveMemMapRegisters(pScrn, save); + RADEONSaveCommonRegisters(pScrn, save); + RADEONSavePLLRegisters(pScrn, save); + RADEONSaveCrtcRegisters(pScrn, save); + RADEONSaveFPRegisters(pScrn, save); + RADEONSaveBIOSRegisters(pScrn, save); + RADEONSaveDACRegisters(pScrn, save); + if (pRADEONEnt->HasCRTC2) { + RADEONSaveCrtc2Registers(pScrn, save); + RADEONSavePLL2Registers(pScrn, save); + } + if (info->InternalTVOut) + RADEONSaveTVRegisters(pScrn, save); + } + + RADEONSaveSurfaces(pScrn, save); + } /* Restore the original (text) mode */ @@ -5176,7 +5960,7 @@ void RADEONRestore(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONSavePtr restore = &info->SavedReg; + RADEONSavePtr restore = info->SavedReg; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); xf86CrtcPtr crtc; @@ -5190,33 +5974,40 @@ void RADEONRestore(ScrnInfoPtr pScrn) RADEONBlank(pScrn); - OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); - RADEONPllErrataAfterIndex(info); - OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); - OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); - OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); - OUTREG(RADEON_GRPH2_BUFFER_CNTL, restore->grph2_buffer_cntl); + if (IS_AVIVO_VARIANT) { + RADEONRestoreMemMapRegisters(pScrn, restore); + avivo_restore(pScrn, restore); + } else { + OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); + RADEONPllErrataAfterIndex(info); + OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); + OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); + OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); + OUTREG(RADEON_GRPH2_BUFFER_CNTL, restore->grph2_buffer_cntl); - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); + if (!info->IsSecondary) { + RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); - if (pRADEONEnt->HasCRTC2) { - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - } + if (pRADEONEnt->HasCRTC2) { + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + } - RADEONRestoreBIOSRegisters(pScrn, restore); - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - RADEONRestoreRMXRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - RADEONRestoreFP2Registers(pScrn, restore); - RADEONRestoreLVDSRegisters(pScrn, restore); + RADEONRestoreBIOSRegisters(pScrn, restore); + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); + RADEONRestoreRMXRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + RADEONRestoreFP2Registers(pScrn, restore); + RADEONRestoreLVDSRegisters(pScrn, restore); - if (info->InternalTVOut) - RADEONRestoreTVRegisters(pScrn, restore); + if (info->InternalTVOut) + RADEONRestoreTVRegisters(pScrn, restore); + } - RADEONRestoreSurfaces(pScrn, restore); + RADEONRestoreSurfaces(pScrn, restore); + } #if 1 /* Temp fix to "solve" VT switch problems. When switching VTs on @@ -5244,8 +6035,8 @@ void RADEONRestore(ScrnInfoPtr pScrn) #endif /* need to make sure we don't enable a crtc by accident or we may get a hang */ - if (pRADEONEnt->HasCRTC2) { - if (info->crtc2_on) { + if (pRADEONEnt->HasCRTC2 && !info->IsSecondary) { + if (info->crtc2_on && xf86_config->num_crtc > 1) { crtc = xf86_config->crtc[1]; crtc->funcs->dpms(crtc, DPMSModeOn); } @@ -5257,6 +6048,8 @@ void RADEONRestore(ScrnInfoPtr pScrn) /* to restore console mode, DAC registers should be set after every other registers are set, * otherwise,we may get blank screen */ + if (IS_AVIVO_VARIANT) + avivo_restore_vga_regs(pScrn, restore); RADEONRestoreDACRegisters(pScrn, restore); #if 0 @@ -5470,7 +6263,7 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, Bool crtc2) crtcoffsetcntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; #endif if (info->tilingEnabled) { - if (IS_R300_VARIANT) { + if (IS_R300_VARIANT || IS_AVIVO_VARIANT) { /* On r300/r400 when tiling is enabled crtc_offset is set to the address of * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc * Makes tiling MUCH easier. @@ -5527,7 +6320,7 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, Bool crtc2) } #endif - if (IS_R300_VARIANT) { + if (IS_R300_VARIANT || IS_AVIVO_VARIANT) { OUTREG(xytilereg, crtcxytile); } else { OUTREG(regcntl, crtcoffsetcntl); @@ -5614,7 +6407,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) } - RADEONRestoreSurfaces(pScrn, &info->ModeReg); + RADEONRestoreSurfaces(pScrn, info->ModeReg); #ifdef XF86DRI if (info->directRenderingEnabled) { if (info->cardType == CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19 && info->FbSecureSize) @@ -5626,7 +6419,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) /* get the DRI back into shape after resume */ RADEONDRISetVBlankInterrupt (pScrn, TRUE); RADEONDRIResume(pScrn->pScreen); - RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg); + RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); } #endif |