diff options
author | tsi <tsi> | 2008-04-02 20:47:56 +0000 |
---|---|---|
committer | tsi <tsi> | 2008-04-02 20:47:56 +0000 |
commit | 32a312b4fddbe8af2892a1d602b7c0446f9011b4 (patch) | |
tree | 7e093d44e558afd5235694eb140dd5cc2a7bae3f | |
parent | c5ebdff80cf33d34c124a1ff71bb6c1e3d93bf7e (diff) |
36. Rage 128 driver changes:
- Add support for dual head on Rage 128 Mobility's (X.Org, via OpenBSD's
xenocara repository).
- Don't use vgaHW if the video mode on server entry is found to be an
accelerator (i.e. non-VGA) video mode (Marc La France).
- Avoid hard-failed master aborts while attempting to read video BIOS
(Marc La France).
-rw-r--r-- | programs/Xserver/hw/xfree86/CHANGELOG | 9 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128.h | 57 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128.man | 12 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c | 67 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c | 62 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c | 19 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c | 1771 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c | 52 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h | 17 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h | 91 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_version.h | 6 | ||||
-rw-r--r-- | programs/Xserver/hw/xfree86/drivers/ati/r128_video.c | 8 |
12 files changed, 1629 insertions, 542 deletions
diff --git a/programs/Xserver/hw/xfree86/CHANGELOG b/programs/Xserver/hw/xfree86/CHANGELOG index 25803d7ae..83287db9f 100644 --- a/programs/Xserver/hw/xfree86/CHANGELOG +++ b/programs/Xserver/hw/xfree86/CHANGELOG @@ -1,4 +1,11 @@ XFree86 4.7.99.15 (xx April 2008) + 36. Rage 128 driver changes: + - Add support for dual head on Rage 128 Mobility's (X.Org, via OpenBSD's + xenocara repository). + - Don't use vgaHW if the video mode on server entry is found to be an + accelerator (i.e. non-VGA) video mode (Marc La France). + - Avoid hard-failed master aborts while attempting to read video BIOS + (Marc La France). 35. Fix PCI resource relocation to avoid nullifying resources (Marc La France). 34. In int10, do attempt to populate shadow system BIOS segments if there's @@ -20697,4 +20704,4 @@ XFree86 3.0a (28 April 1994) XFree86 3.0 (26 April 1994) -$XFree86: xc/programs/Xserver/hw/xfree86/CHANGELOG,v 3.3943 2008/03/27 16:22:40 tsi Exp $ +$XFree86: xc/programs/Xserver/hw/xfree86/CHANGELOG,v 3.3944 2008/04/01 17:18:20 tsi Exp $ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128.h b/programs/Xserver/hw/xfree86/drivers/ati/r128.h index 955f851d7..399914005 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.28tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.29tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -134,6 +134,13 @@ typedef struct { /* 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; @@ -159,13 +166,29 @@ typedef struct { 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 { @@ -185,6 +208,16 @@ typedef struct { DisplayModePtr mode; } R128FBLayout; +typedef enum +{ + MT_NONE, + MT_CRT, + MT_LCD, + MT_DFP, + MT_CTV, + MT_STV +} R128MonitorType; + typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; @@ -301,7 +334,7 @@ typedef struct { Bool IsPCI; /* Current card is a PCI card */ drmSize pciSize; drm_handle_t pciMemHandle; - unsigned char *PCI; /* Map */ + drmAddress PCI; /* Map */ Bool allowPageFlip; /* Enable 3d page flipping */ Bool have3DWindows; /* Are there any 3d clients? */ @@ -310,7 +343,7 @@ typedef struct { drmSize agpSize; drm_handle_t agpMemHandle; /* Handle from drmAgpAlloc */ unsigned long agpOffset; - unsigned char *AGP; /* Map */ + drmAddress AGP; /* Map */ int agpMode; Bool CCEInUse; /* CCE is currently active */ @@ -324,20 +357,20 @@ typedef struct { drm_handle_t ringHandle; /* Handle from drmAddMap */ drmSize ringMapSize; /* Size of map */ int ringSize; /* Size of ring (in MB) */ - unsigned char *ring; /* Map */ + drmAddress ring; /* Map */ int ringSizeLog2QW; unsigned long ringReadOffset; /* Offset into AGP space */ drm_handle_t ringReadPtrHandle; /* Handle from drmAddMap */ drmSize ringReadMapSize; /* Size of map */ - unsigned char *ringReadPtr; /* Map */ + drmAddress ringReadPtr; /* Map */ /* CCE vertex/indirect buffer data */ unsigned long bufStart; /* Offset into AGP space */ drm_handle_t bufHandle; /* Handle from drmAddMap */ drmSize bufMapSize; /* Size of map */ int bufSize; /* Size of buffers (in MB) */ - unsigned char *buf; /* Map */ + drmAddress buf; /* Map */ int bufNumBufs; /* Number of buffers */ drmBufMapPtr buffers; /* Buffer map */ @@ -346,7 +379,7 @@ typedef struct { drm_handle_t agpTexHandle; /* Handle from drmAddMap */ drmSize agpTexMapSize; /* Size of map */ int agpTexSize; /* Size of AGP tex space (in MB) */ - unsigned char *agpTex; /* Map */ + drmAddress agpTex; /* Map */ int log2AGPTexGran; /* CCE 2D accleration */ @@ -400,6 +433,16 @@ typedef struct { I2CBusPtr pI2CBus; CARD32 DDCReg; + /****** Added for dualhead support *******************/ + Bool HasCRTC2; /* M3/M4 */ + Bool IsSecondary; /* second Screen */ + Bool IsPrimary; /* primary Screen */ + Bool UseCRT; /* force use CRT port as primary */ + Bool SwitchingMode; + R128MonitorType DisplayType; /* Monitor connected on */ + + Bool UseVGAHW; + } R128InfoRec, *R128InfoPtr; #define R128WaitForFifo(pScrn, entries) \ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128.man b/programs/Xserver/hw/xfree86/drivers/ati/r128.man index 606b9d642..278a1b804 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128.man +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128.man @@ -1,4 +1,4 @@ -.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.man,v 1.3 2001/06/01 02:10:05 dawes Exp $ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.man,v 1.4tsi Exp $ .\" shorthand for double quote that works everywhere. .ds q \N'34' .TH R128 __drivermansuffix__ __vendorversion__ @@ -19,7 +19,8 @@ full support for 8, 15, 16 and 24 bit pixel depths, hardware acceleration of drawing primitives, hardware cursor, video modes up to 1800x1440 @ 70Hz, doublescan modes (e.g., 320x200 and 320x240), gamma correction at all pixel depths, a fully programming dot clock and robust -text mode restoration for VT switching. +text mode restoration for VT switching. Dualhead is supported on M3/M4 +mobile chips. .SH SUPPORTED HARDWARE The .B r128 @@ -124,6 +125,13 @@ are supported: Enable or disable viewing offscreen cache memory. A development debug option. Default: off. +.PP +.B Dualhead Note: +The video BIOS on some laptops interacts strangely with dualhead. +This can result in flickering and problems changing modes on crtc2. +If you experience these problems, try toggling your laptop's video +output switch (e.g. fn-f7, etc.) prior to starting X or switch to +another VT and back. .SH "SEE ALSO" XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) .SH AUTHORS diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c b/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c index e1026a0ab..cec9f3bd1 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c,v 1.20tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_accel.c,v 1.21tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -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 @@ static struct { { R128_ROP3_ONE, R128_ROP3_ONE } /* GXset */ }; +extern int gR128EntityIndex; + /* Flush all dirty data in the Pixel Cache to memory. */ void R128EngineFlush(ScrnInfoPtr pScrn) { @@ -240,17 +243,23 @@ void R128CCEWaitForIdle(ScrnInfoPtr pScrn) i = 0; do { ret = drmCommandNone(info->drmFD, DRM_R128_CCE_IDLE); - } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY ); + } while ( ret && errno == EBUSY && i++ < (R128_IDLE_RETRY * R128_IDLE_RETRY) ); if (ret && ret != -EBUSY) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: CCE idle %d\n", __FUNCTION__, ret); } + if (i > R128_IDLE_RETRY) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "%s: (DEBUG) CCE idle took i = %d\n", __FUNCTION__, i); + } + if (ret == 0) return; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); + R128CCE_STOP(pScrn, info); R128EngineReset(pScrn); /* Always restart the engine when doing CCE 2D acceleration */ @@ -1020,7 +1029,7 @@ void R128EngineInit(ScrnInfoPtr pScrn) 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); @@ -1644,6 +1653,24 @@ void R128CCEReleaseIndirect( ScrnInfoPtr pScrn ) &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); @@ -1704,9 +1731,29 @@ static void R128CCEAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) | 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); @@ -1785,6 +1832,20 @@ static void R128MMIOAccelInit(ScrnInfoPtr pScrn, XAAInfoRecPtr a) | 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 diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c b/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c index 7527c3367..a4dc73959 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c,v 1.5tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_cursor.c,v 1.6tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -72,8 +72,16 @@ static void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 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 @@ static void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 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 @@ static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) 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 @@ static void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) } - 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 @@ static void R128HideCursor(ScrnInfoPtr pScrn) 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,10 @@ static void R128ShowCursor(ScrnInfoPtr pScrn) 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. */ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c b/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c index 27810b8a4..8dad7dbc0 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.33tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.34tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -243,7 +243,7 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) } pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; - if (accum || stencil) { + if (accum) { pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { pConfigs[i].visualRating = GLX_NONE; @@ -525,7 +525,7 @@ static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) "[agp] ring handle = 0x%08lx\n", info->ringHandle); if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, - (drmAddressPtr)&info->ring) < 0) { + &info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); return FALSE; } @@ -544,7 +544,7 @@ static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) info->ringReadPtrHandle); if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, - (drmAddressPtr)&info->ringReadPtr) < 0) { + &info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring read ptr\n"); return FALSE; @@ -564,7 +564,7 @@ static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) info->bufHandle); if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, - (drmAddressPtr)&info->buf) < 0) { + &info->buf) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map vertex/indirect buffers\n"); return FALSE; @@ -584,7 +584,7 @@ static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen) info->agpTexHandle); if (drmMap(info->drmFD, info->agpTexHandle, info->agpTexMapSize, - (drmAddressPtr)&info->agpTex) < 0) { + &info->agpTex) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map AGP texture map\n"); return FALSE; @@ -669,7 +669,7 @@ static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen) "[pci] ring handle = 0x%08lx\n", info->ringHandle); if (drmMap(info->drmFD, info->ringHandle, info->ringMapSize, - (drmAddressPtr)&info->ring) < 0) { + &info->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n"); return FALSE; } @@ -691,7 +691,7 @@ static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen) info->ringReadPtrHandle); if (drmMap(info->drmFD, info->ringReadPtrHandle, info->ringReadMapSize, - (drmAddressPtr)&info->ringReadPtr) < 0) { + &info->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring read ptr\n"); return FALSE; @@ -714,7 +714,7 @@ static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen) info->bufHandle); if (drmMap(info->drmFD, info->bufHandle, info->bufMapSize, - (drmAddressPtr)&info->buf) < 0) { + &info->buf) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map vertex/indirect buffers\n"); return FALSE; @@ -1297,6 +1297,7 @@ void R128DRICloseScreen(ScreenPtr pScreen) if (info->irq) { drmCtlUninstHandler(info->drmFD); info->irq = 0; + info->gen_int_cntl = 0; } /* De-allocate vertex buffers */ diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c b/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c index b4768818b..842d2eb29 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c,v 1.97tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_driver.c,v 1.98tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -178,6 +178,7 @@ R128RAMRec R128RAM[] = { /* Memory Specifications static const char *vgahwSymbols[] = { "vgaHWFreeHWRec", "vgaHWGetHWRec", + "vgaHWGetIOBase", "vgaHWGetIndex", "vgaHWLock", "vgaHWRestore", @@ -217,7 +218,6 @@ static const char *fbdevHWSymbols[] = { static const char *ddcSymbols[] = { "xf86PrintEDID", - "xf86DoEDID_DDC1", "xf86DoEDID_DDC2", NULL }; @@ -244,6 +244,7 @@ static const char *xaaSymbols[] = { static const char *ramdacSymbols[] = { "xf86CreateCursorInfoRec", "xf86DestroyCursorInfoRec", + "xf86ForceHWCursor", "xf86InitCursor", NULL }; @@ -346,6 +347,16 @@ void R128LoaderRefSymLists(ModuleDescPtr module) NULL); } +extern int gR128EntityIndex; + +static R128EntPtr R128EntPriv(ScrnInfoPtr pScrn) +{ + DevUnion *pPriv; + R128InfoPtr info = R128PTR(pScrn); + pPriv = xf86GetEntityPrivate(info->pEnt->index, gR128EntityIndex); + return pPriv->ptr; +} + /* Allocate our private R128InfoRec. */ static Bool R128GetRec(ScrnInfoPtr pScrn) { @@ -455,7 +466,7 @@ unsigned R128INPLL(ScrnInfoPtr pScrn, int addr) 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); } @@ -489,10 +500,30 @@ static void R128Blank(ScrnInfoPtr pScrn) { 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; + 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_DISP_DIS); + } } /* Unblank screen. */ @@ -501,12 +532,39 @@ static void R128Unblank(ScrnInfoPtr pScrn) 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); + break; + 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); + break; + case MT_NONE: + default: + break; + } + } } /* Compute log base 2 of val. */ @@ -553,14 +611,23 @@ static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) } else { xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, R128_VBIOS_SIZE); if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { + if (!xf86DomainHasBIOSSegments(xf86GetPciDomain(info->PciTag))) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "x86 video BIOS not available\n"); + xfree(info->VBIOS); + info->VBIOS = NULL; + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Video BIOS not detected in PCI space!\n"); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Attempting to read Video BIOS from legacy ISA space!\n"); + "Attempting to read Video BIOS from ISA space!\n"); info->BIOSAddr = 0x000c0000; xf86ReadDomainMemory(info->PciTag, info->BIOSAddr, R128_VBIOS_SIZE, info->VBIOS); } } + if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) { info->BIOSAddr = 0x00000000; xfree(info->VBIOS); @@ -569,7 +636,62 @@ static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) "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 @@ -640,10 +762,10 @@ static Bool R128GetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) } if (!info->PanelXRes || !info->PanelYRes) { - info->HasPanelRegs = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Can't determine panel dimensions, and none specified. \ - Disabling programming of FP registers.\n"); + info->HasPanelRegs = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Can't determine panel dimensions, and none specified.\n" + "\tDisabling programming of FP registers.\n"); } return TRUE; @@ -915,12 +1037,13 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "\n\nWARNING: Forcing the driver to use/not use the flat panel registers\nmight damage your flat panel. Use at your *OWN* *RISK*.\n\n"); } else { - info->isDFP = FALSE; - info->isPro2 = FALSE; + 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. - M3 can also have DFP, no support for now */ + M3 can also have DFP, no support for now */ case PCI_CHIP_RAGE128TF: case PCI_CHIP_RAGE128TL: case PCI_CHIP_RAGE128TR: @@ -966,7 +1089,11 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) 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: @@ -1008,12 +1135,14 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) config file setting. BIOS_5_SCRATCH holds the display device on flat panel systems only. */ if (info->HasPanelRegs) { - char *Display = xf86GetOptValString(info->Options, OPTION_DISPLAY); + char *Display = xf86GetOptValString(info->Options, OPTION_DISPLAY); if (info->FBDev) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Option \"Display\" ignored " "(framebuffer device determines display type)\n"); + else if (info->IsPrimary || info->IsSecondary) + info->BIOSDisplay = R128_DUALHEAD; else if (!Display || !xf86NameCmp(Display, "FP")) info->BIOSDisplay = R128_BIOS_DISPLAY_FP; else if (!xf86NameCmp(Display, "BIOS")) @@ -1070,13 +1199,35 @@ static Bool R128PreInitConfig(ScrnInfoPtr pScrn) from = X_CONFIG; pScrn->videoRam = dev->videoRam; } - pScrn->videoRam &= ~1023; - info->FbMapSize = pScrn->videoRam * 1024; + xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name); + 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; + + /* Flat panel (part 2) */ switch (info->BIOSDisplay) { + case R128_DUALHEAD: + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Dual display\n"); + break; case R128_BIOS_DISPLAY_FP: xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using flat panel for display\n"); @@ -1203,7 +1354,7 @@ static Bool R128PreInitDDC(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) if (!pVbe) { ret = FALSE; } else { - xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,pModule))); + xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(pVbe,pModule))); vbeFree(pVbe); ret = TRUE; } @@ -1247,7 +1398,7 @@ R128I2CPutBits(I2CBusPtr b, int Clock, int data) unsigned char *R128MMIO = info->MMIO; val = INREG(info->DDCReg) - & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3); + & ~(CARD32)(R128_GPIO_MONID_EN_0 | R128_GPIO_MONID_EN_3); val |= (Clock ? 0:R128_GPIO_MONID_EN_3); val |= (data ? 0:R128_GPIO_MONID_EN_0); OUTREG(info->DDCReg, val); @@ -1260,10 +1411,10 @@ R128I2cInit(ScrnInfoPtr pScrn) R128InfoPtr info = R128PTR(pScrn); ModuleDescPtr pModule; if ((pModule = xf86LoadSubModule(pScrn, "i2c")) ) - xf86LoaderModReqSymLists(pModule, i2cSymbols,NULL); + xf86LoaderModReqSymLists(pModule, i2cSymbols,NULL); else{ - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to load i2c module\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to load i2c module\n"); return FALSE; } @@ -1278,7 +1429,7 @@ R128I2cInit(ScrnInfoPtr pScrn) info->pI2CBus->AcknTimeout = 5; if (!xf86I2CBusInit(info->pI2CBus)) { - return FALSE; + return FALSE; } return TRUE; } @@ -1293,47 +1444,49 @@ static Bool R128GetDFPInfo(ScrnInfoPtr pScrn) unsigned char *R128MMIO = info->MMIO; if(!R128I2cInit(pScrn)){ - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "I2C initialization failed!\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "I2C initialization failed!\n"); } OUTREG(info->DDCReg, (INREG(info->DDCReg) - | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3)); + | R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3)); OUTREG(info->DDCReg, INREG(info->DDCReg) - & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3)); + & ~(CARD32)(R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3)); MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); if(!MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No DFP detected\n"); - return FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No DFP detected\n"); + return FALSE; } xf86SetDDCproperties(pScrn, MonInfo); ddc = pScrn->monitor->DDC; for(i=0; i<4; i++) { - if(ddc->det_mon[i].type == 0) - { - info->PanelXRes = - ddc->det_mon[i].section.d_timings.h_active; - info->PanelYRes = - ddc->det_mon[i].section.d_timings.v_active; - - info->HOverPlus = - ddc->det_mon[i].section.d_timings.h_sync_off; - info->HSyncWidth = - ddc->det_mon[i].section.d_timings.h_sync_width; - info->HBlank = - ddc->det_mon[i].section.d_timings.h_blanking; - info->VOverPlus = - ddc->det_mon[i].section.d_timings.v_sync_off; - info->VSyncWidth = - ddc->det_mon[i].section.d_timings.v_sync_width; - info->VBlank = - ddc->det_mon[i].section.d_timings.v_blanking; - } + if((ddc->det_mon[i].type == 0) && + (ddc->det_mon[i].section.d_timings.h_active > 0) && + (ddc->det_mon[i].section.d_timings.v_active > 0)) + { + info->PanelXRes = + ddc->det_mon[i].section.d_timings.h_active; + info->PanelYRes = + ddc->det_mon[i].section.d_timings.v_active; + + info->HOverPlus = + ddc->det_mon[i].section.d_timings.h_sync_off; + info->HSyncWidth = + ddc->det_mon[i].section.d_timings.h_sync_width; + info->HBlank = + ddc->det_mon[i].section.d_timings.h_blanking; + info->VOverPlus = + ddc->det_mon[i].section.d_timings.v_sync_off; + info->VSyncWidth = + ddc->det_mon[i].section.d_timings.v_sync_width; + info->VBlank = + ddc->det_mon[i].section.d_timings.v_blanking; + } } return TRUE; } @@ -1345,120 +1498,120 @@ static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) xf86MonPtr ddc = pScrn->monitor->DDC; if(flag) /*HSync*/ { - for(i=0; i<4; i++) - { - if(ddc->det_mon[i].type == DS_RANGES) - { - pScrn->monitor->nHsync = 1; - pScrn->monitor->hsync[0].lo = - ddc->det_mon[i].section.ranges.min_h; - pScrn->monitor->hsync[0].hi = - ddc->det_mon[i].section.ranges.max_h; - return; - } - } - /*if no sync ranges detected in detailed timing table, - let's try to derive them from supported VESA modes - Are we doing too much here!!!? - **/ - i = 0; - if(ddc->timings1.t1 & 0x02) /*800x600@56*/ - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 35.2; - i++; - } - if(ddc->timings1.t1 & 0x04) /*640x480@75*/ - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 37.5; - i++; - } - if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 37.9; - i++; - } - if(ddc->timings1.t2 & 0x40) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 46.9; - i++; - } - if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 48.1; - i++; - } - if(ddc->timings1.t2 & 0x04) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 56.5; - i++; - } - if(ddc->timings1.t2 & 0x02) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 60.0; - i++; - } - if(ddc->timings1.t2 & 0x01) - { - pScrn->monitor->hsync[i].lo = - pScrn->monitor->hsync[i].hi = 64.0; - i++; - } - pScrn->monitor->nHsync = i; + for(i=0; i<4; i++) + { + if(ddc->det_mon[i].type == DS_RANGES) + { + pScrn->monitor->nHsync = 1; + pScrn->monitor->hsync[0].lo = + ddc->det_mon[i].section.ranges.min_h; + pScrn->monitor->hsync[0].hi = + ddc->det_mon[i].section.ranges.max_h; + return; + } + } + /*if no sync ranges detected in detailed timing table, + let's try to derive them from supported VESA modes + Are we doing too much here!!!? + **/ + i = 0; + if(ddc->timings1.t1 & 0x02) /*800x600@56*/ + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 35.2; + i++; + } + if(ddc->timings1.t1 & 0x04) /*640x480@75*/ + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 37.5; + i++; + } + if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01)) + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 37.9; + i++; + } + if(ddc->timings1.t2 & 0x40) + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 46.9; + i++; + } + if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08)) + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 48.1; + i++; + } + if(ddc->timings1.t2 & 0x04) + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 56.5; + i++; + } + if(ddc->timings1.t2 & 0x02) + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 60.0; + i++; + } + if(ddc->timings1.t2 & 0x01) + { + pScrn->monitor->hsync[i].lo = + pScrn->monitor->hsync[i].hi = 64.0; + i++; + } + pScrn->monitor->nHsync = i; } else /*Vrefresh*/ { - for(i=0; i<4; i++) - { - if(ddc->det_mon[i].type == DS_RANGES) - { - pScrn->monitor->nVrefresh = 1; - pScrn->monitor->vrefresh[0].lo = - ddc->det_mon[i].section.ranges.min_v; - pScrn->monitor->vrefresh[0].hi = - ddc->det_mon[i].section.ranges.max_v; - return; - } - } - i = 0; - if(ddc->timings1.t1 & 0x02) /*800x600@56*/ - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 56; - i++; - } - if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 60; - i++; - } - if(ddc->timings1.t2 & 0x04) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 70; - i++; - } - if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 72; - i++; - } - if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) - || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) - { - pScrn->monitor->vrefresh[i].lo = - pScrn->monitor->vrefresh[i].hi = 75; - i++; - } - pScrn->monitor->nVrefresh = i; + for(i=0; i<4; i++) + { + if(ddc->det_mon[i].type == DS_RANGES) + { + pScrn->monitor->nVrefresh = 1; + pScrn->monitor->vrefresh[0].lo = + ddc->det_mon[i].section.ranges.min_v; + pScrn->monitor->vrefresh[0].hi = + ddc->det_mon[i].section.ranges.max_v; + return; + } + } + i = 0; + if(ddc->timings1.t1 & 0x02) /*800x600@56*/ + { + pScrn->monitor->vrefresh[i].lo = + pScrn->monitor->vrefresh[i].hi = 56; + i++; + } + if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08)) + { + pScrn->monitor->vrefresh[i].lo = + pScrn->monitor->vrefresh[i].hi = 60; + i++; + } + if(ddc->timings1.t2 & 0x04) + { + pScrn->monitor->vrefresh[i].lo = + pScrn->monitor->vrefresh[i].hi = 70; + i++; + } + if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80)) + { + pScrn->monitor->vrefresh[i].lo = + pScrn->monitor->vrefresh[i].hi = 72; + i++; + } + if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40) + || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01)) + { + pScrn->monitor->vrefresh[i].lo = + pScrn->monitor->vrefresh[i].hi = 75; + i++; + } + pScrn->monitor->nVrefresh = i; } } @@ -1467,7 +1620,7 @@ static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) here is our own validation routine. All modes between 640<=XRes<=MaxRes and 480<=YRes<=MaxYRes will be permitted. NOTE: RageProII doesn't support rmx, can only work with the - standard modes the monitor can support (scale). + standard modes the monitor can support (scale). ************/ static int R128ValidateFPModes(ScrnInfoPtr pScrn) @@ -1493,58 +1646,58 @@ static int R128ValidateFPModes(ScrnInfoPtr pScrn) /* If no mode specified in config, we use native resolution*/ if(!pScrn->display->modes[0]) { - pScrn->display->modes[0] = xnfalloc(16); - sprintf(pScrn->display->modes[0], "%dx%d", - info->PanelXRes, info->PanelYRes); + pScrn->display->modes[0] = xnfalloc(16); + sprintf(pScrn->display->modes[0], "%dx%d", + info->PanelXRes, info->PanelYRes); } for(i=0; pScrn->display->modes[i] != NULL; i++) { - if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2) - { - - if(width < 640 || width > info->PanelXRes || - height < 480 || height > info->PanelYRes) - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode %s is out of range.\n" - "Valid mode should be between 640x480-%dx%d\n", - pScrn->display->modes[i], info->PanelXRes, info->PanelYRes); - continue; - } - - new = xnfcalloc(1, sizeof(DisplayModeRec)); - new->prev = last; - new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1); - strcpy(new->name, pScrn->display->modes[i]); - new->HDisplay = new->CrtcHDisplay = width; - new->VDisplay = new->CrtcVDisplay = height; - - ddc = pScrn->monitor->DDC; - for(j=0; j<DET_TIMINGS; j++) - { - /*We use native mode clock only*/ - if(ddc->det_mon[j].type == 0){ - new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000; - break; - } - } - - if(new->prev) new->prev->next = new; - last = new; - if(!first) first = new; - pScrn->display->virtualX = - pScrn->virtualX = MAX(pScrn->virtualX, width); - pScrn->display->virtualY = - pScrn->virtualY = MAX(pScrn->virtualY, height); - count++; - } - else - { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Mode name %s is invalid\n", pScrn->display->modes[i]); - continue; - } + if (sscanf(pScrn->display->modes[i], "%dx%d", &width, &height) == 2) + { + + if(width < 640 || width > info->PanelXRes || + height < 480 || height > info->PanelYRes) + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode %s is out of range.\n" + "Valid mode should be between 640x480-%dx%d\n", + pScrn->display->modes[i], info->PanelXRes, info->PanelYRes); + continue; + } + + new = xnfcalloc(1, sizeof(DisplayModeRec)); + new->prev = last; + new->name = xnfalloc(strlen(pScrn->display->modes[i]) + 1); + strcpy(new->name, pScrn->display->modes[i]); + new->HDisplay = new->CrtcHDisplay = width; + new->VDisplay = new->CrtcVDisplay = height; + + ddc = pScrn->monitor->DDC; + for(j=0; j<DET_TIMINGS; j++) + { + /*We use native mode clock only*/ + if(ddc->det_mon[j].type == 0){ + new->Clock = ddc->det_mon[j].section.d_timings.clock / 1000; + break; + } + } + + if(new->prev) new->prev->next = new; + last = new; + if(!first) first = new; + pScrn->display->virtualX = + pScrn->virtualX = MAX(pScrn->virtualX, width); + pScrn->display->virtualY = + pScrn->virtualY = MAX(pScrn->virtualY, height); + count++; + } + else + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Mode name %s is invalid\n", pScrn->display->modes[i]); + continue; + } } if(last) @@ -1555,20 +1708,20 @@ static int R128ValidateFPModes(ScrnInfoPtr pScrn) /*FIXME: May need to validate line pitch here*/ { - int dummy = 0; - switch(pScrn->depth / 8) - { - case 1: - dummy = 128 - pScrn->virtualX % 128; - break; - case 2: - dummy = 32 - pScrn->virtualX % 32; - break; - case 3: - case 4: - dummy = 16 - pScrn->virtualX % 16; - } - pScrn->displayWidth = pScrn->virtualX + dummy; + int dummy = 0; + switch(pScrn->depth / 8) + { + case 1: + dummy = 128 - pScrn->virtualX % 128; + break; + case 2: + dummy = 32 - pScrn->virtualX % 32; + break; + case 3: + case 4: + dummy = 16 - pScrn->virtualX % 16; + } + pScrn->displayWidth = pScrn->virtualX + dummy; } } @@ -1587,66 +1740,70 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) ModuleDescPtr pModule; if(info->isDFP) { - R128MapMem(pScrn); - info->BIOSDisplay = R128_BIOS_DISPLAY_FP; - /* validate if DFP really connected. */ - if(!R128GetDFPInfo(pScrn)) { - info->isDFP = FALSE; - info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; - } else if(!info->isPro2) { - /* RageProII doesn't support rmx, we can't use native-mode - stretching for other non-native modes. It will rely on - whatever VESA modes monitor can support. */ - modesFound = R128ValidateFPModes(pScrn); - if(modesFound < 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for this DFP/LCD\n"); - R128UnmapMem(pScrn); - return FALSE; - - } - } - R128UnmapMem(pScrn); + R128MapMem(pScrn); + info->BIOSDisplay = R128_BIOS_DISPLAY_FP; + /* validate if DFP really connected. */ + if(!R128GetDFPInfo(pScrn)) { + info->isDFP = FALSE; + info->BIOSDisplay = R128_BIOS_DISPLAY_CRT; + } else if(!info->isPro2) { + /* RageProII doesn't support rmx, we can't use native-mode + stretching for other non-native modes. It will rely on + whatever VESA modes monitor can support. */ + modesFound = R128ValidateFPModes(pScrn); + if(modesFound < 1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid mode found for this DFP/LCD\n"); + R128UnmapMem(pScrn); + return FALSE; + + } + } + R128UnmapMem(pScrn); } if(!info->isDFP || info->isPro2) { /* Get mode information */ - pScrn->progClock = TRUE; - clockRanges = xnfcalloc(sizeof(*clockRanges), 1); - clockRanges->next = NULL; - clockRanges->minClock = info->pll.min_pll_freq; - clockRanges->maxClock = info->pll.max_pll_freq * 10; - clockRanges->clockIndex = -1; - if (info->HasPanelRegs || info->isDFP) { - clockRanges->interlaceAllowed = FALSE; - clockRanges->doubleScanAllowed = FALSE; - } else { - clockRanges->interlaceAllowed = TRUE; - clockRanges->doubleScanAllowed = TRUE; - } - - if(pScrn->monitor->DDC) { - /*if we still don't know sync range yet, let's try EDID. - Note that, since we can have dual heads, the Xconfigurator - may not be able to probe both monitors correctly through - vbe probe function (R128ProbeDDC). Here we provide an - additional way to auto-detect sync ranges if they haven't - been added to XF86Config manually. - **/ - if(pScrn->monitor->nHsync <= 0) - R128SetSyncRangeFromEdid(pScrn, 1); - if(pScrn->monitor->nVrefresh <= 0) - R128SetSyncRangeFromEdid(pScrn, 0); - } - - modesFound = xf86ValidateModes(pScrn, + pScrn->progClock = TRUE; + clockRanges = xnfcalloc(sizeof(*clockRanges), 1); + clockRanges->next = NULL; + clockRanges->minClock = info->pll.min_pll_freq; + clockRanges->maxClock = info->pll.max_pll_freq * 10; + clockRanges->clockIndex = -1; + if (info->HasPanelRegs || info->isDFP) { + clockRanges->interlaceAllowed = FALSE; + clockRanges->doubleScanAllowed = FALSE; + } else { + clockRanges->interlaceAllowed = TRUE; + clockRanges->doubleScanAllowed = TRUE; + } + + if(pScrn->monitor->DDC) { + /*if we still don't know sync range yet, let's try EDID. + Note that, since we can have dual heads, the Xconfigurator + may not be able to probe both monitors correctly through + vbe probe function (R128ProbeDDC). Here we provide an + additional way to auto-detect sync ranges if they haven't + been added to XF86Config manually. + **/ + if(pScrn->monitor->nHsync <= 0) + R128SetSyncRangeFromEdid(pScrn, 1); + if(pScrn->monitor->nVrefresh <= 0) + R128SetSyncRangeFromEdid(pScrn, 0); + } + + modesFound = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, NULL, /* linePitches */ 8 * 64, /* minPitch */ 8 * 1024, /* maxPitch */ - 8 * 64, /* pitchInc */ +/* + * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of + * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks + */ + 8 * 32, /* pitchInc */ 128, /* minHeight */ 2048, /* maxHeight */ pScrn->display->virtualX, @@ -1654,19 +1811,19 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn) info->FbMapSize, LOOKUP_BEST_REFRESH); - if (modesFound < 1 && info->FBDev) { + if (modesFound < 1 && info->FBDev) { fbdevHWUseBuildinMode(pScrn); pScrn->displayWidth = fbdevHWGetLineLength(pScrn)/(pScrn->bitsPerPixel/8); modesFound = 1; - } + } - if (modesFound == -1) return FALSE; - xf86PruneDriverModes(pScrn); - if (!modesFound || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); - return FALSE; - } - xf86SetCrtcForModes(pScrn, 0); + if (modesFound == -1) return FALSE; + xf86PruneDriverModes(pScrn); + if (!modesFound || !pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + return FALSE; + } + xf86SetCrtcForModes(pScrn, 0); } /* Set DPI */ pScrn->currentMode = pScrn->modes; @@ -1865,7 +2022,8 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) { R128InfoPtr info; xf86Int10InfoPtr pInt10 = NULL; - ModuleDescPtr pModule; + ModuleDescPtr pModule; + unsigned char *R128MMIO = NULL; R128TRACE(("R128PreInit\n")); @@ -1875,21 +2033,49 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) info = R128PTR(pScrn); + info->IsSecondary = FALSE; + info->IsPrimary = FALSE; + info->SwitchingMode = 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; + info->IsPrimary = TRUE; + 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; } - if (!(pModule = xf86LoadSubModule(pScrn, "vgahw"))) return FALSE; - xf86LoaderModReqSymLists(pModule, vgahwSymbols, NULL); - if (!vgaHWGetHWRec(pScrn)) { - R128FreeRec(pScrn); - return FALSE; - } - info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); info->PciTag = pciTag(info->PciInfo->bus, info->PciInfo->device, @@ -1919,15 +2105,15 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) if (!R128PreInitWeight(pScrn)) goto fail; if(xf86GetOptValInteger(info->Options, OPTION_VIDEO_KEY, &(info->videoKey))) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", - info->videoKey); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", + info->videoKey); } else { - info->videoKey = 0x1E; + info->videoKey = 0x1E; } if (xf86ReturnOptValBool(info->Options, OPTION_SHOW_CACHE, FALSE)) { - info->showCache = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n"); + info->showCache = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShowCache enabled\n"); } if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) { @@ -1949,6 +2135,28 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) if (!info->FBDev) if (!R128PreInitInt10(pScrn, &pInt10)) goto fail; + if (!R128MapMMIO(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Memory map of MMIO region failed\n"); + goto fail; + } + + R128MMIO = info->MMIO; + + /* + * Don't use vgaHW if the adapter is found to be in an accelerator video + * mode on entry, as vgaHW will not be able to save & restore video memory + * contents. + */ + info->UseVGAHW = !(INREG(R128_CRTC_GEN_CNTL) & R128_CRTC_EXT_DISP_EN); + if (info->UseVGAHW) { + if (!(pModule = xf86LoadSubModule(pScrn, "vgahw"))) goto fail1; + xf86LoaderModReqSymLists(pModule, vgahwSymbols, NULL); + if (!vgaHWGetHWRec(pScrn)) goto fail1; + + vgaHWGetIOBase(VGAHWPTR(pScrn)); + } + if (!R128PreInitConfig(pScrn)) goto fail; if (!R128GetBIOSParameters(pScrn, pInt10)) goto fail; @@ -1980,9 +2188,12 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) if (pInt10) xf86FreeInt10(pInt10); + if (R128MMIO) + R128UnmapMMIO(pScrn); + return TRUE; - fail: +fail: /* Pre-init failed. */ /* Free the video bios (if applicable) */ @@ -1991,11 +2202,17 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags) info->VBIOS = NULL; } + if (info->UseVGAHW) + vgaHWFreeHWRec(pScrn); + +fail1: /* Free int10 info */ if (pInt10) xf86FreeInt10(pInt10); - vgaHWFreeHWRec(pScrn); + if (R128MMIO) + R128UnmapMMIO(pScrn); + R128FreeRec(pScrn); return FALSE; } @@ -2006,12 +2223,14 @@ static void R128LoadPalette(ScrnInfoPtr pScrn, int numColors, { R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - int i; + int i, j; int idx; unsigned char r, g, b; - /* Select palette 0 (main CRTC) if using FP-enabled chip */ - if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0); + /* 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); if (info->CurrentLayout.depth == 15) { /* 15bpp mode. This sends 32 values. */ @@ -2059,7 +2278,7 @@ R128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) #ifdef XF86DRI if (info->directRenderingEnabled) - FLUSH_RING(); + FLUSH_RING(); #endif pScreen->BlockHandler = info->BlockHandler; @@ -2067,7 +2286,7 @@ R128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) pScreen->BlockHandler = R128BlockHandler; if(info->VideoTimerCallback) { - (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds); + (*info->VideoTimerCallback)(pScrn, currentTime.milliseconds); } } @@ -2090,6 +2309,7 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, if (!R128MapMem(pScrn)) return FALSE; pScrn->fbOffset = 0; + if(info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; #ifdef XF86DRI info->fbX = 0; info->fbY = 0; @@ -2143,7 +2363,30 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, 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])) + { + DevUnion* pPriv; + R128EntPtr pR128Ent; + 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"); + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + gR128EntityIndex); + pR128Ent = pPriv->ptr; + pR128Ent->IsDRIEnabled = info->directRenderingEnabled; + } + else + info->directRenderingEnabled = + R128DRIScreenInit(pScreen); + } } } #endif @@ -2456,14 +2699,16 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, /* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */ if (info->FBDev) xf86DPMSInit(pScreen, fbdevHWDPMSSet, 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); + if (!info->IsSecondary) + R128InitVideo(pScreen); /* Provide SaveScreen */ pScreen->SaveScreen = R128SaveScreen; @@ -2544,6 +2789,25 @@ static void R128RestoreCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 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; + + OUTREGP(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl, + R128_CRTC2_DISP_DIS); + + 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) { @@ -2551,8 +2815,8 @@ static void R128RestoreFPRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) unsigned char *R128MMIO = info->MMIO; CARD32 tmp; - - /*OUTREG(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);*/ + if (info->BIOSDisplay != R128_DUALHEAD) + OUTREG(R128_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); OUTREG(R128_FP_HORZ_STRETCH, restore->fp_horz_stretch); OUTREG(R128_FP_VERT_STRETCH, restore->fp_vert_stretch); OUTREG(R128_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); @@ -2593,7 +2857,28 @@ static void R128PLLWriteUpdate(ScrnInfoPtr pScrn) 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. */ @@ -2602,33 +2887,44 @@ static void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 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, @@ -2639,6 +2935,82 @@ static void R128RestorePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 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 1 + 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);*/ + + 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. */ @@ -2651,6 +3023,16 @@ static void R128RestoreDDARegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 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) { @@ -2660,27 +3042,113 @@ static void R128RestorePalette(ScrnInfoPtr pScrn, R128SavePtr restore) if (!restore->palette_valid) return; - /* Select palette 0 (main CRTC) if using FP-enabled chip */ - if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0); + 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++) OUTPAL_NEXT_CARD32(restore->palette[i]); + 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){ - R128RestorePLLRegisters(pScrn, restore); + 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); } @@ -2731,7 +3199,8 @@ static void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save) R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; - save->crtc2_gen_cntl = INREG(R128_CRTC2_GEN_CNTL); + if (info->BIOSDisplay != R128_DUALHEAD) + 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); @@ -2745,6 +3214,22 @@ static void R128SaveFPRegisters(ScrnInfoPtr pScrn, R128SavePtr save) 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->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) { @@ -2762,6 +3247,23 @@ static void R128SavePLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save) (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) { @@ -2772,6 +3274,16 @@ static void R128SaveDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save) 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) { @@ -2779,9 +3291,10 @@ static void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save) unsigned char *R128MMIO = info->MMIO; int i; - /* Select palette 0 (main CRTC) if using FP-enabled chip */ - if (info->HasPanelRegs || info->isDFP) PAL_SELECT(0); - + 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; @@ -2790,15 +3303,29 @@ static void R128SavePalette(ScrnInfoPtr pScrn, R128SavePtr save) /* 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)); } @@ -2809,24 +3336,30 @@ static void R128Save(ScrnInfoPtr pScrn) R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128SavePtr save = &info->SavedReg; - vgaHWPtr hwp = VGAHWPTR(pScrn); R128TRACE(("R128Save\n")); if (info->FBDev) { fbdevHWSave(pScrn); return; } - vgaHWUnlock(hwp); - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); /* save mode, fonts, cmap */ - vgaHWLock(hwp); - R128SaveMode(pScrn, save); + if (!info->IsSecondary) { + if (info->UseVGAHW) { + vgaHWPtr hwp = VGAHWPTR(pScrn); + + vgaHWUnlock(hwp); + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); + vgaHWLock(hwp); + } + + 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); + } - 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. */ @@ -2835,7 +3368,6 @@ static void R128Restore(ScrnInfoPtr pScrn) R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128SavePtr restore = &info->SavedReg; - vgaHWPtr hwp = VGAHWPTR(pScrn); R128TRACE(("R128Restore\n")); if (info->FBDev) { @@ -2844,16 +3376,33 @@ static void R128Restore(ScrnInfoPtr pScrn) } R128Blank(pScrn); - 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); + + 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); - vgaHWUnlock(hwp); - vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); - vgaHWLock(hwp); + if (info->UseVGAHW) { + if (!info->IsSecondary) { + vgaHWPtr hwp = VGAHWPTR(pScrn); + vgaHWUnlock(hwp); + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); + vgaHWLock(hwp); + } else { + R128EntPtr pR128Ent = R128EntPriv(pScrn); + ScrnInfoPtr pScrn0 = pR128Ent->pPrimaryScrn; + vgaHWPtr hwp0; + + hwp0 = VGAHWPTR(pScrn0); + vgaHWUnlock(hwp0); + vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); + vgaHWLock(hwp0); + } + } R128WaitForVerticalSync(pScrn); R128Unblank(pScrn); @@ -2897,7 +3446,7 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, int vsync_wid; int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 }; int hsync_fudge_fp[] = { 0x12, 0x11, 0x09, 0x09, 0x05, 0x05 }; - int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 }; +/* int hsync_fudge_fp_crt[] = { 0x12, 0x10, 0x08, 0x08, 0x04, 0x04 }; */ switch (info->CurrentLayout.pixel_code) { case 4: format = 1; break; @@ -2913,18 +3462,11 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, 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: + else hsync_fudge = hsync_fudge_default[format-1]; - break; - } save->crtc_gen_cntl = (R128_CRTC_EXT_DISP_EN | R128_CRTC_EN @@ -2939,7 +3481,19 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, ? 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)); @@ -2947,16 +3501,16 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, if(info->isDFP && !info->isPro2) { - if(info->PanelXRes < mode->CrtcHDisplay) - mode->HDisplay = mode->CrtcHDisplay = info->PanelXRes; - if(info->PanelYRes < mode->CrtcVDisplay) - mode->VDisplay = mode->CrtcVDisplay = info->PanelYRes; - mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; - mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; - mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; - mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; - mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; - mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; + if(info->PanelXRes < mode->CrtcHDisplay) + mode->HDisplay = mode->CrtcHDisplay = info->PanelXRes; + if(info->PanelYRes < mode->CrtcVDisplay) + mode->VDisplay = mode->CrtcVDisplay = info->PanelYRes; + mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; + mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; + mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; + mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; + mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; + mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; } save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) @@ -3016,6 +3570,92 @@ static Bool R128InitCrtcRegisters(ScrnInfoPtr pScrn, R128SavePtr save, 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 + | (format << 8) + | ((mode->Flags & V_DBLSCAN) + ? R128_CRTC2_DBL_SCAN_EN + : 0)); +/* + save->crtc2_gen_cntl &= ~R128_CRTC_EXT_DISP_EN; + save->crtc2_gen_cntl |= (1 << 21); +*/ + save->crtc2_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0xffff) + | (((mode->CrtcHDisplay / 8) - 1) << 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 & 0xfff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? R128_CRTC2_H_SYNC_POL + : 0)); + +#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 + : 0)); + + 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) @@ -3025,20 +3665,20 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, float Hratio, Vratio; if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) { - save->crtc_ext_cntl |= R128_CRTC_CRT_ON; - save->crtc2_gen_cntl = 0; - save->fp_gen_cntl = orig->fp_gen_cntl; - save->fp_gen_cntl &= ~(R128_FP_FPON | - R128_FP_CRTC_USE_SHADOW_VEND | - R128_FP_CRTC_HORZ_DIV2_EN | - R128_FP_CRTC_HOR_CRT_DIV2_DIS | - R128_FP_USE_SHADOW_EN); - save->fp_gen_cntl |= (R128_FP_SEL_CRTC2 | - R128_FP_CRTC_DONT_SHADOW_VPAR); - save->fp_panel_cntl = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON; - save->lvds_gen_cntl = orig->lvds_gen_cntl & + save->crtc_ext_cntl |= R128_CRTC_CRT_ON; + save->crtc2_gen_cntl = 0; + save->fp_gen_cntl = orig->fp_gen_cntl; + save->fp_gen_cntl &= ~(R128_FP_FPON | + R128_FP_CRTC_USE_SHADOW_VEND | + R128_FP_CRTC_HORZ_DIV2_EN | + R128_FP_CRTC_HOR_CRT_DIV2_DIS | + R128_FP_USE_SHADOW_EN); + save->fp_gen_cntl |= (R128_FP_SEL_CRTC2 | + R128_FP_CRTC_DONT_SHADOW_VPAR); + save->fp_panel_cntl = orig->fp_panel_cntl & (CARD32)~R128_FP_DIGON; + save->lvds_gen_cntl = orig->lvds_gen_cntl & (CARD32)~(R128_LVDS_ON | R128_LVDS_BLON); - return; + return; } if (xres > info->PanelXRes) xres = info->PanelXRes; @@ -3051,14 +3691,14 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, (((((int)(Hratio * R128_HORZ_STRETCH_RATIO_MAX + 0.5)) & R128_HORZ_STRETCH_RATIO_MASK) << R128_HORZ_STRETCH_RATIO_SHIFT) | (orig->fp_horz_stretch & (R128_HORZ_PANEL_SIZE | - R128_HORZ_FP_LOOP_STRETCH | - R128_HORZ_STRETCH_RESERVED))); + R128_HORZ_FP_LOOP_STRETCH | + R128_HORZ_STRETCH_RESERVED))); save->fp_horz_stretch &= ~R128_HORZ_AUTO_RATIO_FIX_EN; save->fp_horz_stretch &= ~R128_AUTO_HORZ_RATIO; if (xres == info->PanelXRes) - save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); + save->fp_horz_stretch &= ~(R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); else - save->fp_horz_stretch |= (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); + save->fp_horz_stretch |= (R128_HORZ_STRETCH_BLEND | R128_HORZ_STRETCH_ENABLE); save->fp_vert_stretch = (((((int)(Vratio * R128_VERT_STRETCH_RATIO_MAX + 0.5)) @@ -3067,9 +3707,9 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, R128_VERT_STRETCH_RESERVED))); save->fp_vert_stretch &= ~R128_VERT_AUTO_RATIO_EN; if (yres == info->PanelYRes) - save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); + save->fp_vert_stretch &= ~(R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); else - save->fp_vert_stretch |= (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); + save->fp_vert_stretch |= (R128_VERT_STRETCH_ENABLE | R128_VERT_STRETCH_BLEND); save->fp_gen_cntl = (orig->fp_gen_cntl & (CARD32)~(R128_FP_SEL_CRTC2 | @@ -3088,35 +3728,40 @@ static void R128InitFPRegisters(R128SavePtr orig, R128SavePtr save, the flat panel and external CRT to either simultaneously display the same image or display two different images. */ + if(!info->isDFP){ - if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) { + if (info->BIOSDisplay == R128_BIOS_DISPLAY_FP_CRT) { + save->crtc_ext_cntl |= R128_CRTC_CRT_ON; + } else if (info->BIOSDisplay == R128_DUALHEAD) { save->crtc_ext_cntl |= R128_CRTC_CRT_ON; - } else { + save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; + save->dac_cntl |= R128_DAC_PALETTE2_SNOOP_EN; + } else { save->crtc_ext_cntl &= ~R128_CRTC_CRT_ON; save->dac_cntl |= R128_DAC_CRT_SEL_CRTC2; save->crtc2_gen_cntl = 0; - } + } } /* WARNING: Be careful about turning on the flat panel */ if(info->isDFP){ - save->fp_gen_cntl = orig->fp_gen_cntl; - - save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND | - R128_FP_CRTC_USE_SHADOW_ROWCUR | - R128_FP_CRTC_HORZ_DIV2_EN | - R128_FP_CRTC_HOR_CRT_DIV2_DIS | - R128_FP_CRT_SYNC_SEL | - R128_FP_USE_SHADOW_EN); - - save->fp_panel_cntl |= (R128_FP_DIGON | R128_FP_BLON); - save->fp_gen_cntl |= (R128_FP_FPON | R128_FP_TDMS_EN | - R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND); - save->tmds_transmitter_cntl = (orig->tmds_transmitter_cntl - & ~(CARD32)R128_TMDS_PLLRST) | R128_TMDS_PLLEN; + save->fp_gen_cntl = orig->fp_gen_cntl; + + save->fp_gen_cntl &= ~(R128_FP_CRTC_USE_SHADOW_VEND | + R128_FP_CRTC_USE_SHADOW_ROWCUR | + R128_FP_CRTC_HORZ_DIV2_EN | + R128_FP_CRTC_HOR_CRT_DIV2_DIS | + R128_FP_CRT_SYNC_SEL | + R128_FP_USE_SHADOW_EN); + + save->fp_panel_cntl |= (R128_FP_DIGON | R128_FP_BLON); + save->fp_gen_cntl |= (R128_FP_FPON | R128_FP_TDMS_EN | + R128_FP_CRTC_DONT_SHADOW_VPAR | R128_FP_CRTC_DONT_SHADOW_HEND); + save->tmds_transmitter_cntl = (orig->tmds_transmitter_cntl + & ~(CARD32)R128_TMDS_PLLRST) | R128_TMDS_PLLEN; } else - save->lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_BLON); + save->lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_BLON); save->fp_crtc_h_total_disp = save->crtc_h_total_disp; save->fp_crtc_v_total_disp = save->crtc_v_total_disp; @@ -3176,10 +3821,62 @@ static void R128InitPLLRegisters(ScrnInfoPtr pScrn, R128SavePtr save, } +/* 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 */ + /* bitvalue = 5 is reserved */ + { 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, - DisplayModePtr mode) + DisplayModePtr mode) { int DisplayFifoWidth = 128; int DisplayFifoDepth = 32; @@ -3197,8 +3894,8 @@ static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, pll->reference_div * save->post_div); if(info->isDFP && !info->isPro2){ - if(info->PanelXRes != mode->CrtcHDisplay) - VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes; + if(info->PanelXRes != mode->CrtcHDisplay) + VclkFreq = (VclkFreq * mode->CrtcHDisplay)/info->PanelXRes; } XclksPerTransfer = R128Div(XclkFreq * DisplayFifoWidth, @@ -3245,6 +3942,77 @@ static Bool R128InitDDARegisters(ScrnInfoPtr pScrn, R128SavePtr save, 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;*/ + /* shift most be 18 otherwise there's corruption on crtc2 */ + save->dda2_on_off = (Ron << 18) | 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 @@ -3312,21 +4080,42 @@ static Bool R128Init(ScrnInfoPtr pScrn, DisplayModePtr mode, R128SavePtr save) 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)) + 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 + { + 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);*/ } - 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; + + if (((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD))) + { + R128InitFPRegisters(&info->SavedReg, save, mode, info); } R128TRACE(("R128Init returns %p\n", save)); @@ -3368,9 +4157,21 @@ static Bool R128SaveScreen(ScreenPtr pScreen, int mode) return TRUE; } +/* + * SwitchMode() doesn't work right on crtc2 on some laptops. + * The workaround is to switch the mode, then switch to another VT, then + * switch back. --AGD + */ Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { - return R128ModeInit(xf86Screens[scrnIndex], mode); + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + R128InfoPtr info = R128PTR(pScrn); + Bool ret; + + info->SwitchingMode = TRUE; + ret = R128ModeInit(xf86Screens[scrnIndex], mode); + info->SwitchingMode = FALSE; + return ret; } /* Used to disallow modes that are not supported by the hardware. */ @@ -3381,20 +4182,19 @@ ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, R128InfoPtr info = R128PTR(pScrn); if(info->isDFP) { - if(info->PanelXRes < mode->CrtcHDisplay || - info->PanelYRes < mode->CrtcVDisplay) - return MODE_NOMODE; - else - return MODE_OK; + if(info->PanelXRes < mode->CrtcHDisplay || + info->PanelYRes < mode->CrtcVDisplay) + return MODE_NOMODE; + else + 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) { @@ -3459,7 +4259,7 @@ void R128AdjustFrame(int scrnIndex, int x, int y, int flags) int Base; if(info->showCache && y && pScrn->vtSema) - y += pScrn->virtualY - 1; + y += pScrn->virtualY - 1; Base = y * info->CurrentLayout.displayWidth + x; @@ -3475,7 +4275,14 @@ void R128AdjustFrame(int scrnIndex, int x, int y, int flags) 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 @@ -3487,9 +4294,9 @@ Bool R128EnterVT(int scrnIndex, int flags) R128TRACE(("R128EnterVT\n")); if (info->FBDev) { - if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; + if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; } else - if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; + if (!R128ModeInit(pScrn, pScrn->currentMode)) return FALSE; if (info->accelOn) R128EngineInit(pScrn); @@ -3529,9 +4336,9 @@ void R128LeaveVT(int scrnIndex, int flags) R128SavePalette(pScrn, save); info->PaletteSavedOnVT = TRUE; if (info->FBDev) - fbdevHWLeaveVT(scrnIndex,flags); + fbdevHWLeaveVT(scrnIndex,flags); else - R128Restore(pScrn); + R128Restore(pScrn); } @@ -3571,7 +4378,7 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) info->DGAModes = NULL; if (info->adaptor) { - xfree(info->adaptor->pPortPrivates[0].ptr); + xfree(info->adaptor->pPortPrivates[0].ptr); xf86XVFreeVideoAdaptorRec(info->adaptor); info->adaptor = NULL; } @@ -3586,9 +4393,10 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) void R128FreeScreen(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + R128InfoPtr info = R128PTR(pScrn); R128TRACE(("R128FreeScreen\n")); - if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + if (info->UseVGAHW) vgaHWFreeHWRec(pScrn); R128FreeRec(pScrn); } @@ -3602,27 +4410,52 @@ static void R128DisplayPowerManagementSet(ScrnInfoPtr pScrn, int mask = (R128_CRTC_DISPLAY_DIS | R128_CRTC_HSYNC_DIS | R128_CRTC_VSYNC_DIS); + int mask2 = R128_CRTC2_DISP_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, ~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, ~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; } + if(info->isDFP) { + switch (PowerManagementMode) { + case DPMSModeOn: + OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) | (R128_FP_FPON | R128_FP_TDMS_EN)); + break; + case DPMSModeStandby: + case DPMSModeSuspend: + case DPMSModeOff: + OUTREG(R128_FP_GEN_CNTL, INREG(R128_FP_GEN_CNTL) & ~(R128_FP_FPON | R128_FP_TDMS_EN)); + break; + } + } } static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on); @@ -3638,7 +4471,7 @@ static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, case DPMSModeOn: /* Screen: On; HSync: On, VSync: On */ OUTREGP(R128_LVDS_GEN_CNTL, 0, ~mask); - r128_set_backlight_enable(pScrn, 1); + r128_set_backlight_enable(pScrn, 1); break; case DPMSModeStandby: /* Fall through */ @@ -3648,21 +4481,21 @@ static void R128DisplayPowerManagementSetLCD(ScrnInfoPtr pScrn, case DPMSModeOff: /* Screen: Off; HSync: Off, VSync: Off */ OUTREGP(R128_LVDS_GEN_CNTL, mask, ~mask); - r128_set_backlight_enable(pScrn, 0); + r128_set_backlight_enable(pScrn, 0); break; } } static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on) { - R128InfoPtr info = R128PTR(pScrn); - unsigned char *R128MMIO = info->MMIO; + R128InfoPtr info = R128PTR(pScrn); + unsigned char *R128MMIO = info->MMIO; unsigned int lvds_gen_cntl = INREG(R128_LVDS_GEN_CNTL); lvds_gen_cntl |= (/*R128_LVDS_BL_MOD_EN |*/ R128_LVDS_BLON); if (on) { lvds_gen_cntl |= R128_LVDS_DIGON; - if (!lvds_gen_cntl & R128_LVDS_ON) { + if (!(lvds_gen_cntl & R128_LVDS_ON)) { lvds_gen_cntl &= ~R128_LVDS_BLON; OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl); (void)INREG(R128_LVDS_GEN_CNTL); diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c b/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c index 303250e62..385fe3b1f 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c,v 1.19 2006/03/02 03:00:37 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.c,v 1.20tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -180,6 +180,8 @@ PciChipsets R128PciChipsets[] = { { -1, -1, RES_UNDEFINED } }; +int gR128EntityIndex = -1; + /* Return the options for supported chipset 'n'; NULL otherwise */ const OptionInfoRec * R128AvailableOptions(int chipid, int busid) @@ -216,7 +218,6 @@ R128Probe(DriverPtr drv, int flags) int numDevSections, nATIGDev, nR128GDev; int *usedChips; GDevPtr *devSections, *ATIGDevs, *R128GDevs; - EntityInfoPtr pEnt; Bool foundScreen = FALSE; int i; @@ -262,10 +263,11 @@ R128Probe(DriverPtr drv, int flags) if (flags & PROBE_DETECT) foundScreen = TRUE; else for (i = 0; i < numUsed; i++) { - pEnt = xf86GetEntityInfo(usedChips[i]); + ScrnInfoPtr pScrn; + EntityInfoPtr pEnt; - if (pEnt->active) { - ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0); + if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i], + R128PciChipsets, 0, 0, 0, 0, 0))) { #ifdef XFree86LOADER ModuleDescPtr pModule; @@ -293,13 +295,47 @@ R128Probe(DriverPtr drv, int flags) pScrn->LeaveVT = R128LeaveVT; pScrn->FreeScreen = R128FreeScreen; pScrn->ValidMode = R128ValidMode; + pScrn->Probe = R128Probe; 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(pEnt); } xfree(usedChips); diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h b/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h index 8fb20c466..0226a4ead 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h,v 1.10tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_probe.h,v 1.11tsi Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -41,6 +41,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 FunctionPrototype((int, int)); diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h b/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h index cdd8751a1..9ca104f5f 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.17 2003/09/28 20:15:54 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.18tsi Exp $ */ /* * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario, * Precision Insight, Inc., Cedar Park, Texas, and @@ -68,7 +68,7 @@ do { \ CARD32 tmp = INREG(addr); \ tmp &= (mask); \ - tmp |= (val); \ + tmp |= ((val) & ~(mask)); \ OUTREG(addr, tmp); \ } while (0) @@ -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) @@ -84,7 +84,7 @@ do { \ CARD32 tmp = INPLL(pScrn, addr); \ tmp &= (mask); \ - tmp |= (val); \ + tmp |= ((val) & ~(mask)); \ OUTPLL(addr, tmp); \ } while (0) @@ -151,9 +151,6 @@ #define R128_AMCGPIO_EN_REG 0x01a8 #define R128_AMCGPIO_MASK 0x0194 #define R128_AMCGPIO_Y_REG 0x01a4 -#define R128_ATTRDR 0x03c1 /* VGA */ -#define R128_ATTRDW 0x03c0 /* VGA */ -#define R128_ATTRX 0x03c0 /* VGA */ #define R128_AUX_SC_CNTL 0x1660 # define R128_AUX1_SC_EN (1 << 0) # define R128_AUX1_SC_MODE_OR (0 << 1) @@ -189,6 +186,9 @@ # define R128_BIOS_DISPLAY_FP (1 << 0) # define R128_BIOS_DISPLAY_CRT (2 << 0) # define R128_BIOS_DISPLAY_FP_CRT (3 << 0) +/* R128_DUALHEAD is just a flag for the driver; + it doesn't actually correspond to any bits */ +# define R128_DUALHEAD 4 #define R128_BIOS_6_SCRATCH 0x0028 #define R128_BIOS_7_SCRATCH 0x002c #define R128_BIOS_ROM 0x0f30 /* PCI */ @@ -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,45 +375,77 @@ #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_CUR_EN (1 << 16) +# define R128_CRTC2_ICON_EN (1 << 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_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 (0x1ff << 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 (0x01ff << 0) +# define R128_CRTC2_H_TOTAL_SHIFT 0 +# define R128_CRTC2_H_DISP (0x00ff << 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 */ #define R128_CUR_CLR0 0x026c #define R128_CUR_CLR1 0x0270 #define R128_CUR_HORZ_VERT_OFF 0x0268 #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) #define R128_DAC_CRC_SIG 0x02cc -#define R128_DAC_DATA 0x03c9 /* VGA */ -#define R128_DAC_MASK 0x03c6 /* VGA */ -#define R128_DAC_R_INDEX 0x03c7 /* VGA */ -#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_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) # define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) +#define R128_DEFAULT2_OFFSET 0x16f8 +#define R128_DEFAULT2_PITCH 0x16fc +#define R128_DEFAULT2_SC_BOTTOM_RIGHT 0x16dc #define R128_DESTINATION_3D_CLR_CMP_VAL 0x1820 #define R128_DESTINATION_3D_CLR_CMP_MSK 0x1824 #define R128_DEVICE_ID 0x0f02 /* PCI */ @@ -613,13 +646,6 @@ # define R128_SOFT_RESET_PCLK (1 << 9) # define R128_SOFT_RESET_DISPENG_XCLK (1 << 11) # define R128_SOFT_RESET_MEMCTLR_XCLK (1 << 12) -#define R128_GENENB 0x03c3 /* VGA */ -#define R128_GENFC_RD 0x03ca /* VGA */ -#define R128_GENFC_WT 0x03da /* VGA, 0x03ba */ -#define R128_GENMO_RD 0x03cc /* VGA */ -#define R128_GENMO_WT 0x03c2 /* VGA */ -#define R128_GENS0 0x03c2 /* VGA */ -#define R128_GENS1 0x03da /* VGA, 0x03ba */ #define R128_GPIO_MONID 0x0068 # define R128_GPIO_MONID_A_0 (1 << 0) # define R128_GPIO_MONID_A_1 (1 << 1) @@ -638,8 +664,6 @@ # define R128_GPIO_MONID_MASK_2 (1 << 26) # define R128_GPIO_MONID_MASK_3 (1 << 27) #define R128_GPIO_MONIDB 0x006c -#define R128_GRPH8_DATA 0x03cf /* VGA */ -#define R128_GRPH8_IDX 0x03ce /* VGA */ #define R128_GUI_DEBUG0 0x16a0 #define R128_GUI_DEBUG1 0x16a4 #define R128_GUI_DEBUG2 0x16a8 @@ -670,6 +694,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 +900,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 */ @@ -888,8 +926,6 @@ #define R128_SC_TOP 0x1648 #define R128_SC_TOP_LEFT 0x16ec #define R128_SC_TOP_LEFT_C 0x1c88 -#define R128_SEQ8_DATA 0x03c5 /* VGA */ -#define R128_SEQ8_IDX 0x03c4 /* VGA */ #define R128_SNAPSHOT_F_COUNT 0x0244 #define R128_SNAPSHOT_VH_COUNTS 0x0240 #define R128_SNAPSHOT_VIF_COUNT 0x024c @@ -935,7 +971,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 diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h b/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h index 78dd5a580..34b0e660a 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h,v 1.10tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h,v 1.11tsi Exp $ */ /* * Copyright 2000 through 2008 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -38,8 +38,8 @@ #define R128_DRIVER_NAME "r128" #define R128_VERSION_MAJOR 4 -#define R128_VERSION_MINOR 0 -#define R128_VERSION_PATCH 1 +#define R128_VERSION_MINOR 1 +#define R128_VERSION_PATCH 0 #ifndef R128_VERSION_EXTRA #define R128_VERSION_EXTRA "" diff --git a/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c b/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c index 7b3f08b8c..5b57d1a7a 100644 --- a/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c +++ b/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c,v 1.32tsi Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_video.c,v 1.33tsi Exp $ */ #include "r128.h" #include "r128_reg.h" @@ -579,20 +579,20 @@ R128AllocateMemory( pScreen = screenInfo.screens[pScrn->scrnIndex]; - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); if(!new_linear) { int max_size; - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME); if(max_size < size) return NULL; xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); } |