? Makefile ? dualhead.diff ? r128.4.html ? r128._man ? r128dh.diff ? radeon.4.html ? radeon._man Index: r128.h =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v retrieving revision 1.3 diff -u -r1.3 r128.h --- r128.h 16 Jun 2004 09:43:58 -0000 1.3 +++ r128.h 7 Nov 2004 07:56:08 -0000 @@ -135,6 +135,13 @@ /* CRTC2 registers */ CARD32 crtc2_gen_cntl; + CARD32 crtc2_h_total_disp; + CARD32 crtc2_h_sync_strt_wid; + CARD32 crtc2_v_total_disp; + CARD32 crtc2_v_sync_strt_wid; + CARD32 crtc2_offset; + CARD32 crtc2_offset_cntl; + CARD32 crtc2_pitch; /* Flat panel registers */ CARD32 fp_crtc_h_total_disp; @@ -160,13 +167,29 @@ CARD32 ppll_div_3; CARD32 htotal_cntl; + /* Computed values for PLL2 */ + CARD32 dot_clock_freq_2; + CARD32 pll_output_freq_2; + int feedback_div_2; + int post_div_2; + + /* PLL2 registers */ + CARD32 p2pll_ref_div; + CARD32 p2pll_div_0; + CARD32 htotal_cntl2; + /* DDA register */ CARD32 dda_config; CARD32 dda_on_off; + /* DDA2 register */ + CARD32 dda2_config; + CARD32 dda2_on_off; + /* Pallet */ Bool palette_valid; CARD32 palette[256]; + CARD32 palette2[256]; } R128SaveRec, *R128SavePtr; typedef struct { @@ -186,6 +209,25 @@ DisplayModePtr mode; } R128FBLayout; +typedef enum +{ + MT_NONE, + MT_CRT, + MT_LCD, + MT_DFP, + MT_CTV, + MT_STV +}R128MonitorType; + +typedef enum +{ + DDC_NONE_DETECTED, + DDC_MONID, + DDC_DVI, + DDC_VGA, + DDC_CRT2 +}R128DDCType; + typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; @@ -401,6 +443,14 @@ I2CBusPtr pI2CBus; CARD32 DDCReg; + /****** Added for dualhead support *******************/ + BOOL HasCRTC2; /* M3/M4 */ + BOOL IsSecondary; /* second Screen */ + BOOL UseCRT; /* force use CRT port as primary */ + BOOL SwitchingMode; + R128MonitorType DisplayType; /* Monitor connected on*/ + R128DDCType DDCType; + } R128InfoRec, *R128InfoPtr; #define R128WaitForFifo(pScrn, entries) \ Index: r128_accel.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c,v retrieving revision 1.3 diff -u -r1.3 r128_accel.c --- r128_accel.c 16 Jun 2004 09:43:58 -0000 1.3 +++ r128_accel.c 7 Nov 2004 07:56:09 -0000 @@ -82,6 +82,7 @@ /* Driver data structures */ #include "r128.h" #include "r128_reg.h" +#include "r128_probe.h" #ifdef XF86DRI #include "r128_sarea.h" #define _XF86DRI_SERVER_ @@ -117,6 +118,8 @@ { R128_ROP3_ONE, R128_ROP3_ONE } /* GXset */ }; +extern int gR128EntityIndex; + /* Flush all dirty data in the Pixel Cache to memory. */ void R128EngineFlush(ScrnInfoPtr pScrn) { @@ -1017,7 +1020,7 @@ R128TRACE(("Pitch for acceleration = %d\n", info->pitch)); R128WaitForFifo(pScrn, 2); - OUTREG(R128_DEFAULT_OFFSET, 0); + OUTREG(R128_DEFAULT_OFFSET, pScrn->fbOffset); OUTREG(R128_DEFAULT_PITCH, info->pitch); R128WaitForFifo(pScrn, 4); @@ -1641,6 +1644,25 @@ &indirect, sizeof(drmR128Indirect)); } +/* This callback is required for multihead cards using XAA */ +static +void R128RestoreCCEAccelState(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); +/* unsigned char *R128MMIO = info->MMIO; needed for OUTREG below */ + /*xf86DrvMsg(pScrn->scrnIndex, X_INFO, "===>RestoreCP\n");*/ + + R128WaitForFifo(pScrn, 1); +/* is this needed on r128 + OUTREG( R128_DEFAULT_OFFSET, info->frontPitchOffset); +*/ + R128WaitForIdle(pScrn); + + /* FIXME: May need to restore other things, + like BKGD_CLK FG_CLK...*/ + +} + static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) { R128InfoPtr info = R128PTR(pScrn); @@ -1701,9 +1723,32 @@ | HARDWARE_PATTERN_PROGRAMMED_ORIGIN | HARDWARE_PATTERN_SCREEN_ORIGIN | BIT_ORDER_IN_BYTE_LSBFIRST); + + if(!info->IsSecondary && xf86IsEntityShared(pScrn->entityList[0])) + a->RestoreAccelState = R128RestoreCCEAccelState; + + } #endif +/* This callback is required for multihead cards using XAA */ +static +void R128RestoreAccelState(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + R128WaitForFifo(pScrn, 2); + OUTREG(R128_DEFAULT_OFFSET, pScrn->fbOffset); + OUTREG(R128_DEFAULT_PITCH, info->pitch); + + /* FIXME: May need to restore other things, + like BKGD_CLK FG_CLK...*/ + + R128WaitForIdle(pScrn); + +} + static void R128MMIOAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) { R128InfoPtr info = R128PTR(pScrn); @@ -1782,6 +1827,22 @@ | LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X | SCANLINE_PAD_DWORD; + + if(xf86IsEntityShared(pScrn->entityList[0])) + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + + /*if there are more than one devices sharing this entity, we + have to assign this call back, otherwise the XAA will be + disabled */ + if(pR128Ent->HasSecondary || pR128Ent->BypassSecondary) + a->RestoreAccelState = R128RestoreAccelState; + } + } /* Initialize XAA for supported acceleration and also initialize the Index: r128_cursor.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c,v retrieving revision 1.2 diff -u -r1.2 r128_cursor.c --- r128_cursor.c 23 Apr 2004 19:26:46 -0000 1.2 +++ r128_cursor.c 7 Nov 2004 07:56:09 -0000 @@ -72,8 +72,16 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - OUTREG(R128_CUR_CLR0, bg); - OUTREG(R128_CUR_CLR1, fg); + if(info->IsSecondary) + { + OUTREG(R128_CUR2_CLR0, bg); + OUTREG(R128_CUR2_CLR1, fg); + } + else + { + OUTREG(R128_CUR_CLR0, bg); + OUTREG(R128_CUR_CLR1, fg); + } } /* Set cursor position to (x,y) with offset into cursor bitmap at @@ -94,11 +102,25 @@ if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin); - OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK + if(!info->IsSecondary) + { + OUTREG(R128_CUR_HORZ_VERT_OFF, R128_CUR_LOCK | (xorigin << 16) | yorigin); + OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); - OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16); + OUTREG(R128_CUR_OFFSET, info->cursor_start + yorigin * 16); + } + else + { + OUTREG(R128_CUR2_HORZ_VERT_OFF, (R128_CUR2_LOCK + | (xorigin << 16) + | yorigin)); + OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK + | ((xorigin ? 0 : x) << 16) + | (yorigin ? 0 : y))); + OUTREG(R128_CUR2_OFFSET, + info->cursor_start + pScrn->fbOffset + yorigin * 16); + } } /* Copy cursor image from `image' to video memory. R128SetCursorPosition @@ -112,8 +134,16 @@ int y; CARD32 save; - save = INREG(R128_CRTC_GEN_CNTL); - OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN); + if(!info->IsSecondary) + { + save = INREG(R128_CRTC_GEN_CNTL); + OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN); + } + else + { + save = INREG(R128_CRTC2_GEN_CNTL); + OUTREG(R128_CRTC2_GEN_CNTL, save & (CARD32)~R128_CRTC2_CUR_EN); + } #if X_BYTE_ORDER == X_BIG_ENDIAN switch(info->CurrentLayout.pixel_bytes) { @@ -169,7 +199,11 @@ } - OUTREG(R128_CRTC_GEN_CNTL, save); + if(!info->IsSecondary) + OUTREG(R128_CRTC_GEN_CNTL, save); + else + OUTREG(R128_CRTC2_GEN_CNTL, save); + } /* Hide hardware cursor. */ @@ -178,7 +212,10 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); + if(info->IsSecondary) + OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN); + else + OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN); } /* Show hardware cursor. */ @@ -187,7 +224,16 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); + if(info->IsSecondary) + { + OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN, + ~R128_CRTC2_CUR_EN); + } + else + { + OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN); + } + } /* Determine if hardware cursor is in use. */ Index: r128_driver.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c,v retrieving revision 1.13 diff -u -r1.13 r128_driver.c --- r128_driver.c 17 Oct 2004 22:45:57 -0000 1.13 +++ r128_driver.c 7 Nov 2004 07:56:11 -0000 @@ -353,6 +353,8 @@ NULL); } +extern int gR128EntityIndex; + /* Allocate our private R128InfoRec. */ static Bool R128GetRec(ScrnInfoPtr pScrn) { @@ -461,7 +463,7 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); + OUTREG8(R128_CLOCK_CNTL_INDEX, addr & 0x3f); return INREG(R128_CLOCK_CNTL_DATA); } @@ -495,10 +497,46 @@ { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - if(info->isDFP) - OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS); + + if(!info->IsSecondary) + { + switch(info->DisplayType) + { + case MT_LCD: + OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_DISPLAY_DIS, + ~R128_LVDS_DISPLAY_DIS); + break; + case MT_CRT: + OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS); + break; + case MT_DFP: + OUTREGP(R128_FP_GEN_CNTL, R128_FP_BLANK_DIS, ~R128_FP_BLANK_DIS); + break; +#if 0 + OUTREGP(R128_CRTC_EXT_CNTL, + R128_CRTC_DISPLAY_DIS | + R128_CRTC_VSYNC_DIS | + R128_CRTC_HSYNC_DIS, + ~(R128_CRTC_DISPLAY_DIS | + R128_CRTC_VSYNC_DIS | + R128_CRTC_HSYNC_DIS)); + break; +#endif + case MT_NONE: + default: + break; + } + } else - OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_DISPLAY_DIS, ~R128_CRTC_DISPLAY_DIS); + { + OUTREGP(R128_CRTC2_GEN_CNTL, + R128_CRTC2_DISP_DIS | + R128_CRTC2_VSYNC_DIS | + R128_CRTC2_HSYNC_DIS, + ~(R128_CRTC2_DISP_DIS | + R128_CRTC2_VSYNC_DIS | + R128_CRTC2_HSYNC_DIS)); + } } /* Unblank screen. */ @@ -507,12 +545,50 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - if(info->isDFP) - OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS); + if(!info->IsSecondary) + { + switch(info->DisplayType) + { + case MT_LCD: + OUTREGP(R128_LVDS_GEN_CNTL, 0, + ~R128_LVDS_DISPLAY_DIS); + break; + case MT_CRT: + OUTREGP(R128_CRTC_EXT_CNTL, 0, ~R128_CRTC_DISPLAY_DIS); + break; + case MT_DFP: + OUTREGP(R128_FP_GEN_CNTL, 0, ~R128_FP_BLANK_DIS); +#if 0 + OUTREGP(R128_CRTC_EXT_CNTL, + R128_CRTC_CRT_ON, + ~(R128_CRTC_DISPLAY_DIS | + R128_CRTC_VSYNC_DIS | + R128_CRTC_HSYNC_DIS)); + break; +#endif + case MT_NONE: + default: + break; + } + } else - OUTREGP(R128_CRTC_EXT_CNTL, 0, ~(R128_CRTC_DISPLAY_DIS | - R128_CRTC_VSYNC_DIS | - R128_CRTC_HSYNC_DIS)); + { + switch(info->DisplayType) + { + case MT_LCD: + case MT_DFP: + case MT_CRT: + OUTREGP(R128_CRTC2_GEN_CNTL, + 0, + ~(R128_CRTC2_DISP_DIS | + R128_CRTC2_VSYNC_DIS | + R128_CRTC2_HSYNC_DIS)); + break; + case MT_NONE: + default: + break; + } + } } /* Compute log base 2 of val. */ @@ -575,7 +651,73 @@ "Video BIOS not found!\n"); } - if (info->VBIOS && info->HasPanelRegs) { + if(info->HasCRTC2) + { + if(info->IsSecondary) + { + /* there may be a way to detect this, for now, just assume + second head is CRT */ + info->DisplayType = MT_CRT; + + if(info->DisplayType > MT_NONE) + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + pR128Ent->HasSecondary = TRUE; + + } + else return FALSE; + + } + else + { + /* really need some sort of detection here */ + if (info->HasPanelRegs) { + info->DisplayType = MT_LCD; + } else if (info->isDFP) { + info->DisplayType = MT_DFP; + } else + { + /*DVI port has no monitor connected, try CRT port. + If something on CRT port, treat it as primary*/ + if(xf86IsEntityShared(pScrn->entityList[0])) + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + pR128Ent->BypassSecondary = TRUE; + } + + info->DisplayType = MT_CRT; +#if 0 + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No monitor detected!!!\n"); + return FALSE; + } +#endif + } + } + } + else + { + /*Regular Radeon ASIC, only one CRTC, but it could be + used for DFP with a DVI output, like AIW board*/ + if(info->isDFP) info->DisplayType = MT_DFP; + else info->DisplayType = MT_CRT; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n", + (info->IsSecondary ? "Secondary" : "Primary"), + info->DisplayType); + + + if (info->VBIOS && info->DisplayType == MT_LCD) { info->FPBIOSstart = 0; /* FIXME: There should be direct access to the start of the FP info @@ -923,6 +1065,7 @@ } else { info->isDFP = FALSE; info->isPro2 = FALSE; + info->HasCRTC2 = FALSE; switch (info->Chipset) { /* R128 Pro and Pro2 can have DFP, we will deal with it. No support for dual-head/xinerama yet. @@ -972,7 +1115,11 @@ case PCI_CHIP_RAGE128LE: case PCI_CHIP_RAGE128LF: case PCI_CHIP_RAGE128MF: - case PCI_CHIP_RAGE128ML: info->HasPanelRegs = TRUE; break; + case PCI_CHIP_RAGE128ML: + info->HasPanelRegs = TRUE; + /* which chips support dualhead? */ + info->HasCRTC2 = TRUE; + break; case PCI_CHIP_RAGE128RE: case PCI_CHIP_RAGE128RF: case PCI_CHIP_RAGE128RG: @@ -1005,6 +1152,23 @@ else pScrn->videoRam = INREG(R128_CONFIG_MEMSIZE) / 1024; + if(info->IsSecondary) + { + /*FIXME: For now, split FB into two equal sections. This should + be able to be adjusted by user with a config option*/ + DevUnion* pPriv; + R128EntPtr pR128Ent; + R128InfoPtr info1; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + pScrn->videoRam /= 2; + pR128Ent->pPrimaryScrn->videoRam = pScrn->videoRam; + info1 = R128PTR(pR128Ent->pPrimaryScrn); + info1->FbMapSize = pScrn->videoRam * 1024; + info->LinearAddr += pScrn->videoRam * 1024; + } + info->MemCntl = INREG(R128_MEM_CNTL); info->BusCntl = INREG(R128_BUS_CNTL); @@ -1863,9 +2027,41 @@ info = R128PTR(pScrn); + info->IsSecondary = FALSE; + info->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); if (info->pEnt->location.type != BUS_PCI) goto fail; + if(xf86IsEntityShared(pScrn->entityList[0])) + { + if(xf86IsPrimInitDone(pScrn->entityList[0])) + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + info->IsSecondary = TRUE; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + if(pR128Ent->BypassSecondary) return FALSE; + pR128Ent->pSecondaryScrn = pScrn; + } + else + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + xf86SetPrimInitDone(pScrn->entityList[0]); + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + pR128Ent->pPrimaryScrn = pScrn; + pR128Ent->IsDRIEnabled = FALSE; + pR128Ent->BypassSecondary = FALSE; + pR128Ent->HasSecondary = FALSE; + pR128Ent->RestorePrimary = FALSE; + pR128Ent->IsSecondaryRestored = FALSE; + } + } + if (flags & PROBE_DETECT) { R128ProbeDDC(pScrn, info->pEnt->index); return TRUE; @@ -2003,12 +2199,20 @@ { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - int i; + int i, j; int idx; unsigned char r, g, b; + /* If the second monitor is connected, we also + need to deal with the secondary palette*/ + if (info->IsSecondary) j = 1; + else j = 0; + + PAL_SELECT(j); + + /* Select palette 0 (main CRTC) if using FP-enabled chip */ - if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0); + /*if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0);*/ if (info->CurrentLayout.depth == 15) { /* 15bpp mode. This sends 32 values. */ @@ -2086,6 +2290,7 @@ if (!R128MapMem(pScrn)) return FALSE; pScrn->fbOffset = 0; + if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; #ifdef XF86DRI info->fbX = 0; info->fbY = 0; @@ -2139,7 +2344,33 @@ info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024); info->directRenderingEnabled = FALSE; } else { - info->directRenderingEnabled = R128DRIScreenInit(pScreen); + if(info->IsSecondary) + info->directRenderingEnabled = FALSE; + else + { + /* Xinerama has sync problem with DRI, disable it for now */ + if(xf86IsEntityShared(pScrn->entityList[0])) + { + info->directRenderingEnabled = FALSE; + xf86DrvMsg(scrnIndex, X_WARNING, + "Direct Rendering Disabled -- " + "Dual-head configuration is not working with DRI " + "at present.\nPlease use only one Device/Screen " + "section in your XFConfig file.\n"); + } + else + info->directRenderingEnabled = + R128DRIScreenInit(pScreen); + if(xf86IsEntityShared(pScrn->entityList[0])) + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + pR128Ent->IsDRIEnabled = info->directRenderingEnabled; + } + } } } #endif @@ -2452,11 +2683,12 @@ /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */ if (info->FBDev) xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0); + else { - if (!info->HasPanelRegs || info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) - xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0); - else if (info->HasPanelRegs || info->BIOSDisplay == R128_BIOS_DISPLAY_FP) + if (info->DisplayType == MT_LCD) xf86DPMSInit(pScreen, R128DisplayPowerManagementSetLCD, 0); + else + xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0); } R128InitVideo(pScreen); @@ -2540,6 +2772,32 @@ OUTREG(R128_CRTC_PITCH, restore->crtc_pitch); } +/* Write CRTC2 registers. */ +static void R128RestoreCrtc2Registers(ScrnInfoPtr pScrn, + R128SavePtr restore) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + +/* OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);*/ + OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl, + R128_CRTC2_VSYNC_DIS | + R128_CRTC2_HSYNC_DIS | + R128_CRTC2_DISP_DIS); + +/* OUTREG(R128_DAC_CNTL2, restore->dac2_cntl); + OUTREG(R128_DISP_OUTPUT_CNTL, restore->disp_output_cntl);*/ + + OUTREG(R128_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); + OUTREG(R128_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); + OUTREG(R128_CRTC2_V_TOTAL_DISP, restore->crtc2_v_total_disp); + OUTREG(R128_CRTC2_V_SYNC_STRT_WID, restore->crtc2_v_sync_strt_wid); + OUTREG(R128_CRTC2_OFFSET, restore->crtc2_offset); + OUTREG(R128_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); + OUTREG(R128_CRTC2_PITCH, restore->crtc2_pitch); + +} + /* Write flat panel registers */ static void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) { @@ -2589,7 +2847,27 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W, 0xffff); + while (INPLL(pScrn, R128_PPLL_REF_DIV) & R128_PPLL_ATOMIC_UPDATE_R); + + OUTPLLP(pScrn, R128_PPLL_REF_DIV, R128_PPLL_ATOMIC_UPDATE_W, + ~R128_PPLL_ATOMIC_UPDATE_W); +} + +static void R128PLL2WaitForReadUpdateComplete(ScrnInfoPtr pScrn) +{ + while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); +} + +static void R128PLL2WriteUpdate(ScrnInfoPtr pScrn) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + while (INPLL(pScrn, R128_P2PLL_REF_DIV) & R128_P2PLL_ATOMIC_UPDATE_R); + + OUTPLLP(pScrn, R128_P2PLL_REF_DIV, + R128_P2PLL_ATOMIC_UPDATE_W, + ~(R128_P2PLL_ATOMIC_UPDATE_W)); } /* Write PLL registers. */ @@ -2598,33 +2876,44 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, 0xffff); + + OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, + R128_VCLK_SRC_SEL_CPUCLK, + ~(R128_VCLK_SRC_SEL_MASK)); OUTPLLP(pScrn, R128_PPLL_CNTL, R128_PPLL_RESET | R128_PPLL_ATOMIC_UPDATE_EN | R128_PPLL_VGA_ATOMIC_UPDATE_EN, - 0xffff); + ~(R128_PPLL_RESET + | R128_PPLL_ATOMIC_UPDATE_EN + | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); - R128PLLWaitForReadUpdateComplete(pScrn); + OUTREGP(R128_CLOCK_CNTL_INDEX, R128_PLL_DIV_SEL, ~(R128_PLL_DIV_SEL)); + + /* R128PLLWaitForReadUpdateComplete(pScrn);*/ OUTPLLP(pScrn, R128_PPLL_REF_DIV, restore->ppll_ref_div, ~R128_PPLL_REF_DIV_MASK); - R128PLLWriteUpdate(pScrn); + /* R128PLLWriteUpdate(pScrn);*/ - R128PLLWaitForReadUpdateComplete(pScrn); + /* R128PLLWaitForReadUpdateComplete(pScrn);*/ OUTPLLP(pScrn, R128_PPLL_DIV_3, restore->ppll_div_3, ~R128_PPLL_FB3_DIV_MASK); - R128PLLWriteUpdate(pScrn); + /*R128PLLWriteUpdate(pScrn);*/ OUTPLLP(pScrn, R128_PPLL_DIV_3, restore->ppll_div_3, ~R128_PPLL_POST3_DIV_MASK); - R128PLLWriteUpdate(pScrn); + R128PLLWriteUpdate(pScrn); R128PLLWaitForReadUpdateComplete(pScrn); + OUTPLL(R128_HTOTAL_CNTL, restore->htotal_cntl); - R128PLLWriteUpdate(pScrn); + /*R128PLLWriteUpdate(pScrn);*/ - OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~R128_PPLL_RESET); + OUTPLLP(pScrn, R128_PPLL_CNTL, 0, ~(R128_PPLL_RESET + | R128_PPLL_SLEEP + | R128_PPLL_ATOMIC_UPDATE_EN + | R128_PPLL_VGA_ATOMIC_UPDATE_EN)); R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", restore->ppll_ref_div, @@ -2635,6 +2924,85 @@ restore->ppll_ref_div & R128_PPLL_REF_DIV_MASK, restore->ppll_div_3 & R128_PPLL_FB3_DIV_MASK, (restore->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16)); + + usleep(5000); /* let the clock lock */ + + OUTPLLP(pScrn, R128_VCLK_ECP_CNTL, + R128_VCLK_SRC_SEL_PPLLCLK, + ~(R128_VCLK_SRC_SEL_MASK)); + +} + +/* Write PLL2 registers. */ +static void R128RestorePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + + OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, + R128_V2CLK_SRC_SEL_CPUCLK, + ~R128_V2CLK_SRC_SEL_MASK); + + OUTPLLP(pScrn, + R128_P2PLL_CNTL, + R128_P2PLL_RESET + | R128_P2PLL_ATOMIC_UPDATE_EN + | R128_P2PLL_VGA_ATOMIC_UPDATE_EN, + ~(R128_P2PLL_RESET + | R128_P2PLL_ATOMIC_UPDATE_EN + | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); + +#if 0 + OUTREGP(R128_CLOCK_CNTL_INDEX, 0, R128_PLL2_DIV_SEL_MASK); +#endif + + /* R128PLL2WaitForReadUpdateComplete(pScrn);*/ + + OUTPLLP(pScrn, R128_P2PLL_REF_DIV, restore->p2pll_ref_div, ~R128_P2PLL_REF_DIV_MASK); + + /* R128PLL2WriteUpdate(pScrn); + R128PLL2WaitForReadUpdateComplete(pScrn); + */ + OUTPLLP(pScrn, R128_P2PLL_DIV_0, + restore->p2pll_div_0, ~R128_P2PLL_FB0_DIV_MASK); + /* + R128PLL2WriteUpdate(pScrn); + R128PLL2WaitForReadUpdateComplete(pScrn); + */ + ErrorF("p2pll_div_0 POST0 mask\n"); + OUTPLLP(pScrn, R128_P2PLL_DIV_0, + restore->p2pll_div_0, ~R128_P2PLL_POST0_DIV_MASK); + + R128PLL2WriteUpdate(pScrn); + R128PLL2WaitForReadUpdateComplete(pScrn); + + OUTPLL(R128_HTOTAL2_CNTL, restore->htotal_cntl2); + + /* R128PLL2WriteUpdate(pScrn);*/ + + OUTPLLP(pScrn, R128_P2PLL_CNTL, 0, ~(R128_P2PLL_RESET + | R128_P2PLL_SLEEP + | R128_P2PLL_ATOMIC_UPDATE_EN + | R128_P2PLL_VGA_ATOMIC_UPDATE_EN)); + + R128TRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + restore->p2pll_ref_div, + restore->p2pll_div_0, + restore->htotal_cntl2, + INPLL(pScrn, RADEON_P2PLL_CNTL))); + R128TRACE(("Wrote: rd=%d, fd=%d, pd=%d\n", + restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + restore->p2pll_div_0 & RADEON_P2PLL_FB3_DIV_MASK, + (restore->p2pll_div_0 & RADEON_P2PLL_POST3_DIV_MASK) >>16)); + + usleep(5000); /* Let the clock to lock */ + + OUTPLLP(pScrn, R128_V2CLK_VCLKTV_CNTL, + R128_V2CLK_SRC_SEL_P2PLLCLK, + ~R128_V2CLK_SRC_SEL_MASK); + + } /* Write DDA registers. */ @@ -2647,6 +3015,16 @@ OUTREG(R128_DDA_ON_OFF, restore->dda_on_off); } +/* Write DDA registers. */ +static void R128RestoreDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr restore) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + OUTREG(R128_DDA2_CONFIG, restore->dda2_config); + OUTREG(R128_DDA2_ON_OFF, restore->dda2_on_off); +} + /* Write palette data. */ static void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore) { @@ -2656,27 +3034,122 @@ if (!restore->palette_valid) return; +#if 0 /* Select palette 0 (main CRTC) if using FP-enabled chip */ if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0); OUTPAL_START(0); for (i = 0; i < 256; i++) OUTPAL_NEXT_CARD32(restore->palette[i]); +#endif + +/* from radeon_driver.c */ + PAL_SELECT(1); + OUTPAL_START(0); + for (i = 0; i < 256; i++) { + R128WaitForFifo(pScrn, 32); /* delay */ + OUTPAL_NEXT_CARD32(restore->palette2[i]); + } + + PAL_SELECT(0); + OUTPAL_START(0); + for (i = 0; i < 256; i++) { + R128WaitForFifo(pScrn, 32); /* delay */ + OUTPAL_NEXT_CARD32(restore->palette[i]); + } + } /* Write out state to define a new video mode. */ static void R128RestoreMode(ScrnInfoPtr pScrn, R128SavePtr restore) { R128InfoPtr info = R128PTR(pScrn); + DevUnion* pPriv; + R128EntPtr pR128Ent; + static R128SaveRec restore0; R128TRACE(("R128RestoreMode(%p)\n", restore)); - R128RestoreCommonRegisters(pScrn, restore); - R128RestoreCrtcRegisters(pScrn, restore); - if (!(info->HasPanelRegs) || info->BIOSDisplay == R128_BIOS_DISPLAY_CRT){ + if(!info->HasCRTC2) + { + R128RestoreCommonRegisters(pScrn, restore); + R128RestoreDDARegisters(pScrn, restore); + R128RestoreCrtcRegisters(pScrn, restore); + if((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD)) + { + R128RestoreFPRegisters(pScrn, restore); + } R128RestorePLLRegisters(pScrn, restore); + return; + } + + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + + + /***** + When changing mode with Dual-head card (VE/M6), care must + be taken for the special order in setting registers. CRTC2 has + to be set before changing CRTC_EXT register. + In the dual-head setup, X server calls this routine twice with + primary and secondary pScrn pointers respectively. The calls + can come with different 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. + *****/ + + if(info->IsSecondary) + { + if (!pR128Ent->RestorePrimary && !info->SwitchingMode) + R128RestoreCommonRegisters(pScrn, restore); + R128RestoreDDA2Registers(pScrn, restore); + R128RestoreCrtc2Registers(pScrn, restore); + R128RestorePLL2Registers(pScrn, restore); + + if(info->SwitchingMode) return; + + pR128Ent->IsSecondaryRestored = TRUE; + + if(pR128Ent->RestorePrimary) + { + R128InfoPtr info0 = R128PTR(pR128Ent->pPrimaryScrn); + pR128Ent->RestorePrimary = FALSE; + + R128RestoreCrtcRegisters(pScrn, &restore0); + if((info0->DisplayType == MT_DFP) || + (info0->DisplayType == MT_LCD)) + { + R128RestoreFPRegisters(pScrn, &restore0); + } + + R128RestorePLLRegisters(pScrn, &restore0); + pR128Ent->IsSecondaryRestored = FALSE; + + } + } + else + { + if (!pR128Ent->IsSecondaryRestored) + R128RestoreCommonRegisters(pScrn, restore); + R128RestoreDDARegisters(pScrn, restore); + if(!pR128Ent->HasSecondary || pR128Ent->IsSecondaryRestored + || info->SwitchingMode) + { + pR128Ent->IsSecondaryRestored = FALSE; + R128RestoreCrtcRegisters(pScrn, restore); + if((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD)) + { + R128RestoreFPRegisters(pScrn, restore); + } + R128RestorePLLRegisters(pScrn, restore); + } + else + { + memcpy(&restore0, restore, sizeof(restore0)); + pR128Ent->RestorePrimary = TRUE; + } } - R128RestoreDDARegisters(pScrn, restore); - if (info->HasPanelRegs || info->isDFP) - R128RestoreFPRegisters(pScrn, restore); R128RestorePalette(pScrn, restore); } @@ -2727,7 +3200,7 @@ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); + /*save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL);*/ save->fp_crtc_h_total_disp = INREG(R128_FP_CRTC_H_TOTAL_DISP); save->fp_crtc_v_total_disp = INREG(R128_FP_CRTC_V_TOTAL_DISP); save->fp_gen_cntl = INREG(R128_FP_GEN_CNTL); @@ -2741,6 +3214,24 @@ save->tmds_transmitter_cntl = INREG(R128_TMDS_TRANSMITTER_CNTL); } +/* Read CRTC2 registers. */ +static void R128SaveCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + /*save->dac_cntl = INREG(R128_DAC_CNTL);*/ + + save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); + save->crtc2_h_total_disp = INREG(R128_CRTC2_H_TOTAL_DISP); + save->crtc2_h_sync_strt_wid = INREG(R128_CRTC2_H_SYNC_STRT_WID); + save->crtc2_v_total_disp = INREG(R128_CRTC2_V_TOTAL_DISP); + save->crtc2_v_sync_strt_wid = INREG(R128_CRTC2_V_SYNC_STRT_WID); + save->crtc2_offset = INREG(R128_CRTC2_OFFSET); + save->crtc2_offset_cntl = INREG(R128_CRTC2_OFFSET_CNTL); + save->crtc2_pitch = INREG(R128_CRTC2_PITCH); +} + /* Read PLL registers. */ static void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save) { @@ -2758,6 +3249,23 @@ (save->ppll_div_3 & R128_PPLL_POST3_DIV_MASK) >> 16)); } +/* Read PLL2 registers. */ +static void R128SavePLL2Registers(ScrnInfoPtr pScrn, R128SavePtr save) +{ + save->p2pll_ref_div = INPLL(pScrn, R128_P2PLL_REF_DIV); + save->p2pll_div_0 = INPLL(pScrn, R128_P2PLL_DIV_0); + save->htotal_cntl2 = INPLL(pScrn, R128_HTOTAL2_CNTL); + + R128TRACE(("Read: 0x%08x 0x%08x 0x%08x\n", + save->p2pll_ref_div, + save->p2pll_div_0, + save->htotal_cntl2)); + R128TRACE(("Read: rd=%d, fd=%d, pd=%d\n", + save->p2pll_ref_div & R128_P2PLL_REF_DIV_MASK, + save->p2pll_div_0 & R128_P2PLL_FB0_DIV_MASK, + (save->p2pll_div_0 & R128_P2PLL_POST0_DIV_MASK) >> 16)); +} + /* Read DDA registers. */ static void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save) { @@ -2768,6 +3276,16 @@ save->dda_on_off = INREG(R128_DDA_ON_OFF); } +/* Read DDA2 registers. */ +static void R128SaveDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save) +{ + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; + + save->dda2_config = INREG(R128_DDA2_CONFIG); + save->dda2_on_off = INREG(R128_DDA2_ON_OFF); +} + /* Read palette data. */ static void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save) { @@ -2775,26 +3293,49 @@ unsigned char *R128MMIO = info->MMIO; int i; +#if 0 /* Select palette 0 (main CRTC) if using FP-enabled chip */ if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0); INPAL_START(0); for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT(); save->palette_valid = TRUE; +#endif + PAL_SELECT(1); + INPAL_START(0); + for (i = 0; i < 256; i++) save->palette2[i] = INPAL_NEXT(); + PAL_SELECT(0); + INPAL_START(0); + for (i = 0; i < 256; i++) save->palette[i] = INPAL_NEXT(); + save->palette_valid = TRUE; } /* Save state that defines current video mode. */ static void R128SaveMode(ScrnInfoPtr pScrn, R128SavePtr save) { + R128InfoPtr info = R128PTR(pScrn); + R128TRACE(("R128SaveMode(%p)\n", save)); - R128SaveCommonRegisters(pScrn, save); - R128SaveCrtcRegisters(pScrn, save); - if (R128PTR(pScrn)->HasPanelRegs || R128PTR(pScrn)->isDFP) - R128SaveFPRegisters(pScrn, save); - R128SavePLLRegisters(pScrn, save); - R128SaveDDARegisters(pScrn, save); - R128SavePalette(pScrn, save); + if(info->IsSecondary) + { + R128SaveCrtc2Registers(pScrn, save); + R128SavePLL2Registers(pScrn, save); + R128SaveDDA2Registers(pScrn, save); + } + else + { + R128SaveCommonRegisters(pScrn, save); + R128SaveCrtcRegisters(pScrn, save); + if((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD)) + { + R128SaveFPRegisters(pScrn, save); + } + R128SavePLLRegisters(pScrn, save); + R128SaveDDARegisters(pScrn, save); + R128SavePalette(pScrn, save); + } R128TRACE(("R128SaveMode returns %p\n", save)); } @@ -2812,17 +3353,24 @@ fbdevHWSave(pScrn); return; } + + if(!info->IsSecondary) + { vgaHWUnlock(hwp); vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); /* save mode, fonts, cmap */ vgaHWLock(hwp); - R128SaveMode(pScrn, save); + /*R128SaveMode(pScrn, save);*/ save->dp_datatype = INREG(R128_DP_DATATYPE); save->gen_reset_cntl = INREG(R128_GEN_RESET_CNTL); save->clock_cntl_index = INREG(R128_CLOCK_CNTL_INDEX); save->amcgpio_en_reg = INREG(R128_AMCGPIO_EN_REG); save->amcgpio_mask = INREG(R128_AMCGPIO_MASK); + } + + R128SaveMode(pScrn, save); + } /* Restore the original (text) mode. */ @@ -2840,16 +3388,46 @@ } R128Blank(pScrn); + + if (!info->IsSecondary) { OUTREG(R128_AMCGPIO_MASK, restore->amcgpio_mask); OUTREG(R128_AMCGPIO_EN_REG, restore->amcgpio_en_reg); OUTREG(R128_CLOCK_CNTL_INDEX, restore->clock_cntl_index); OUTREG(R128_GEN_RESET_CNTL, restore->gen_reset_cntl); OUTREG(R128_DP_DATATYPE, restore->dp_datatype); + } R128RestoreMode(pScrn, restore); + + /* Temp fix to "solve" VT switch problems. When switching VTs on + some systems, the console can either hang or the fonts can be + corrupted. This hack solves the problem 99% of the time. A + correct fix is being worked on. */ + /* does r128 need this? */ + usleep(100000); + + if(!info->IsSecondary) + { vgaHWUnlock(hwp); vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); vgaHWLock(hwp); + } + else + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + { + ScrnInfoPtr pScrn0 = pR128Ent->pPrimaryScrn; + vgaHWPtr hwp0 = VGAHWPTR(pScrn0); + vgaHWUnlock(hwp0); + vgaHWRestore(pScrn0, &hwp0->SavedReg, + VGA_SR_MODE | VGA_SR_FONTS ); + vgaHWLock(hwp0); + } + } R128WaitForVerticalSync(pScrn); R128Unblank(pScrn); @@ -2909,18 +3487,11 @@ return FALSE; } - switch (info->BIOSDisplay) { - case R128_BIOS_DISPLAY_FP: + if ((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD)) hsync_fudge = hsync_fudge_fp[format-1]; - break; - case R128_BIOS_DISPLAY_FP_CRT: - hsync_fudge = hsync_fudge_fp_crt[format-1]; - break; - case R128_BIOS_DISPLAY_CRT: - default: - hsync_fudge = hsync_fudge_default[format-1]; - break; - } + else + hsync_fudge = hsync_fudge_default[format-1]; save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN | R128_CRTC_EN @@ -2935,7 +3506,19 @@ ? R128_CRTC_CSYNC_EN : 0)); - save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | R128_XCRT_CNT_EN; + if((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD)) + { + save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | + R128_XCRT_CNT_EN; + save->crtc_gen_cntl &= ~(R128_CRTC_DBL_SCAN_EN | + R128_CRTC_INTERLACE_EN); + } + else + save->crtc_ext_cntl = R128_VGA_ATI_LINEAR | + R128_XCRT_CNT_EN | + R128_CRTC_CRT_ON; + save->dac_cntl = (R128_DAC_MASK_ALL | R128_DAC_VGA_ADR_EN | (info->dac6bits ? 0 : R128_DAC_8BIT_EN)); @@ -3012,6 +3595,98 @@ return TRUE; } +/* Define CRTC2 registers for requested video mode. */ +static Bool R128InitCrtc2Registers(ScrnInfoPtr pScrn, R128SavePtr save, + DisplayModePtr mode, R128InfoPtr info) +{ + int format; + int hsync_start; + int hsync_wid; + int hsync_fudge; + int vsync_wid; + int bytpp; + int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; bytpp = 0; break; + case 8: format = 2; bytpp = 1; break; + case 15: format = 3; bytpp = 2; break; /* 555 */ + case 16: format = 4; bytpp = 2; break; /* 565 */ + case 24: format = 5; bytpp = 3; break; /* RGB */ + case 32: format = 6; bytpp = 4; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", info->CurrentLayout.bitsPerPixel); + return FALSE; + } + R128TRACE(("Format = %d (%d bytes per pixel)\n", format, bytpp)); + + hsync_fudge = hsync_fudge_default[format-1]; + + save->crtc2_gen_cntl = (R128_CRTC2_EN + /*| R128_CRTC2_CRT2_ON*/ + | (format << 8) + | ((mode->Flags & V_DBLSCAN) + ? R128_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? R128_CRTC2_INTERLACE_EN + : 0)); +#if 0 + save->dac_cntl = (R128_DAC_MASK_ALL + | R128_DAC_VGA_ADR_EN + | R128_DAC_CRT_SEL_CRTC2 + | (info->dac6bits ? 0 : R128_DAC_8BIT_EN)); + /*save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2;*/ +#endif + save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge; + + save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? R128_CRTC_H_SYNC_POL + : R128_CRTC_H_SYNC_POL)); + +#if 1 + /* This works for double scan mode. */ + save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); +#else + /* This is what cce/nbmode.c example code + does -- is this correct? */ + save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay + * ((mode->Flags & V_DBLSCAN) ? 2 : 1) - 1) + << 16)); +#endif + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + + save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? R128_CRTC2_V_SYNC_POL + : R128_CRTC2_V_SYNC_POL)); + + save->crtc2_offset = 0; + save->crtc2_offset_cntl = 0; + + save->crtc2_pitch = info->CurrentLayout.displayWidth / 8; + + R128TRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n", + save->crtc2_pitch, pScrn->virtualX, + info->CurrentLayout.displayWidth)); + return TRUE; +} + /* Define CRTC registers for requested video mode. */ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, DisplayModePtr mode, R128InfoPtr info) @@ -3084,6 +3759,7 @@ the flat panel and external CRT to either simultaneously display the same image or display two different images. */ +#if 0 if(!info->isDFP){ if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) { save->crtc_ext_cntl |= R128_CRTC_CRT_ON; @@ -3093,6 +3769,13 @@ save->crtc2_gen_cntl = 0; } } +#endif + if(!info->isDFP){ + /*save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON;*/ + save->crtc_ext_cntl |= R128_CRTC_CRT_ON; + save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; + save->dac_cntl |= R128_DAC_PALETTE2_SNOOP_EN; + } /* WARNING: Be careful about turning on the flat panel */ if(info->isDFP){ @@ -3172,6 +3855,57 @@ } +/* Define PLL2 registers for requested video mode. */ +static void R128InitPLL2Registers(R128SavePtr save, R128PLLPtr pll, + double dot_clock) +{ + unsigned long freq = dot_clock * 100; + struct { + int divider; + int bitvalue; + } *post_div, + post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + Reference Manual (Technical Reference + Manual P/N RRG-G04100-C Rev. 0.04), page + 3-17 (PLL_DIV_[3:0]). */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 16, 5 }, /* VCLK_SRC/16 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; + if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + save->pll_output_freq_2 = post_div->divider * freq; + if (save->pll_output_freq_2 >= pll->min_pll_freq + && save->pll_output_freq_2 <= pll->max_pll_freq) break; + } + + save->dot_clock_freq_2 = freq; + save->feedback_div_2 = R128Div(pll->reference_div + * save->pll_output_freq_2, + pll->reference_freq); + save->post_div_2 = post_div->divider; + + R128TRACE(("dc=%d, of=%d, fd=%d, pd=%d\n", + save->dot_clock_freq_2, + save->pll_output_freq_2, + save->feedback_div_2, + save->post_div_2)); + + save->p2pll_ref_div = pll->reference_div; + save->p2pll_div_0 = (save->feedback_div_2 | (post_div->bitvalue<<16)); + save->htotal_cntl2 = 0; +} + /* Define DDA registers for requested video mode. */ static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, R128PLLPtr pll, R128InfoPtr info, @@ -3241,6 +3975,74 @@ return TRUE; } +/* Define DDA2 registers for requested video mode. */ +static Bool R128InitDDA2Registers(ScrnInfoPtr pScrn, R128SavePtr save, + R128PLLPtr pll, R128InfoPtr info, + DisplayModePtr mode) +{ + int DisplayFifoWidth = 128; + int DisplayFifoDepth = 32; + int XclkFreq; + int VclkFreq; + int XclksPerTransfer; + int XclksPerTransferPrecise; + int UseablePrecision; + int Roff; + int Ron; + + XclkFreq = pll->xclk; + + VclkFreq = R128Div(pll->reference_freq * save->feedback_div_2, + pll->reference_div * save->post_div_2); + + if(info->isDFP && !info->isPro2){ + if(info->PanelXRes != mode->CrtcHDisplay) + VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes; + } + + XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, + VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); + + UseablePrecision = R128MinBits(XclksPerTransfer) + 1; + + XclksPerTransferPrecise = R128Div((XclkFreq * DisplayFifoWidth) + << (11 - UseablePrecision), + VclkFreq * (info->CurrentLayout.pixel_bytes * 8)); + + Roff = XclksPerTransferPrecise * (DisplayFifoDepth - 4); + + Ron = (4 * info->ram->MB + + 3 * MAX(info->ram->Trcd - 2, 0) + + 2 * info->ram->Trp + + info->ram->Twr + + info->ram->CL + + info->ram->Tr2w + + XclksPerTransfer) << (11 - UseablePrecision); + + if (Ron + info->ram->Rloop >= Roff) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "(Ron = %d) + (Rloop = %d) >= (Roff = %d)\n", + Ron, info->ram->Rloop, Roff); + return FALSE; + } + + save->dda2_config = (XclksPerTransferPrecise + | (UseablePrecision << 16) + | (info->ram->Rloop << 20)); + + save->dda2_on_off = (Ron << 16) | Roff; + + R128TRACE(("XclkFreq = %d; VclkFreq = %d; per = %d, %d (useable = %d)\n", + XclkFreq, + VclkFreq, + XclksPerTransfer, + XclksPerTransferPrecise, + UseablePrecision)); + R128TRACE(("Roff = %d, Ron = %d, Rloop = %d\n", + Roff, Ron, info->ram->Rloop)); + + return TRUE; +} #if 0 /* Define initial palette for requested video mode. This doesn't do @@ -3308,21 +4110,42 @@ info->Flags = mode->Flags; - R128InitCommonRegisters(save, info); - if (!R128InitCrtcRegisters(pScrn, save, mode, info)) return FALSE; - if (info->HasPanelRegs || info->isDFP) - R128InitFPRegisters(&info->SavedReg, save, mode, info); - if(dot_clock > 0){ - R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock); - if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode)) - return FALSE; + if(info->IsSecondary) + { + if (!R128InitCrtc2Registers(pScrn, save, + pScrn->currentMode,info)) + return FALSE; + R128InitPLL2Registers(save, &info->pll, dot_clock); + if (!R128InitDDA2Registers(pScrn, save, &info->pll, info, mode)) + return FALSE; } - else{ - save->ppll_ref_div = info->SavedReg.ppll_ref_div; - save->ppll_div_3 = info->SavedReg.ppll_div_3; - save->htotal_cntl = info->SavedReg.htotal_cntl; - save->dda_config = info->SavedReg.dda_config; - save->dda_on_off = info->SavedReg.dda_on_off; + else + { + R128InitCommonRegisters(save, info); + if(!R128InitCrtcRegisters(pScrn, save, mode, info)) + return FALSE; + if(dot_clock) + { + R128InitPLLRegisters(pScrn, save, &info->pll, dot_clock); + if (!R128InitDDARegisters(pScrn, save, &info->pll, info, mode)) + return FALSE; + } + else + { + save->ppll_ref_div = info->SavedReg.ppll_ref_div; + save->ppll_div_3 = info->SavedReg.ppll_div_3; + save->htotal_cntl = info->SavedReg.htotal_cntl; + save->dda_config = info->SavedReg.dda_config; + save->dda_on_off = info->SavedReg.dda_on_off; + } + /* not used for now */ + /*if (!info->PaletteSavedOnVT) RADEONInitPalette(save);*/ + } + + if (((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD))) + { + R128InitFPRegisters(&info->SavedReg, save, mode, info); } R128TRACE(("R128Init returns %p\n", save)); @@ -3366,7 +4189,19 @@ Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { - return R128ModeInit(xf86Screens[scrnIndex], mode); + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + R128InfoPtr info = R128PTR(pScrn); + Bool ret; + /* when switch mode in dual-head setup, this function will be called + separately for each screen (depending on which screen the cursor is + in when user press ctrl-alt-+). Since this function is always + called when screen already in extensive mode, the sequence of + setting CRTC2 and CRT_EXT regesters doesn't matter any more, + So we set the flag for RADEONRestoreMode here. */ + info->SwitchingMode = TRUE; + ret = R128ModeInit(xf86Screens[scrnIndex], mode); + info->SwitchingMode = FALSE; + return ret; } /* Used to disallow modes that are not supported by the hardware. */ @@ -3384,13 +4219,12 @@ return MODE_OK; } - if (info->HasPanelRegs) { + if (info->DisplayType == MT_LCD) { if (mode->Flags & V_INTERLACE) return MODE_NO_INTERLACE; if (mode->Flags & V_DBLSCAN) return MODE_NO_DBLESCAN; } - if (info->HasPanelRegs && - info->BIOSDisplay != R128_BIOS_DISPLAY_CRT && + if (info->DisplayType == MT_LCD && info->VBIOS) { int i; for (i = info->FPBIOSstart+64; R128_BIOS16(i) != 0; i += 2) { @@ -3471,7 +4305,14 @@ if (info->CurrentLayout.pixel_code == 24) Base += 8 * (Base % 3); /* Must be multiple of 8 and 3 */ + if(info->IsSecondary) + { + Base += pScrn->fbOffset; + OUTREG(R128_CRTC2_OFFSET, Base); + } + else OUTREG(R128_CRTC_OFFSET, Base); + } /* Called when VT switching back to the X server. Reinitialize the video @@ -3598,25 +4439,44 @@ int mask = (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_VSYNC_DIS); + int mask2 = (R128_CRTC2_DISP_DIS | + R128_CRTC2_VSYNC_DIS | + R128_CRTC2_HSYNC_DIS); switch (PowerManagementMode) { case DPMSModeOn: /* Screen: On; HSync: On, VSync: On */ - OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask); + if (info->IsSecondary) + OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~mask2); + else + OUTREGP(R128_CRTC_EXT_CNTL, 0, ~mask); break; case DPMSModeStandby: /* Screen: Off; HSync: Off, VSync: On */ - OUTREGP(R128_CRTC_EXT_CNTL, - R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask); + if (info->IsSecondary) + OUTREGP(R128_CRTC2_GEN_CNTL, + R128_CRTC2_DISP_DIS | R128_CRTC2_HSYNC_DIS, + ~mask2); + else + OUTREGP(R128_CRTC_EXT_CNTL, + R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS, ~mask); break; case DPMSModeSuspend: /* Screen: Off; HSync: On, VSync: Off */ - OUTREGP(R128_CRTC_EXT_CNTL, - R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask); + if (info->IsSecondary) + OUTREGP(R128_CRTC2_GEN_CNTL, + R128_CRTC2_DISP_DIS | R128_CRTC2_VSYNC_DIS, + ~mask2); + else + OUTREGP(R128_CRTC_EXT_CNTL, + R128_CRTC_DISPLAY_DIS | R128_CRTC_VSYNC_DIS, ~mask); break; case DPMSModeOff: /* Screen: Off; HSync: Off, VSync: Off */ - OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask); + if (info->IsSecondary) + OUTREGP(R128_CRTC2_GEN_CNTL, mask2, ~mask2); + else + OUTREGP(R128_CRTC_EXT_CNTL, mask, ~mask); break; } } Index: r128_probe.c =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c,v retrieving revision 1.4 diff -u -r1.4 r128_probe.c --- r128_probe.c 12 Aug 2004 01:03:06 -0000 1.4 +++ r128_probe.c 7 Nov 2004 07:56:12 -0000 @@ -101,6 +101,8 @@ { -1, -1, RES_UNDEFINED } }; +int gR128EntityIndex = -1; + /* Return the options for supported chipset 'n'; NULL otherwise */ const OptionInfoRec * R128AvailableOptions(int chipid, int busid) @@ -137,7 +139,6 @@ int numDevSections, nATIGDev, nR128GDev; int *usedChips; GDevPtr *devSections, *ATIGDevs, *R128GDevs; - EntityInfoPtr pEnt; Bool foundScreen = FALSE; int i; @@ -183,10 +184,13 @@ if (flags & PROBE_DETECT) foundScreen = TRUE; else for (i = 0; i < numUsed; i++) { - pEnt = xf86GetEntityInfo(usedChips[i]); - - if (pEnt->active) { - ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0); + ScrnInfoPtr pScrn; + EntityInfoPtr pEnt; + + pScrn = NULL; + if((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], + R128PciChipsets, 0, 0, 0, 0, 0))) + { #ifdef XFree86LOADER @@ -206,11 +210,43 @@ foundScreen = TRUE; - xf86ConfigActivePciEntity(pScrn, usedChips[i], R128PciChipsets, - 0, 0, 0, 0, 0); + pEnt = xf86GetEntityInfo(usedChips[i]); + + /* mobility cards support Dual-Head, mark the entity as sharable*/ + if(pEnt->chipset == PCI_CHIP_RAGE128LE || + pEnt->chipset == PCI_CHIP_RAGE128LF || + pEnt->chipset == PCI_CHIP_RAGE128MF || + pEnt->chipset == PCI_CHIP_RAGE128ML) + { + static int instance = 0; + DevUnion* pPriv; + + xf86SetEntitySharable(usedChips[i]); + xf86SetEntityInstanceForScreen(pScrn, + pScrn->entityList[0], instance); + + if(gR128EntityIndex < 0) + { + gR128EntityIndex = xf86AllocateEntityPrivateIndex(); + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + + if (!pPriv->ptr) + { + R128EntPtr pR128Ent; + pPriv->ptr = xnfcalloc(sizeof(R128EntRec), 1); + pR128Ent = pPriv->ptr; + pR128Ent->IsDRIEnabled = FALSE; + pR128Ent->BypassSecondary = FALSE; + pR128Ent->HasSecondary = FALSE; + pR128Ent->IsSecondaryRestored = FALSE; + } + } + instance++; } xfree(pEnt); } + } xfree(usedChips); xfree(devSections); Index: r128_probe.h =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h,v retrieving revision 1.6 diff -u -r1.6 r128_probe.h --- r128_probe.h 21 Sep 2004 18:10:34 -0000 1.6 +++ r128_probe.h 7 Nov 2004 07:56:12 -0000 @@ -39,6 +39,21 @@ #include "xf86str.h" +typedef struct +{ + Bool IsDRIEnabled; + + Bool HasSecondary; + Bool BypassSecondary; + /*These two registers are used to make sure the CRTC2 is + retored before CRTC_EXT, otherwise it could lead to blank screen.*/ + Bool IsSecondaryRestored; + Bool RestorePrimary; + + ScrnInfoPtr pSecondaryScrn; + ScrnInfoPtr pPrimaryScrn; +}R128EntRec, *R128EntPtr; + /* r128_probe.c */ extern const OptionInfoRec * R128AvailableOptions(int, int); extern void R128Identify(int); Index: r128_reg.h =================================================================== RCS file: /cvs/xorg/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v retrieving revision 1.3 diff -u -r1.3 r128_reg.h --- r128_reg.h 16 Jun 2004 09:43:58 -0000 1.3 +++ r128_reg.h 7 Nov 2004 07:56:13 -0000 @@ -76,7 +76,7 @@ #define OUTPLL(addr, val) \ do { \ - OUTREG8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x1f) | R128_PLL_WR_EN); \ + OUTREG8(R128_CLOCK_CNTL_INDEX, ((addr) & 0x3f) | R128_PLL_WR_EN); \ OUTREG(R128_CLOCK_CNTL_DATA, val); \ } while (0) @@ -284,6 +284,7 @@ #define R128_CLOCK_CNTL_INDEX 0x0008 # define R128_PLL_WR_EN (1 << 7) # define R128_PLL_DIV_SEL (3 << 8) +# define R128_PLL2_DIV_SEL_MASK ~(3 << 8) #define R128_CLR_CMP_CLR_3D 0x1a24 #define R128_CLR_CMP_CLR_DST 0x15c8 #define R128_CLR_CMP_CLR_SRC 0x15c4 @@ -374,15 +375,49 @@ #define R128_CRTC2_CRNT_FRAME 0x0314 #define R128_CRTC2_DEBUG 0x031c #define R128_CRTC2_GEN_CNTL 0x03f8 +# define R128_CRTC2_DBL_SCAN_EN (1 << 0) +# define R128_CRTC2_INTERLACE_EN (1 << 1) +# define R128_CRTC2_SYNC_TRISTAT (1 << 4) +# define R128_CRTC2_HSYNC_TRISTAT (1 << 5) +# define R128_CRTC2_VSYNC_TRISTAT (1 << 6) +# define R128_CRTC2_CRT2_ON (1 << 7) +# define R128_CRTC2_ICON_EN (1 << 15) +# define R128_CRTC2_CUR_EN (1 << 16) +# define R128_CRTC2_CUR_MODE_MASK (7 << 20) +# define R128_CRTC2_DISP_DIS (1 << 23) +# define R128_CRTC2_EN (1 << 25) +# define R128_CRTC2_DISP_REQ_EN_B (1 << 26) +# define R128_CRTC2_HSYNC_DIS (1 << 28) +# define R128_CRTC2_VSYNC_DIS (1 << 29) #define R128_CRTC2_GUI_TRIG_VLINE 0x0318 #define R128_CRTC2_H_SYNC_STRT_WID 0x0304 +# define R128_CRTC2_H_SYNC_STRT_PIX (0x07 << 0) +# define R128_CRTC2_H_SYNC_STRT_CHAR (0x3ff << 3) +# define R128_CRTC2_H_SYNC_STRT_CHAR_SHIFT 3 +# define R128_CRTC2_H_SYNC_WID (0x3f << 16) +# define R128_CRTC2_H_SYNC_WID_SHIFT 16 +# define R128_CRTC2_H_SYNC_POL (1 << 23) #define R128_CRTC2_H_TOTAL_DISP 0x0300 +# define R128_CRTC2_H_TOTAL (0x03ff << 0) +# define R128_CRTC2_H_TOTAL_SHIFT 0 +# define R128_CRTC2_H_DISP (0x01ff << 16) +# define R128_CRTC2_H_DISP_SHIFT 16 #define R128_CRTC2_OFFSET 0x0324 #define R128_CRTC2_OFFSET_CNTL 0x0328 +# define R128_CRTC2_TILE_EN (1 << 15) #define R128_CRTC2_PITCH 0x032c #define R128_CRTC2_STATUS 0x03fc #define R128_CRTC2_V_SYNC_STRT_WID 0x030c +# define R128_CRTC2_V_SYNC_STRT (0x7ff << 0) +# define R128_CRTC2_V_SYNC_STRT_SHIFT 0 +# define R128_CRTC2_V_SYNC_WID (0x1f << 16) +# define R128_CRTC2_V_SYNC_WID_SHIFT 16 +# define R128_CRTC2_V_SYNC_POL (1 << 23) #define R128_CRTC2_V_TOTAL_DISP 0x0308 +# define R128_CRTC2_V_TOTAL (0x07ff << 0) +# define R128_CRTC2_V_TOTAL_SHIFT 0 +# define R128_CRTC2_V_DISP (0x07ff << 16) +# define R128_CRTC2_V_DISP_SHIFT 16 #define R128_CRTC2_VLINE_CRNT_VLINE 0x0310 #define R128_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ #define R128_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ @@ -392,12 +427,19 @@ #define R128_CUR_HORZ_VERT_POSN 0x0264 #define R128_CUR_OFFSET 0x0260 # define R128_CUR_LOCK (1 << 31) +#define R128_CUR2_CLR0 0x036c +#define R128_CUR2_CLR1 0x0370 +#define R128_CUR2_HORZ_VERT_OFF 0x0368 +#define R128_CUR2_HORZ_VERT_POSN 0x0364 +#define R128_CUR2_OFFSET 0x0360 +# define R128_CUR2_LOCK (1 << 31) #define R128_DAC_CNTL 0x0058 # define R128_DAC_RANGE_CNTL (3 << 0) # define R128_DAC_BLANKING (1 << 2) # define R128_DAC_CRT_SEL_CRTC2 (1 << 4) # define R128_DAC_PALETTE_ACC_CTL (1 << 5) +# define R128_DAC_PALETTE2_SNOOP_EN (1 << 6) # define R128_DAC_8BIT_EN (1 << 8) # define R128_DAC_VGA_ADR_EN (1 << 13) # define R128_DAC_MASK_ALL (0xff << 24) @@ -408,9 +450,14 @@ #define R128_DAC_W_INDEX 0x03c8 /* VGA */ #define R128_DDA_CONFIG 0x02e0 #define R128_DDA_ON_OFF 0x02e4 +#define R128_DDA2_CONFIG 0x03e0 +#define R128_DDA2_ON_OFF 0x03e4 #define R128_DEFAULT_OFFSET 0x16e0 #define R128_DEFAULT_PITCH 0x16e4 #define R128_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 +#define R128_DEFAULT2_OFFSET 0x16f8 +#define R128_DEFAULT2_PITCH 0x16fc +#define R128_DEFAULT2_SC_BOTTOM_RIGHT 0x16dc # define R128_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) # define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) #define R128_DESTINATION_3D_CLR_CMP_VAL 0x1820 @@ -670,6 +717,7 @@ #define R128_HOST_DATA_LAST 0x17e0 #define R128_HOST_PATH_CNTL 0x0130 #define R128_HTOTAL_CNTL 0x0009 /* PLL */ +#define R128_HTOTAL2_CNTL 0x002e /* PLL */ #define R128_HW_DEBUG 0x0128 #define R128_HW_DEBUG2 0x011c @@ -875,6 +923,19 @@ # define R128_PPLL_REF_DIV_MASK 0x03ff # define R128_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ # define R128_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ +#define R128_P2PLL_CNTL 0x002a /* P2PLL */ +# define R128_P2PLL_RESET (1 << 0) +# define R128_P2PLL_SLEEP (1 << 1) +# define R128_P2PLL_ATOMIC_UPDATE_EN (1 << 16) +# define R128_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17) +# define R128_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18) +#define R128_P2PLL_DIV_0 0x002c +# define R128_P2PLL_FB0_DIV_MASK 0x07ff +# define R128_P2PLL_POST0_DIV_MASK 0x00070000 +#define R128_P2PLL_REF_DIV 0x002B /* PLL */ +# define R128_P2PLL_REF_DIV_MASK 0x03ff +# define R128_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ +# define R128_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ #define R128_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */ #define R128_REG_BASE 0x0f18 /* PCI */ #define R128_REGPROG_INF 0x0f09 /* PCI */ @@ -935,7 +996,14 @@ #define R128_TRAIL_X_SUB 0x1620 #define R128_VCLK_ECP_CNTL 0x0008 /* PLL */ +# define R128_VCLK_SRC_SEL_MASK 0x03 +# define R128_VCLK_SRC_SEL_CPUCLK 0x00 +# define R128_VCLK_SRC_SEL_PPLLCLK 0x03 # define R128_ECP_DIV_MASK (3 << 8) +#define R128_V2CLK_VCLKTV_CNTL 0x002d /* PLL */ +# define R128_V2CLK_SRC_SEL_MASK 0x03 +# define R128_V2CLK_SRC_SEL_CPUCLK 0x00 +# define R128_V2CLK_SRC_SEL_P2PLLCLK 0x03 #define R128_VENDOR_ID 0x0f00 /* PCI */ #define R128_VGA_DDA_CONFIG 0x02e8 #define R128_VGA_DDA_ON_OFF 0x02ec