diff options
author | Eric Anholt <anholt@freebsd.org> | 2004-06-16 09:25:58 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2004-06-16 09:25:58 +0000 |
commit | bea8085e04136b0ef513c17bb65c54069ec531e1 (patch) | |
tree | 8f9c7a4da5c6b8bb7db35eb8928d035d787157a0 | |
parent | 7b588cda922992a8ee2d04853ba1533cf43592a3 (diff) |
DRI trunk-20040613 importDRI-trunk-20040613
40 files changed, 3098 insertions, 1037 deletions
diff --git a/man/radeon.man b/man/radeon.man index 6eeec440..0a11d538 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -16,7 +16,7 @@ radeon \- ATI RADEON video driver is a XFree86 driver for ATI RADEON based video cards. It contains full support for 8, 15, 16 and 24 bit pixel depths, dual-head setup, flat panel, hardware 2D acceleration, hardware 3D acceleration -(except R300 and IGP series cards), hardware cursor, XV extension, Xinerama extension. +(except R300 series cards), hardware cursor, XV extension, Xinerama extension. .SH SUPPORTED HARDWARE The .B radeon @@ -29,37 +29,43 @@ Radeon 7200 Radeon 7000(VE), M6 .TP 12 .B RS100 -Radeon IGP320(M) (2D only) +Radeon IGP320(M) .TP 12 .B RV200 -Radeon 7500, M7 +Radeon 7500, M7, FireGL 7800 .TP 12 .B RS200 -Radeon IGP330(M)/IGP340(M) (2D only) +Radeon IGP330(M)/IGP340(M) .TP 12 .B RS250 -Radeon Mobility 7000 IGP (2D only) +Radeon Mobility 7000 IGP .TP 12 .B R200 Radeon 8500, 9100, FireGL 8800/8700 .TP 12 .B RV250 -Radeon 9000, M9 +Radeon 9000PRO/9000, M9 .TP 12 .B RS300 -Radeon 9000 IGP (2D only) +Radeon 9100 IGP .TP 12 .B RV280 -Radeon 9200, M9+ +Radeon 9200PRO/9200/9200SE, M9+ .TP 12 .B R300 -Radeon 9700PRO/9700/9500PRO/9500, FireGL X1/Z1 (2D only) +Radeon 9700PRO/9700/9500PRO/9500/9600TX, FireGL X1/Z1 (2D only) .TP 12 .B R350 -Radeon 9800PRO (2D only) +Radeon 9800PRO/9800SE/9800, FireGL X2 (2D only) +.TP 12 +.B R360 +Radeon 9800XT (2d only) .TP 12 .B RV350 -Radeon 9600PRO/9600, M10 (2D only) +Radeon 9600PRO/9600SE/9600, M10/M11, FireGL T2 (2D only) +.TP 12 +.B RV360 +Radeon 9600XT (2d only) .SH CONFIGURATION DETAILS Please refer to XF86Config(__filemansuffix__) for general configuration @@ -111,8 +117,8 @@ The default value is .TP .BI "Option \*qUseFBDev\*q \*q" boolean \*q Enable or disable use of an OS\-specific framebuffer device interface -(which is not supported on all OSs). See fbdevhw(__drivermansuffix__) -for further information. +(which is not supported on all OSs). MergedFB does not work when this +option is in use. See fbdevhw(__drivermansuffix__) for further information. .br The default is .B off. @@ -137,13 +143,22 @@ Enable AGP fast write. The default is .B off. .TP -.BI "Option \*qForcePCIMode\*q \*q" boolean \*q -Force to use PCI GART for DRI acceleration. +.BI "Option \*qBusType\*q \*q" string \*q +Used to replace previous ForcePCIMode option. +Should only be used when driver's bus detection is incorrect +or you want to force a AGP card to PCI mode. Should NEVER force +a PCI card to AGP bus. +.br +PCI \-\- PCI bus +.br +AGP \-\- AGP bus +.br +PCIE \-\- PCI Express (falls back to PCI at present) .br (used only when DRI is enabled) .br The default is -.B off. +.B auto detect. .TP .BI "Option \*qDDCMode\*q \*q" boolean \*q Force to use the modes queried from the connected monitor. @@ -151,6 +166,23 @@ Force to use the modes queried from the connected monitor. The default is .B off. .TP +.BI "Option \*qDisplayPriority\*q \*q" string \*q +.br +Used to prevent flickering or tearing problem caused by display buffer underflow. +.br +AUTO \-\- Driver calculated (default). +.br +BIOS \-\- Remain unchanged from BIOS setting. + Use this if the calculation is not correct + for your card. +.br +HIGH \-\- Force to the highest priority. + Use this if you have problem with above options. + This may affect performance slightly. +.br +The default value is +.B AUTO. +.TP .BI "Option \*qMonitorLayout\*q \*q" string \*q .br This option is used to overwrite the detected monitor types. @@ -163,7 +195,7 @@ CRT \-\- Analog CRT monitor .br TMDS \-\- Desktop flat panel .br -LVDS \-\- Lapto flat panel +LVDS \-\- Laptop flat panel .br This option can be used in following format: .br @@ -181,7 +213,7 @@ DVI port on DVI+VGA cards .br LCD output on laptops .br -Internal TMDS prot on DVI+DVI cards +Internal TMDS port on DVI+DVI cards .br .B Secondary head: .br @@ -194,40 +226,162 @@ External TMDS port on DVI+DVI cards The default value is .B undefined. .TP -.BI "Option \*qCloneMode\*q \*q" "string" \*q -Set the first mode for the secondary head. -It can be different from the modes used for the primary head. If you don't -have this line while clone is on, the modes specified for the primary head -will be used for the secondary head. +.BI "Option \*qMergedFB\*q \*q" boolean \*q +This enables merged framebuffer mode. In this mode you have a single +shared framebuffer with two viewports looking into it. It is similar +to Xinerama, but has some advantages. It is faster than Xinerama, the +DRI works on both heads, and it supports clone modes. +.br +Merged framebuffer mode provides two linked viewports looking into a +single large shared framebuffer. The size of the framebuffer is +determined by the +.B Virtual +keyword defined on the +.B Screen +section of your XF86Config file. It works just like regular virtual +desktop except you have two viewports looking into it instead of one. +.br +For example, if you wanted a desktop composed of two 1024x768 viewports +looking into a single desktop you would create a virtual desktop of +2048x768 (left/right) or 1024x1536 (above/below), e.g., +.br +.B Virtual 2048 768 +or +.B Virtual 1024 1536 +.br +The virtual desktop can be larger than larger than the size of the viewports +looking into it. In this case the linked viewports will scroll around in the +virtual desktop. Viewports with different sizes are also supported (e.g., one +that is 1024x768 and one that is 640x480). In this case the smaller viewport +will scroll relative to the larger one such that none of the virtual desktop +is inaccessable. If you do not define a virtual desktop the driver will create +one based on the orientation of the heads and size of the largest defined mode in +the display section that is supported on each head. .br -For example, Option "CloneMode" "1024x768" +The relation of the viewports in specified by the +.B CRT2Position +Option. The options are +.B Clone +, +.B LeftOf +, +.B RightOf +, +.B Above +, and +.B Below. +MergedFB is enabled by default if a monitor is detected on each output. If +no position is given it defaults to clone mode (the old clone options are now +deprecated, also, the option OverlayOnCRTC2 has been replaced by the Xv +attribute XV_SWITCHCRT; the overlay can be switched to CRT1 or CRT2 on the fly +in clone mode). +.br +The maximum framebuffer size that the 2D acceleration engine can handle is +8192x8192. The maximum framebuffer size that the 3D engine can handle is +2048x2048. +.br +.B Note: +Page flipping does not work well in certain configurations with MergedFB. If you +see rendering errors or other strange behavior, disable page flipping. Also MergedFB +is not compatible with the +.B UseFBDev +option. .br The default value is .B undefined. .TP -.BI "Option \*qCloneHSync\*q \*q" "string" \*q +.BI "Option \*qCRT2HSync\*q \*q" "string" \*q Set the horizontal sync range for the secondary monitor. It is not required if a DDC\-capable monitor is connected. .br -For example, Option "CloneHSync" "30.0-86.0" +For example, Option "CRT2HSync" "30.0-86.0" .br The default value is .B undefined. .TP -.BI "Option \*qCloneVRefresh\*q \*q" "string" \*q -Set the vertical refresh range for the secondary monitor. +.BI "Option \*qCRT2VRefresh\*q \*q" "string" \*q +Set the vertical refresh range for the secondary monitor. It is not required if a DDC\-capable monitor is connected. .br -For example, Option "CloneVRefresh" "50.0-120.0" +For example, Option "CRT2VRefresh" "50.0-120.0" +.br +The default value is +.B undefined. +.TP +.BI "Option \*qCRT2Position\*q \*q" "string" \*q +Set the relationship of CRT2 relative to CRT1. Valid options are: +.B Clone +, +.B LeftOf +, +.B RightOf +, +.B Above +, and +.B Below +. +.br +For example, Option "CRT2Position" "RightOf" +.br +The default value is +.B Clone. +.TP +.BI "Option \*qMetaModes\*q \*q" "string" \*q +MetaModes are mode combinations for CRT1 and CRT2. If you are using merged +frame buffer mode and want to change modes (CTRL-ALT-+/-), these define which +modes will be switched to on CRT1 and CRT2. The MetaModes are defined as +CRT1Mode-CRT2Mode (800x600-1024x768). Modes listed individually (800x600) +define clone modes, that way you can mix clone modes with non-clone modes. +Also some programs require "standard" modes. +.br +Note: Any mode you use in the MetaModes must be defined in the +.B Screen +section of your XF86Config file. Modes not defined there will be ignored when +the MetaModes are parsed since the driver uses them to make sure the monitors can +handle those modes. If you do not define a MetaMode the driver will create +one based on the orientation of the heads and size of the largest defined mode in +the display section that is supported on each head. +.br +.B Modes "1024x768" "800x600" "640x480" +.br +For example, Option "MetaModes" "1024x768-1024x768 800x600-1024x768 640x480-800x600 800x600" .br The default value is .B undefined. .TP -.BI "Option \*qOverlayOnCRTC2\*q \*q" boolean \*q -Force hardware overlay to clone head. +.BI "Option \*qNoMergedXinerama\*q \*q" boolean \*q +Since merged framebuffer mode does not use Xinerama, apps are not able to intelligently +place windows. Merged framebuffer mode provides its own pseudo-Xinerama. This allows +Xinerama compliant applications to place windows appropriately. There are some caveats. +Since merged framebuffer mode is able to change relative screen sizes and orientations on +the fly, as well has having overlapping viewports, pseudo-Xinerama, might not always +provide the right hints. Also many Xinerama compliant applications only query Xinerama +once at startup; if the information changes, they may not be aware of the change. If +you are already using Xinerama (e.g., a single head card and a dualhead card providing +three heads), pseudo-Xinerama will be disabled. +.br +This option allows you turn off the driver provided pseudo-Xinerama extension. .br The default value is -.B off. +.B FALSE. +.TP +.BI "Option \*qMergedXineramaCRT2IsScreen0\*q \*q" boolean \*q +By default the pseudo-Xinerama provided by the driver makes the left-most or bottom +head Xinerama screen 0. Certain Xinerama-aware applications do special things with +screen 0. To change that behavior, use this option. +.br +The default value is +.B undefined. +.TP +.BI "Option \*qMergedDPI\*q \*q" "string" \*q +The driver will attempt to figure out an appropriate DPI based on the DDC information +and the orientation of the heads when in merged framebuffer mode. If this value does +not suit you, you can manually set the DPI using this option. +.br +For example, Option "MergedDPI" "100 100" +.br +The default value is +.B undefined. .TP .BI "Option \*qIgnoreEDID\*q \*q" boolean \*q Do not use EDID data for mode validation, but DDC is still used @@ -236,8 +390,21 @@ for monitor detection. This is different from NoDDC option. The default value is .B off. .TP +.BI "Option \*qPanelSize\*q \*q" "string" \*q +Should only be used when driver cannot detect the correct panel size. +Apply to both desktop (TMDS) and laptop (LVDS) digital panels. +When a valid panel size is specified, the timings collected from +DDC and BIOS will not be used. If you have a panel with timings +different from that of a standard VESA mode, you have to provide +this information through the Modeline. +.br +For example, Option "PanelSize" "1400x1050" +.br +The default value is +.B none. +.TP .BI "Option \*qPanelOff\*q \*q" boolean \*q -Disable panel output. Only used when clone is enabled. +Disable panel output. .br The default value is .B off. @@ -246,6 +413,10 @@ The default value is Enable page flipping for 3D acceleration. This will increase performance but not work correctly in some rare cases, hence the default is .B off. +.br +.B Note: +Page flipping does not work well in certain configurations with MergedFB. If you +see rendering errors or other strange behavior, disable page flipping. .SH SEE ALSO diff --git a/src/atiaccel.c b/src/atiaccel.c index 626cb34e..04edd30c 100644 --- a/src/atiaccel.c +++ b/src/atiaccel.c @@ -19,6 +19,9 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Leif Delgass <ldelgass@retinalburn.net> */ #include "atiaccel.h" @@ -64,6 +67,12 @@ ATIInitializeAcceleration #endif /* AVOID_CPIO */ +#ifdef XF86DRI + + /* If DRI is enabled, we've already set up the FB manager in ATIScreenInit */ + if (!pATI->directRenderingEnabled) + +#endif /* XF86DRI */ { /* * Note: If PixelArea exceeds the engine's maximum, the excess is diff --git a/src/atichip.c b/src/atichip.c index f1fa25e7..3c2b094a 100644 --- a/src/atichip.c +++ b/src/atichip.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c,v 1.35 2003/07/02 17:31:28 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.c,v 1.37 2003/10/07 22:47:11 martin Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -101,6 +101,7 @@ const char *ATIChipNames[] = "ATI Radeon 9700/9500", "ATI Radeon 9600", "ATI Radeon 9800", + "ATI Radeon 9800XT", "ATI Rage HDTV" }; @@ -673,14 +674,11 @@ ATIChipID case NewChipID('Q', 'X'): return ATI_CHIP_RV200; - case NewChipID('I', 'd'): - case NewChipID('I', 'e'): case NewChipID('I', 'f'): case NewChipID('I', 'g'): return ATI_CHIP_RV250; case NewChipID('L', 'd'): - case NewChipID('L', 'e'): case NewChipID('L', 'f'): case NewChipID('L', 'g'): return ATI_CHIP_RADEONMOBILITY9; @@ -691,14 +689,12 @@ ATIChipID case NewChipID('Y', '\''): case NewChipID('Y', 'a'): - case NewChipID('I', 'b'): - case NewChipID('I', 'c'): + case NewChipID('Y', 'b'): + case NewChipID('Y', 'd'): return ATI_CHIP_RV280; - case NewChipID('Y', 'h'): - case NewChipID('Y', 'i'): - case NewChipID('Y', 'j'): - case NewChipID('Y', 'k'): + case NewChipID('\\', 'a'): + case NewChipID('\\', 'c'): return ATI_CHIP_RADEONMOBILITY9PLUS; case NewChipID('A', 'D'): @@ -711,16 +707,32 @@ ATIChipID case NewChipID('N', 'G'): return ATI_CHIP_R300; + case NewChipID('A', 'H'): + case NewChipID('A', 'I'): + case NewChipID('A', 'J'): case NewChipID('A', 'K'): case NewChipID('N', 'H'): + case NewChipID('N', 'I'): case NewChipID('N', 'K'): return ATI_CHIP_R350; - case NewChipID('N', 'P'): case NewChipID('A', 'P'): + case NewChipID('A', 'Q'): case NewChipID('A', 'R'): + case NewChipID('A', 'S'): + case NewChipID('A', 'T'): + case NewChipID('A', 'V'): + case NewChipID('N', 'P'): + case NewChipID('N', 'Q'): + case NewChipID('N', 'R'): + case NewChipID('N', 'S'): + case NewChipID('N', 'T'): + case NewChipID('N', 'V'): return ATI_CHIP_RV350; + case NewChipID('N', 'J'): + return ATI_CHIP_R360; + case NewChipID('H', 'D'): return ATI_CHIP_HDTV; diff --git a/src/atichip.h b/src/atichip.h index 96d56ba6..4cc30a0c 100644 --- a/src/atichip.h +++ b/src/atichip.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h,v 1.24 2003/07/02 17:31:29 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atichip.h,v 1.25 2003/10/07 22:47:11 martin Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -103,6 +103,7 @@ typedef enum ATI_CHIP_R300, /* R300 */ ATI_CHIP_RV350, /* RV350 */ ATI_CHIP_R350, /* R350 */ + ATI_CHIP_R360, /* R360 */ ATI_CHIP_HDTV /* HDTV */ } ATIChipType; diff --git a/src/aticonfig.c b/src/aticonfig.c index 3cad3e2d..eb1f428c 100644 --- a/src/aticonfig.c +++ b/src/aticonfig.c @@ -19,6 +19,9 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Leif Delgass <ldelgass@retinalburn.net> */ #include "ati.h" @@ -29,6 +32,8 @@ #include "atioption.h" #include "atistruct.h" +#include "mach64_common.h" + /* * Non-publicised XF86Config options. */ @@ -109,6 +114,17 @@ ATIProcessOptions #endif /* AVOID_CPIO */ +#ifdef XF86DRI + +# define IsPCI PublicOption[ATI_OPTION_IS_PCI].value.bool +# define DMAMode PublicOption[ATI_OPTION_DMA_MODE].value.str +# define AGPMode PublicOption[ATI_OPTION_AGP_MODE].value.num +# define AGPSize PublicOption[ATI_OPTION_AGP_SIZE].value.num +# define LocalTex PublicOption[ATI_OPTION_LOCAL_TEXTURES].value.bool +# define BufferSize PublicOption[ATI_OPTION_BUFFER_SIZE].value.num + +#endif /* XF86DRI */ + # define CacheMMIO PublicOption[ATI_OPTION_MMIO_CACHE].value.bool # define TestCacheMMIO PublicOption[ATI_OPTION_TEST_MMIO_CACHE].value.bool # define PanelDisplay PublicOption[ATI_OPTION_PANEL_DISPLAY].value.bool @@ -155,6 +171,7 @@ ATIProcessOptions } Blend = PanelDisplay = TRUE; + DMAMode = "mmio"; xf86ProcessOptions(pScreenInfo->scrnIndex, pScreenInfo->options, PublicOption); @@ -200,6 +217,32 @@ ATIProcessOptions else pATI->OptionPanelDisplay = !CRTScreen; +#ifdef XF86DRI + + pATI->OptionIsPCI = IsPCI; + pATI->OptionAGPMode = AGPMode; + pATI->OptionAGPSize = AGPSize; + pATI->OptionLocalTextures = LocalTex; + pATI->OptionBufferSize = BufferSize; + + if (strcasecmp(DMAMode, "async")==0) + pATI->OptionDMAMode = MACH64_MODE_DMA_ASYNC; + else if (strcasecmp(DMAMode, "sync")==0) + pATI->OptionDMAMode = MACH64_MODE_DMA_SYNC; + else if (strcasecmp(DMAMode, "mmio")==0 ) + pATI->OptionDMAMode = MACH64_MODE_MMIO; + else { + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "Unkown dma_mode: '%s'\n", DMAMode); + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "Valid dma_mode options are: 'async','sync','mmio'\n"); + xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, + "Defaulting to async DMA mode\n"); + pATI->OptionDMAMode = MACH64_MODE_DMA_ASYNC; + } + +#endif /* XF86DRI */ + /* Validate and set cursor options */ pATI->Cursor = ATI_CURSOR_SOFTWARE; if (SWCursor || !HWCursor) diff --git a/src/aticonsole.c b/src/aticonsole.c index b025cddb..1d65df7c 100644 --- a/src/aticonsole.c +++ b/src/aticonsole.c @@ -19,19 +19,29 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Manuel Teira + * Leif Delgass <ldelgass@retinalburn.net> */ +#include "ati.h" #include "atiadapter.h" #include "aticonsole.h" #include "aticrtc.h" #include "atii2c.h" #include "atilock.h" #include "atimach64.h" +#include "atimach64io.h" #include "atimode.h" #include "atistruct.h" #include "ativga.h" #include "atividmem.h" +#include "mach64_common.h" + + + #include "xf86.h" /* @@ -242,7 +252,28 @@ ATISwitchMode if (pScreenInfo->vtSema) { pScreenInfo->currentMode = pMode; + +#ifdef XF86DRI + + if (pATI->directRenderingEnabled) + { + DRILock(pScreenInfo->pScreen,0); + ATIDRIWaitForIdle(pATI); + } + +#endif /* XF86DRI */ + ATIModeSet(pScreenInfo, pATI, &pATI->NewHW); + +#ifdef XF86DRI + + if (pATI->directRenderingEnabled) + { + DRIUnlock(pScreenInfo->pScreen); + } + +#endif /* XF86DRI */ + } SetTimeSinceLastInputEvent(); @@ -274,7 +305,19 @@ ATIEnterVT /* The rest of this isn't needed for shadowfb */ if (pATI->OptionShadowFB) + { + +#ifdef XF86DRI + + if (pATI->directRenderingEnabled) + { + DRIUnlock(pScreen); + } + +#endif /* XF86DRI */ + return TRUE; + } #ifndef AVOID_CPIO @@ -299,6 +342,15 @@ ATIEnterVT pScreenPixmap->devPrivate.ptr = NULL; } +#ifdef XF86DRI + + if (pATI->directRenderingEnabled) + { + DRIUnlock(pScreen); + } + +#endif /* XF86DRI */ + return Entered; } @@ -316,6 +368,18 @@ ATILeaveVT ) { ScrnInfoPtr pScreenInfo = xf86Screens[iScreen]; + ScreenPtr pScreen = pScreenInfo->pScreen; + ATIPtr pATI = ATIPTR(pScreenInfo); + +#ifdef XF86DRI + + if (pATI->directRenderingEnabled) + { + DRILock(pScreen,0); + ATIDRIWaitForIdle(pATI); + } + +#endif /* XF86DRI */ ATILeaveGraphics(pScreenInfo, ATIPTR(pScreenInfo)); } diff --git a/src/atiload.c b/src/atiload.c index a7eebd1d..9449205a 100644 --- a/src/atiload.c +++ b/src/atiload.c @@ -19,6 +19,9 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Leif Delgass <ldelgass@retinalburn.net> */ #ifdef XFree86LOADER @@ -44,7 +47,7 @@ const char *ATIint10Symbols[] = const char *ATIddcSymbols[] = { "xf86PrintEDID", - "xf86SetDDCProperties", + "xf86SetDDCproperties", NULL }; @@ -72,6 +75,58 @@ const char *ATIxf4bppSymbols[] = #endif /* AVOID_CPIO */ +#ifdef XF86DRI + +const char *ATIdrmSymbols[] = { + "drmAddBufs", + "drmAddMap", + "drmAgpAcquire", + "drmAgpAlloc", + "drmAgpBase", + "drmAgpBind", + "drmAgpDeviceId", + "drmAgpEnable", + "drmAgpFree", + "drmAgpGetMode", + "drmAgpRelease", + "drmAgpUnbind", + "drmAgpVendorId", + "drmAvailable", + "drmCommandNone", + "drmCommandRead", + "drmCommandWrite", + "drmCommandWriteRead", + "drmCtlInstHandler", + "drmCtlUninstHandler", + "drmFreeVersion", + "drmGetInterruptFromBusID", + "drmGetLibVersion", + "drmGetVersion", + "drmMap", + "drmMapBufs", + "drmDMA", + "drmUnmap", + "drmUnmapBufs", + NULL +}; + +const char *ATIdriSymbols[] = { + "DRICloseScreen", + "DRICreateInfoRec", + "DRIDestroyInfoRec", + "DRIFinishScreenInit", + "DRIGetSAREAPrivate", + "DRILock", + "DRIQueryVersion", + "DRIScreenInit", + "DRIUnlock", + "GlxSetVisualConfigs", + "DRICreatePCIBusID", + NULL +}; + +#endif /* XF86DRI */ + const char *ATIfbSymbols[] = { "fbPictureInit", diff --git a/src/atiload.h b/src/atiload.h index a695579e..3447825d 100644 --- a/src/atiload.h +++ b/src/atiload.h @@ -19,6 +19,9 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Leif Delgass <ldelgass@retinalburn.net> */ #ifndef ___ATILOAD_H___ @@ -39,6 +42,12 @@ extern const char *ATIint10Symbols[], *ATIddcSymbols[], *ATIvbeSymbols[], #endif /* AVOID_CPIO */ +#ifdef XF86DRI + + *ATIdrmSymbols[], *ATIdriSymbols[], + +#endif /* XF86DRI */ + *ATIfbSymbols[], *ATIshadowfbSymbols[], *ATIxaaSymbols[], *ATIramdacSymbols[], *ATIi2cSymbols[]; diff --git a/src/atilock.c b/src/atilock.c index b07744d4..4ba06e50 100644 --- a/src/atilock.c +++ b/src/atilock.c @@ -119,6 +119,15 @@ ATIUnlock pATI->LockData.crtc_int_cntl = inr(CRTC_INT_CNTL); outr(CRTC_INT_CNTL, (pATI->LockData.crtc_int_cntl & ~CRTC_INT_ENS) | CRTC_INT_ACKS); + +#ifdef XF86DRI + + if (pATI->irq > 0) + outr(CRTC_INT_CNTL, (inr(CRTC_INT_CNTL) & ~CRTC_INT_ACKS) | + CRTC_VBLANK_INT_EN); /* Enable VBLANK interrupt - handled by DRM */ + +#endif /* XF86DRI */ + pATI->LockData.gen_test_cntl = inr(GEN_TEST_CNTL) & (GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN | GEN_BLOCK_WR_EN); diff --git a/src/atimach64.c b/src/atimach64.c index 89ee7c96..72f4a106 100644 --- a/src/atimach64.c +++ b/src/atimach64.c @@ -20,6 +20,34 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +/* + * Copyright 1999-2000 Precision Insight, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +/* + * DRI support by: + * Manuel Teira + * Leif Delgass <ldelgass@retinalburn.net> + */ #include "ati.h" #include "atibus.h" @@ -197,8 +225,20 @@ ATIMach64PreInit * When possible, max out command FIFO size. */ if (pATI->Chip >= ATI_CHIP_264VT4) + +#ifdef XF86DRI + + /* Changing the FIFO depth seems to interfere with DMA, so use + * default of 128 entries (0x01) + */ + pATIHW->gui_cntl = (inm(GUI_CNTL) & ~CMDFIFO_SIZE_MODE) | 0x01; + +#else /* XF86DRI */ + pATIHW->gui_cntl = inm(GUI_CNTL) & ~CMDFIFO_SIZE_MODE; +#endif /* XF86DRI */ + /* Initialise destination registers */ pATIHW->dst_off_pitch = SetBits((pATI->displayWidth * pATI->XModifier) >> 3, DST_PITCH); @@ -1083,6 +1123,13 @@ ATIMach64SetDPMSMode return; } +#ifdef XF86DRI + + /* XAA Sync requires the DRM lock if DRI enabled */ + ATIDRILock(pScreenInfo); + +#endif /* XF86DRI */ + ATIMach64Sync(pScreenInfo); outr(CRTC_GEN_CNTL, crtc_gen_cntl); @@ -1178,4 +1225,11 @@ ATIMach64SetDPMSMode } } } + +#ifdef XF86DRI + + ATIDRIUnlock(pScreenInfo); + +#endif /* XF86DRI */ + } diff --git a/src/atimach64accel.c b/src/atimach64accel.c index 12029187..b7b8e076 100644 --- a/src/atimach64accel.c +++ b/src/atimach64accel.c @@ -43,6 +43,11 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ +/* + * DRI support by: + * Manuel Teira + * Leif Delgass <ldelgass@retinalburn.net> + */ #include "ati.h" #include "atichip.h" @@ -51,6 +56,8 @@ #include "atipriv.h" #include "atiregs.h" +#include "mach64_common.h" + #include "miline.h" /* Used to test MMIO cache integrity in ATIMach64Sync() */ @@ -130,12 +137,146 @@ ATIMach64Sync { ATIPtr pATI = ATIPTR(pScreenInfo); - ATIMach64WaitForIdle(pATI); - if (pATI->pXAAInfo) - pATI->pXAAInfo->NeedToSync = FALSE; +#ifdef XF86DRI - if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache) + if ( pATI->directRenderingEnabled && pATI->NeedDRISync ) { + ATIHWPtr pATIHW = &pATI->NewHW; + + if (pATI->OptionMMIOCache) { + /* "Invalidate" the MMIO cache so the cache slots get updated */ + UncacheRegister(SRC_CNTL); + UncacheRegister(HOST_CNTL); + UncacheRegister(PAT_CNTL); + UncacheRegister(SC_LEFT_RIGHT); + UncacheRegister(SC_TOP_BOTTOM); + UncacheRegister(DP_BKGD_CLR); + UncacheRegister(DP_FRGD_CLR); + UncacheRegister(DP_WRITE_MASK); + UncacheRegister(DP_MIX); + UncacheRegister(CLR_CMP_CNTL); + } + + ATIDRIWaitForIdle(pATI); + + outr( BUS_CNTL, pATIHW->bus_cntl ); + + /* DRI uses GUI_TRAJ_CNTL, which is a composite of + * src_cntl, dst_cntl, pat_cntl, and host_cntl + */ + outf( SRC_CNTL, pATIHW->src_cntl ); + outf( DST_CNTL, pATIHW->dst_cntl ); + outf( PAT_CNTL, pATIHW->pat_cntl ); + outf( HOST_CNTL, pATIHW->host_cntl ); + + outf( DST_OFF_PITCH, pATIHW->dst_off_pitch ); + outf( SRC_OFF_PITCH, pATIHW->src_off_pitch ); + outf( DP_SRC, pATIHW->dp_src ); + outf( DP_MIX, pATIHW->dp_mix ); + outf( DP_FRGD_CLR, pATIHW->dp_frgd_clr ); + outf( DP_WRITE_MASK, pATIHW->dp_write_mask ); + + outf( DP_PIX_WIDTH, pATIHW->dp_pix_width ); + outf( CLR_CMP_CNTL, pATIHW->clr_cmp_cntl ); + outf( ALPHA_TST_CNTL, 0 ); + outf( Z_CNTL, 0 ); + outf( SCALE_3D_CNTL, 0 ); + + ATIMach64WaitForFIFO(pATI, 2); + outf( SC_LEFT_RIGHT, + SetWord(pATIHW->sc_right, 1) | SetWord(pATIHW->sc_left, 0) ); + outf( SC_TOP_BOTTOM, + SetWord(pATIHW->sc_bottom, 1) | SetWord(pATIHW->sc_top, 0) ); + + if (pATI->OptionMMIOCache) { + /* Now that the cache slots reflect the register state, re-enable MMIO cache */ + CacheRegister(SRC_CNTL); + CacheRegister(HOST_CNTL); + CacheRegister(PAT_CNTL); + CacheRegister(SC_LEFT_RIGHT); + CacheRegister(SC_TOP_BOTTOM); + CacheRegister(DP_BKGD_CLR); + CacheRegister(DP_FRGD_CLR); + CacheRegister(DP_WRITE_MASK); + CacheRegister(DP_MIX); + CacheRegister(CLR_CMP_CNTL); + } + + ATIMach64WaitForIdle(pATI); + + if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache) { + + /* Only check registers we didn't restore */ + TestRegisterCaching(PAT_REG0); + TestRegisterCaching(PAT_REG1); + + TestRegisterCaching(CLR_CMP_CLR); + TestRegisterCaching(CLR_CMP_MSK); + + if (pATI->Block1Base) + { + TestRegisterCaching(OVERLAY_Y_X_START); + TestRegisterCaching(OVERLAY_Y_X_END); + + TestRegisterCaching(OVERLAY_GRAPHICS_KEY_CLR); + TestRegisterCaching(OVERLAY_GRAPHICS_KEY_MSK); + + TestRegisterCaching(OVERLAY_KEY_CNTL); + + TestRegisterCaching(OVERLAY_SCALE_INC); + TestRegisterCaching(OVERLAY_SCALE_CNTL); + + TestRegisterCaching(SCALER_HEIGHT_WIDTH); + + TestRegisterCaching(SCALER_TEST); + + TestRegisterCaching(VIDEO_FORMAT); + + if (pATI->Chip < ATI_CHIP_264VTB) + { + TestRegisterCaching(BUF0_OFFSET); + TestRegisterCaching(BUF0_PITCH); + TestRegisterCaching(BUF1_OFFSET); + TestRegisterCaching(BUF1_PITCH); + } + else + { + TestRegisterCaching(SCALER_BUF0_OFFSET); + TestRegisterCaching(SCALER_BUF1_OFFSET); + TestRegisterCaching(SCALER_BUF_PITCH); + + TestRegisterCaching(OVERLAY_EXCLUSIVE_HORZ); + TestRegisterCaching(OVERLAY_EXCLUSIVE_VERT); + + if (pATI->Chip >= ATI_CHIP_264GTPRO) + { + TestRegisterCaching(SCALER_COLOUR_CNTL); + + TestRegisterCaching(SCALER_H_COEFF0); + TestRegisterCaching(SCALER_H_COEFF1); + TestRegisterCaching(SCALER_H_COEFF2); + TestRegisterCaching(SCALER_H_COEFF3); + TestRegisterCaching(SCALER_H_COEFF4); + + TestRegisterCaching(SCALER_BUF0_OFFSET_U); + TestRegisterCaching(SCALER_BUF0_OFFSET_V); + TestRegisterCaching(SCALER_BUF1_OFFSET_U); + TestRegisterCaching(SCALER_BUF1_OFFSET_V); + } + } + } + } + pATI->NeedDRISync = FALSE; + + } + else + +#endif /* XF86DRI */ + { + ATIMach64WaitForIdle(pATI); + + if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache) + { /* * For debugging purposes, attempt to verify that each cached register * should actually be cached. @@ -227,6 +368,7 @@ ATIMach64Sync } } } + } } /* @@ -235,6 +377,9 @@ ATIMach64Sync * caching of framebuffer data I haven't found any way of disabling, or * otherwise circumventing. Thanks to Mark Vojkovich for the suggestion. */ + if (pATI->pXAAInfo) + pATI->pXAAInfo->NeedToSync = FALSE; + pATI = *(volatile ATIPtr *)pATI->pMemory; } @@ -257,6 +402,8 @@ ATIMach64SetupForScreenToScreenCopy { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + ATIMach64WaitForFIFO(pATI, 3); outf(DP_WRITE_MASK, planemask); outf(DP_SRC, DP_MONO_SRC_ALLONES | @@ -319,6 +466,8 @@ ATIMach64SubsequentScreenToScreenCopy xDst *= pATI->XModifier; w *= pATI->XModifier; + ATIDRISync(pScreenInfo); + /* Disable clipping if it gets in the way */ ATIMach64ValidateClip(pATI, xDst, xDst + w - 1, yDst, yDst + h - 1); @@ -360,6 +509,8 @@ ATIMach64SetupForSolidFill { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + ATIMach64WaitForFIFO(pATI, 5); outf(DP_WRITE_MASK, planemask); outf(DP_SRC, DP_MONO_SRC_ALLONES | @@ -390,6 +541,8 @@ ATIMach64SubsequentSolidFillRect { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + if (pATI->XModifier != 1) { x *= pATI->XModifier; @@ -424,6 +577,8 @@ ATIMach64SetupForSolidLine { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + ATIMach64WaitForFIFO(pATI, 5); outf(DP_WRITE_MASK, planemask); outf(DP_SRC, DP_MONO_SRC_ALLONES | @@ -455,6 +610,8 @@ ATIMach64SubsequentSolidHorVertLine { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + ATIMach64WaitForFIFO(pATI, 3); outf(DST_CNTL, DST_X_DIR | DST_Y_DIR); outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); @@ -495,6 +652,8 @@ ATIMach64SubsequentSolidBresenhamLine if (!(octant & YDECREASING)) dst_cntl |= DST_Y_DIR; + ATIDRISync(pScreenInfo); + ATIMach64WaitForFIFO(pATI, 6); outf(DST_CNTL, dst_cntl); outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0)); @@ -524,6 +683,8 @@ ATIMach64SetupForMono8x8PatternFill { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + ATIMach64WaitForFIFO(pATI, 3); outf(DP_WRITE_MASK, planemask); outf(DP_SRC, DP_MONO_SRC_PATTERN | @@ -573,6 +734,8 @@ ATIMach64SubsequentMono8x8PatternFillRect { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + if (pATI->XModifier != 1) { x *= pATI->XModifier; @@ -607,6 +770,8 @@ ATIMach64SetupForScanlineCPUToScreenColorExpandFill { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + ATIMach64WaitForFIFO(pATI, 3); outf(DP_WRITE_MASK, planemask); outf(DP_SRC, DP_MONO_SRC_HOST | @@ -650,6 +815,8 @@ ATIMach64SubsequentScanlineCPUToScreenColorExpandFill { ATIPtr pATI = ATIPTR(pScreenInfo); + ATIDRISync(pScreenInfo); + if (pATI->XModifier != 1) { x *= pATI->XModifier; @@ -691,6 +858,8 @@ ATIMach64SubsequentColorExpandScanline int w = pATI->ExpansionBitmapWidth; int nDWord; + ATIDRISync(pScreenInfo); + while (w > 0) { /* diff --git a/src/atimach64cursor.c b/src/atimach64cursor.c index 8cd76dba..6b55d423 100644 --- a/src/atimach64cursor.c +++ b/src/atimach64cursor.c @@ -132,6 +132,13 @@ ATIMach64LoadCursorImage CARD32 *pSrc = (pointer)pImage; volatile CARD32 *pDst = pATI->pCursorImage; +#ifdef XF86DRI + + /* XAA Sync requires the DRM lock if DRI enabled */ + ATIDRILock(pScreenInfo); + +#endif /* XF86DRI */ + /* Synchronise video memory accesses */ ATIMach64Sync(pScreenInfo); @@ -277,6 +284,12 @@ ATIMach64LoadCursorImage #endif +#ifdef XF86DRI + + ATIDRIUnlock(pScreenInfo); + +#endif /* XF86DRI */ + } /* diff --git a/src/atimach64io.h b/src/atimach64io.h index e4db52a3..d9da1d2b 100644 --- a/src/atimach64io.h +++ b/src/atimach64io.h @@ -19,6 +19,10 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Manuel Teira + * Leif Delgass <ldelgass@retinalburn.net> */ #ifndef ___ATIMACH64IO_H___ @@ -200,6 +204,70 @@ extern void ATIMach64PollEngineStatus FunctionPrototype((ATIPtr)); while ((_pATI)->EngineIsBusy) \ ATIMach64PollEngineStatus(_pATI) +#ifdef XF86DRI + +#define ATIDRIWaitForIdle(_pATI) \ +do { \ + ATIDRIServerInfoPtr pATIDRIServer = _pATI->pDRIServerInfo; \ + int ret; \ + \ + if (pATIDRIServer && pATI->directRenderingEnabled) { \ + /* Wait for DMA to complete */ \ + ret = drmCommandNone(_pATI->drmFD, DRM_MACH64_IDLE); \ + if (ret) { \ + drmCommandNone(_pATI->drmFD, DRM_MACH64_RESET); \ + } \ + \ + /* Force updating of FIFO entry counters */ \ + pATI->EngineIsBusy = TRUE; \ + ATIMach64PollEngineStatus(_pATI); \ + } else { \ + ATIMach64WaitForIdle(_pATI); \ + } \ +} while (0) + +#define ATIDRILock(_pScrInfo) \ +do \ +{ \ + ATIPtr _pATI=ATIPTR(_pScrInfo); \ + if (_pATI->directRenderingEnabled) \ + { \ + DRILock(_pScrInfo->pScreen, 0); \ + pATI->NeedDRISync = TRUE; \ + } \ +} while (0) + +#define ATIDRIUnlock(_pScrInfo) \ +do \ +{ \ + ATIPtr _pATI=ATIPTR(_pScrInfo); \ + if (_pATI->directRenderingEnabled) \ + { \ + DRIUnlock(_pScrInfo->pScreen); \ + } \ +} while (0) + +#define ATIDRISync(_pScrInfo) \ +do \ +{ \ + ATIPtr _pATI=ATIPTR(_pScrInfo); \ + if (_pATI->directRenderingEnabled && _pATI->pXAAInfo) \ + { \ + if (_pATI->NeedDRISync) (*_pATI->pXAAInfo->Sync)(_pScrInfo); \ + } \ +} while (0) + +#else /* XF86DRI */ + + +#define ATIDRIWaitForIdle(_pATI) +#define ATIDRILock(_pScrInfo) +#define ATIDRIUnlock(_pScrInfo) +#define ATIDRISync(_pScrInfo) + +#endif /* XF86DRI */ + + /* * An outf() variant to write two registers such that the second register is * is always written whenever either is to be changed. diff --git a/src/atimisc.c b/src/atimisc.c index a84eac49..61801eb7 100644 --- a/src/atimisc.c +++ b/src/atimisc.c @@ -19,6 +19,9 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Leif Delgass <ldelgass@retinalburn.net> */ #ifdef XFree86LOADER @@ -81,6 +84,13 @@ ATISetup #endif /* AVOID_CPIO */ +#ifdef XF86DRI + + ATIdrmSymbols, + ATIdriSymbols, + +#endif /* XF86DRI */ + ATIfbSymbols, ATIshadowfbSymbols, ATIxaaSymbols, diff --git a/src/atioption.c b/src/atioption.c index 6b84128c..1bd90eca 100644 --- a/src/atioption.c +++ b/src/atioption.c @@ -19,6 +19,9 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Leif Delgass <ldelgass@retinalburn.net> */ #include "atioption.h" @@ -73,6 +76,53 @@ const OptionInfoRec ATIPublicOptions[] = #endif /* AVOID_CPIO */ +#ifdef XF86DRI + + { + ATI_OPTION_IS_PCI, + "force_pci_mode", + OPTV_BOOLEAN, + {0, }, + FALSE, + }, + { + ATI_OPTION_DMA_MODE, + "dma_mode", + OPTV_STRING, + {0, }, + FALSE, + }, + { + ATI_OPTION_AGP_MODE, + "agp_mode", + OPTV_INTEGER, + {0, }, + FALSE, + }, + { + ATI_OPTION_AGP_SIZE, + "agp_size", + OPTV_INTEGER, + {0, }, + FALSE, + }, + { + ATI_OPTION_LOCAL_TEXTURES, + "local_textures", + OPTV_BOOLEAN, + {0, }, + FALSE, + }, + { + ATI_OPTION_BUFFER_SIZE, + "buffer_size", + OPTV_INTEGER, + {0, }, + FALSE, + }, + +#endif /* XF86DRI */ + { ATI_OPTION_MMIO_CACHE, "mmio_cache", @@ -80,6 +130,8 @@ const OptionInfoRec ATIPublicOptions[] = {0, }, FALSE }, + + { ATI_OPTION_TEST_MMIO_CACHE, "test_mmio_cache", diff --git a/src/atioption.h b/src/atioption.h index 2e629b8d..6a907dbd 100644 --- a/src/atioption.h +++ b/src/atioption.h @@ -19,6 +19,9 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Leif Delgass <ldelgass@retinalburn.net> */ #ifndef ___ATIOPTION_H___ @@ -44,6 +47,17 @@ typedef enum #endif /* AVOID_CPIO */ +#ifdef XF86DRI + + ATI_OPTION_IS_PCI, + ATI_OPTION_DMA_MODE, + ATI_OPTION_AGP_MODE, + ATI_OPTION_AGP_SIZE, + ATI_OPTION_LOCAL_TEXTURES, + ATI_OPTION_BUFFER_SIZE, + +#endif /* XF86DRI */ + ATI_OPTION_MMIO_CACHE, ATI_OPTION_TEST_MMIO_CACHE, ATI_OPTION_PANEL_DISPLAY, diff --git a/src/atiprobe.c b/src/atiprobe.c index 5e2c31bb..8dc80ba1 100644 --- a/src/atiprobe.c +++ b/src/atiprobe.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprobe.c,v 1.58 2003/07/02 17:31:29 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprobe.c,v 1.60 2003/10/07 22:47:11 martin Exp $ */ /* * Copyright 1997 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org * @@ -206,7 +206,7 @@ ATICheckSparseIOBases /* User might wish to override this decision */ xf86Msg(X_WARNING, - ATI_NAME ": Sparse I/O base 0x%04X not probed.\n", IOBase); + ATI_NAME ": Sparse I/O base 0x%04lX not probed.\n", IOBase); return Allowed; } } @@ -310,7 +310,7 @@ ATIVGAWonderProbe case 0: xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability could not be" - " detected at I/O port 0x%04X because it would conflict with" + " detected at I/O port 0x%04lX because it would conflict with" " a non-video PCI/AGP device.\n", pATI->CPIO_VGAWonder); pATI->CPIO_VGAWonder = 0; break; @@ -318,7 +318,7 @@ ATIVGAWonderProbe case Detected8514A: xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability could not be" - " detected at I/O port 0x%04X because it would conflict with" + " detected at I/O port 0x%04lX because it would conflict with" " a %s %s.\n", pATI->CPIO_VGAWonder, ATIBusNames[p8514->BusType], ATIAdapterNames[p8514->Adapter]); pATI->CPIO_VGAWonder = 0; @@ -327,7 +327,7 @@ ATIVGAWonderProbe case DetectedMach64: xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability could not be" - " detected at I/O port 0x%04X because it would conflict with" + " detected at I/O port 0x%04lX because it would conflict with" " a Mach64.\n", pATI->CPIO_VGAWonder); pATI->CPIO_VGAWonder = 0; break; @@ -367,14 +367,14 @@ ATIVGAWonderProbe (IOValue6 == 0)) { xf86MsgVerb(X_INFO, 3, - ATI_NAME ": VGA Wonder at I/O port 0x%04X detected.\n", + ATI_NAME ": VGA Wonder at I/O port 0x%04lX detected.\n", pATI->CPIO_VGAWonder); } else { xf86Msg(X_WARNING, ATI_NAME ": Expected VGA Wonder capability at I/O port" - " 0x%04X was not detected.\n", pATI->CPIO_VGAWonder); + " 0x%04lX was not detected.\n", pATI->CPIO_VGAWonder); pATI->CPIO_VGAWonder = 0; } break; @@ -1300,7 +1300,7 @@ ATIProbe 4, fChipsets[ATI_CHIPSET_MACH64]) != DoProbe) { xf86MsgVerb(X_INFO, 2, - ATI_NAME ": Unshared Mach64 at PIO base 0x%04X not" + ATI_NAME ": Unshared Mach64 at PIO base 0x%04lX not" " probed.\n", Mach64SparseIOBases[i]); continue; @@ -1310,7 +1310,7 @@ ATIProbe if (!pATI) { xf86MsgVerb(X_INFO, 4, - ATI_NAME ": Unshared Mach64 at PIO base 0x%04X not" + ATI_NAME ": Unshared Mach64 at PIO base 0x%04lX not" " detected.\n", Mach64SparseIOBases[i]); continue; } @@ -1604,7 +1604,7 @@ ATIProbe ATI_NAME ": PCI Mach64 in slot %d:%d:%d will" " not be enabled\n because it conflicts with" " another %s Mach64 at sparse I/O base" - " 0x%04X.\n", + " 0x%04lX.\n", pVideo->bus, pVideo->device, pVideo->func, ATIBusNames[pATI->BusType], Mach64SparseIOBases[j]); @@ -1639,7 +1639,7 @@ ATIProbe "Shared PCI Mach64 in slot %d:%d:%d", pVideo->bus, pVideo->device, pVideo->func); xf86MsgVerb(X_INFO, 3, - ATI_NAME ": %s with sparse PIO base 0x%04X" + ATI_NAME ": %s with sparse PIO base 0x%04lX" " detected.\n", Identifier, Mach64SparseIOBases[j]); AddAdapter(pATI); @@ -1753,6 +1753,7 @@ ATIProbe case ATI_CHIP_R300: case ATI_CHIP_RV350: case ATI_CHIP_R350: + case ATI_CHIP_R360: DoRadeon = TRUE; continue; diff --git a/src/atiregs.h b/src/atiregs.h index 943dbadd..b0c3d847 100644 --- a/src/atiregs.h +++ b/src/atiregs.h @@ -1935,6 +1935,19 @@ #define CRT_HORZ_VERT_LOAD BlockIOTag(0x151u) /* VTB/GTB */ #define AGP_BASE BlockIOTag(0x152u) /* GTPro */ #define AGP_CNTL BlockIOTag(0x153u) /* GTPro */ +#define AGP_MODE_1X 0x00000001ul +#define AGP_MODE_2X 0x00000002ul +#define AGP_MODE_MASK 0x00000003ul +#define AGP_APER_SIZE_MASK 0x0000003ful +#define AGP_APER_SIZE_4MB 0x0000003ful +#define AGP_APER_SIZE_8MB 0x0000003eul +#define AGP_APER_SIZE_16MB 0x0000003cul +#define AGP_APER_SIZE_32MB 0x00000038ul +#define AGP_APER_SIZE_64MB 0x00000030ul +#define AGP_APER_SIZE_128MB 0x00000020ul +#define AGP_APER_SIZE_256MB 0x00000000ul +#define HIGH_PRIORITY_READ_EN 0x00010000ul +#define AGP_TRDY_MODE 0x00020000ul #define SCALER_COLOUR_CNTL BlockIOTag(0x154u) /* GTPro */ #define SCALE_BRIGHTNESS 0x0000007ful /* ? 0x00000080ul */ diff --git a/src/atiscreen.c b/src/atiscreen.c index daf5a8ce..ec784cbc 100644 --- a/src/atiscreen.c +++ b/src/atiscreen.c @@ -19,17 +19,31 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Gareth Hughes <gareth@valinux.com> + * José Fonseca <j_r_fonseca@yahoo.co.uk> + * Leif Delgass <ldelgass@retinalburn.net> */ #include "ati.h" +#include "atibus.h" +#include "atichip.h" #include "atiaccel.h" #include "aticonsole.h" #include "aticursor.h" #include "atidac.h" #include "atidga.h" +#include "atidri.h" +#include "atimach64.h" +#include "atimode.h" #include "atiscreen.h" #include "atistruct.h" #include "atixv.h" +#include "atimach64accel.h" + +#include "mach64_dri.h" +#include "mach64_sarea.h" #include "shadowfb.h" #include "xf86cmap.h" @@ -81,6 +95,24 @@ ATIRefreshArea } /* + * ATIMinBits -- + * + * Compute log base 2 of val. + */ +static int +ATIMinBits +( + int val +) +{ + int bits; + + if (!val) return 1; + for (bits = 0; val; val >>= 1, ++bits); + return bits; +} + +/* * ATIScreenInit -- * * This function is called by DIX to initialise the screen. @@ -98,6 +130,7 @@ ATIScreenInit ATIPtr pATI = ATIPTR(pScreenInfo); pointer pFB; int VisualMask; + BoxRec ScreenArea; /* Set video hardware state */ if (!ATIEnterGraphics(pScreen, pScreenInfo, pATI)) @@ -122,6 +155,8 @@ ATIScreenInit pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth); if (pATI->OptionShadowFB) { + pATI->FBBytesPerPixel = pATI->bitsPerPixel >> 3; + pATI->FBPitch = PixmapBytePad(pATI->displayWidth, pATI->depth); if ((pATI->pShadow = xalloc(pATI->FBPitch * pScreenInfo->virtualY))) { pFB = pATI->pShadow; @@ -134,6 +169,50 @@ ATIScreenInit } } +#ifdef XF86DRI + + /* Setup DRI after visuals have been established, but before + * cfbScreenInit is called. cfbScreenInit will eventually call the + * driver's InitGLXVisuals call back. + */ + + /* According to atiregs.h, GTPro (3D Rage Pro) is the first chip type with + * 3D triangle setup (the VERTEX_* registers) + */ + if (pATI->Chip < ATI_CHIP_264GTPRO) { + xf86DrvMsg(iScreen, X_WARNING, + "Direct rendering is not supported for ATI chips earlier than " + "the ATI 3D Rage Pro.\n"); + pATI->directRenderingEnabled = FALSE; + } else { + /* FIXME: When we move to dynamic allocation of back and depth + * buffers, we will want to revisit the following check for 3 + * times the virtual size (or 2.5 times for 24-bit depth) of the screen below. + */ + int cpp = pATI->bitsPerPixel >> 3; + int maxY = pScreenInfo->videoRam * 1024 / (pATI->displayWidth * cpp); + int requiredY; + + requiredY = pScreenInfo->virtualY * 2 /* front, back buffers */ + + (pScreenInfo->virtualY * 2 / cpp); /* depth buffer (always 16-bit) */ + + if (!pATI->OptionAccel) { + xf86DrvMsg(iScreen, X_WARNING, + "Acceleration disabled, not initializing the DRI\n"); + pATI->directRenderingEnabled = FALSE; + } else if ( maxY > requiredY ) { + pATI->directRenderingEnabled = ATIDRIScreenInit(pScreen); + } else { + xf86DrvMsg(iScreen, X_WARNING, + "DRI static buffer allocation failed -- " + "need at least %d kB video memory\n", + (pScreenInfo->displayWidth * requiredY * cpp ) / 1024); + pATI->directRenderingEnabled = FALSE; + } + } + +#endif /* XF86DRI */ + /* Initialise framebuffer layer */ switch (pATI->bitsPerPixel) { @@ -234,7 +313,183 @@ ATIScreenInit #endif /* AVOID_CPIO */ + /* Memory manager setup */ + +#ifdef XF86DRI + + if (pATI->directRenderingEnabled) + { + ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo; + int cpp = pATI->bitsPerPixel >> 3; + int widthBytes = pScreenInfo->displayWidth * cpp; + int zWidthBytes = pScreenInfo->displayWidth * 2; /* always 16-bit z-buffer */ + int fbSize = pScreenInfo->videoRam * 1024; + int bufferSize = pScreenInfo->virtualY * widthBytes; + int zBufferSize = pScreenInfo->virtualY * zWidthBytes; + int offscreenBytes, total, scanlines; + + pATIDRIServer->fbX = 0; + pATIDRIServer->fbY = 0; + pATIDRIServer->frontOffset = 0; + pATIDRIServer->frontPitch = pScreenInfo->displayWidth; + + /* Calculate memory remaining for pixcache and textures after + * front, back, and depth buffers + */ + offscreenBytes = fbSize - ( 2 * bufferSize + zBufferSize ); + + if ( !pATIDRIServer->IsPCI && !pATI->OptionLocalTextures ) { + /* Don't allocate a local texture heap for AGP unless requested */ + pATIDRIServer->textureSize = 0; + } else { + int l, maxPixcache; + +# ifdef XvExtension + + int xvBytes; + + /* Try for enough pixmap cache for DVD and a full viewport + */ + xvBytes = 720*480*cpp; /* enough for single-buffered DVD */ + maxPixcache = xvBytes > bufferSize ? xvBytes : bufferSize; + +# else /* XvExtension */ + + /* Try for one viewport */ + maxPixcache = bufferSize; + +# endif /* XvExtension */ + + pATIDRIServer->textureSize = offscreenBytes - maxPixcache; + + /* If that gives us less than half the offscreen mem available for textures, split + * the available mem between textures and pixmap cache + */ + if (pATIDRIServer->textureSize < (offscreenBytes/2)) { + pATIDRIServer->textureSize = offscreenBytes/2; + } + + if (pATIDRIServer->textureSize <= 0) + pATIDRIServer->textureSize = 0; + + l = ATIMinBits((pATIDRIServer->textureSize-1) / MACH64_NR_TEX_REGIONS); + if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY; + + /* Round the texture size up to the nearest whole number of + * texture regions. Again, be greedy about this, don't round + * down. + */ + pATIDRIServer->logTextureGranularity = l; + pATIDRIServer->textureSize = + (pATIDRIServer->textureSize >> l) << l; + } + + total = fbSize - pATIDRIServer->textureSize; + scanlines = total / widthBytes; + if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY; + + /* Recalculate the texture offset and size to accomodate any + * rounding to a whole number of scanlines. + * FIXME: Is this actually needed? + */ + pATIDRIServer->textureOffset = scanlines * widthBytes; + pATIDRIServer->textureSize = fbSize - pATIDRIServer->textureOffset; + + /* Set a minimum usable local texture heap size. This will fit + * two 256x256 textures. We check this after any rounding of + * the texture area. + */ + if (pATIDRIServer->textureSize < 256*256 * cpp * 2) { + pATIDRIServer->textureOffset = 0; + pATIDRIServer->textureSize = 0; + scanlines = fbSize / widthBytes; + if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY; + } + + pATIDRIServer->depthOffset = scanlines * widthBytes - zBufferSize; + pATIDRIServer->depthPitch = pScreenInfo->displayWidth; + pATIDRIServer->depthY = pATIDRIServer->depthOffset/widthBytes; + pATIDRIServer->depthX = (pATIDRIServer->depthOffset - + (pATIDRIServer->depthY * widthBytes)) / cpp; + + pATIDRIServer->backOffset = pATIDRIServer->depthOffset - bufferSize; + pATIDRIServer->backPitch = pScreenInfo->displayWidth; + pATIDRIServer->backY = pATIDRIServer->backOffset/widthBytes; + pATIDRIServer->backX = (pATIDRIServer->backOffset - + (pATIDRIServer->backY * widthBytes)) / cpp; + + scanlines = fbSize / widthBytes; + if (scanlines > ATIMach64MaxY) scanlines = ATIMach64MaxY; + + if ( pATIDRIServer->IsPCI && pATIDRIServer->textureSize == 0 ) { + xf86DrvMsg(iScreen, X_WARNING, + "Not enough memory for local textures, disabling DRI\n"); + ATIDRICloseScreen(pScreen); + pATI->directRenderingEnabled = FALSE; + } else { + + ScreenArea.x1 = 0; + ScreenArea.y1 = 0; + ScreenArea.x2 = pATI->displayWidth; + ScreenArea.y2 = scanlines; + + if (!xf86InitFBManager(pScreen, &ScreenArea)) { + xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, + "Memory manager initialization to (%d,%d) (%d,%d) failed\n", + ScreenArea.x1, ScreenArea.y1, + ScreenArea.x2, ScreenArea.y2); + return FALSE; + } else { + int width, height; + + xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, + "Memory manager initialized to (%d,%d) (%d,%d)\n", + ScreenArea.x1, ScreenArea.y1, ScreenArea.x2, ScreenArea.y2); + + if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) { + xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, + "Largest offscreen area available: %d x %d\n", + width, height); + + /* lines in offscreen area needed for depth buffer and textures */ + pATI->depthTexLines = scanlines + - pATIDRIServer->depthOffset / widthBytes; + pATI->backLines = scanlines + - pATIDRIServer->backOffset / widthBytes + - pATI->depthTexLines; + pATI->depthTexArea = NULL; + pATI->backArea = NULL; + } else { + xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR, + "Unable to determine largest offscreen area available\n"); + return FALSE; + } + + } + + xf86DrvMsg(iScreen, X_INFO, "Will use %d kB of offscreen memory for XAA\n", + (offscreenBytes - pATIDRIServer->textureSize)/1024); + + xf86DrvMsg(iScreen, X_INFO, "Will use back buffer at offset 0x%x\n", + pATIDRIServer->backOffset); + + xf86DrvMsg(iScreen, X_INFO, "Will use depth buffer at offset 0x%x\n", + pATIDRIServer->depthOffset); + + if (pATIDRIServer->textureSize > 0) { + xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, + "Will use %d kB for local textures at offset 0x%x\n", + pATIDRIServer->textureSize/1024, + pATIDRIServer->textureOffset); + } + } + } + +#endif /* XF86DRI */ + /* Setup acceleration */ + /* If direct rendering is not enabled, the framebuffer memory + * manager is initialized by this function call */ if (!ATIInitializeAcceleration(pScreen, pScreenInfo, pATI)) return FALSE; @@ -294,6 +549,26 @@ ATIScreenInit if (serverGeneration == 1) xf86ShowUnusedOptions(pScreenInfo->scrnIndex, pScreenInfo->options); +#ifdef XF86DRI + + /* DRI finalization */ + if (pATI->directRenderingEnabled) { + /* Now that mi, cfb, drm and others have done their thing, + * complete the DRI setup. + */ + pATI->directRenderingEnabled = ATIDRIFinishScreenInit(pScreen); + } + if (pATI->directRenderingEnabled) { + xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, + "Direct rendering enabled\n"); + } else { + /* FIXME: Release unused offscreen mem here? */ + xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO, + "Direct rendering disabled\n"); + } + +#endif /* XF86DRI */ + return TRUE; } @@ -313,6 +588,17 @@ ATICloseScreen ATIPtr pATI = ATIPTR(pScreenInfo); Bool Closed = TRUE; +#ifdef XF86DRI + + /* Disable direct rendering */ + if (pATI->directRenderingEnabled) + { + ATIDRICloseScreen(pScreen); + pATI->directRenderingEnabled = FALSE; + } + +#endif /* XF86DRI */ + ATICloseXVideo(pScreen, pScreenInfo, pATI); if (pATI->pXAAInfo) diff --git a/src/atistruct.h b/src/atistruct.h index 8b98931c..cbaf1b85 100644 --- a/src/atistruct.h +++ b/src/atistruct.h @@ -19,6 +19,10 @@ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. + * + * DRI support by: + * Gareth Hughes <gareth@valinux.com> + * Leif Delgass <ldelgass@retinalburn.net> */ #ifndef ___ATISTRUCT_H___ @@ -28,6 +32,20 @@ #include "aticlock.h" #include "atiregs.h" +#ifdef XF86DRI + +/* + * DRI support + */ +#define _XF86DRI_SERVER_ +#include "atidripriv.h" +#include "mach64_dri.h" +#include "sarea.h" +#include "xf86dri.h" +#include "dri.h" + +#endif /* XF86DRI */ + #include "xaa.h" #include "xf86Cursor.h" #include "xf86Pci.h" @@ -250,7 +268,7 @@ typedef struct _ATIRec pointer pMemory, pShadow; pointer pMemoryLE; /* Always little-endian */ unsigned long LinearBase; - int LinearSize, FBPitch; + int LinearSize, FBPitch, FBBytesPerPixel; #ifndef AVOID_CPIO @@ -435,6 +453,37 @@ typedef struct _ATIRec * Wrapped functions. */ CloseScreenProcPtr CloseScreen; + +#ifdef XF86DRI + + /* + * DRI data. + */ + int directRenderingEnabled; + DRIInfoPtr pDRIInfo; + int drmFD; + int irq; + int numVisualConfigs; + __GLXvisualConfig *pVisualConfigs; + ATIConfigPrivPtr pVisualConfigsPriv; + ATIDRIServerInfoPtr pDRIServerInfo; + Bool NeedDRISync; + Bool have3DWindows; + + /* offscreen memory management */ + int backLines; + FBAreaPtr backArea; + int depthTexLines; + FBAreaPtr depthTexArea; + CARD8 OptionIsPCI; /* Force PCI mode */ + CARD8 OptionDMAMode; /* async, sync, mmio */ + CARD8 OptionAGPMode; /* AGP mode */ + CARD8 OptionAGPSize; /* AGP size in MB */ + CARD8 OptionLocalTextures; /* Use local textures + AGP textures (only valid for AGP) */ + CARD8 OptionBufferSize; /* Command/dma buffer size in MB */ + +#endif /* XF86DRI */ + } ATIRec; #define ATIPTR(_p) ((ATIPtr)((_p)->driverPrivate)) @@ -289,19 +289,19 @@ typedef struct { Bool directRenderingEnabled; DRIInfoPtr pDRIInfo; int drmFD; - drmContext drmCtx; + drm_context_t drmCtx; int numVisualConfigs; __GLXvisualConfig *pVisualConfigs; R128ConfigPrivPtr pVisualConfigsPriv; - drmHandle fbHandle; + drm_handle_t fbHandle; drmSize registerSize; - drmHandle registerHandle; + drm_handle_t registerHandle; Bool IsPCI; /* Current card is a PCI card */ drmSize pciSize; - drmHandle pciMemHandle; + drm_handle_t pciMemHandle; unsigned char *PCI; /* Map */ Bool allowPageFlip; /* Enable 3d page flipping */ @@ -309,7 +309,7 @@ typedef struct { int drmMinor; drmSize agpSize; - drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ + drm_handle_t agpMemHandle; /* Handle from drmAgpAlloc */ unsigned long agpOffset; unsigned char *AGP; /* Map */ int agpMode; @@ -322,20 +322,20 @@ typedef struct { /* CCE ring buffer data */ unsigned long ringStart; /* Offset into AGP space */ - drmHandle ringHandle; /* Handle from drmAddMap */ + drm_handle_t ringHandle; /* Handle from drmAddMap */ drmSize ringMapSize; /* Size of map */ int ringSize; /* Size of ring (in MB) */ unsigned char *ring; /* Map */ int ringSizeLog2QW; unsigned long ringReadOffset; /* Offset into AGP space */ - drmHandle ringReadPtrHandle; /* Handle from drmAddMap */ + drm_handle_t ringReadPtrHandle; /* Handle from drmAddMap */ drmSize ringReadMapSize; /* Size of map */ unsigned char *ringReadPtr; /* Map */ /* CCE vertex/indirect buffer data */ unsigned long bufStart; /* Offset into AGP space */ - drmHandle bufHandle; /* Handle from drmAddMap */ + drm_handle_t bufHandle; /* Handle from drmAddMap */ drmSize bufMapSize; /* Size of map */ int bufSize; /* Size of buffers (in MB) */ unsigned char *buf; /* Map */ @@ -344,7 +344,7 @@ typedef struct { /* CCE AGP Texture data */ unsigned long agpTexStart; /* Offset into AGP space */ - drmHandle agpTexHandle; /* Handle from drmAddMap */ + 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 */ diff --git a/src/r128_accel.c b/src/r128_accel.c index 9329ad25..98877962 100644 --- a/src/r128_accel.c +++ b/src/r128_accel.c @@ -87,6 +87,7 @@ #include "r128_sarea.h" #define _XF86DRI_SERVER_ #include "r128_dri.h" +#include "r128_common.h" #endif /* Line support */ diff --git a/src/r128_dri.c b/src/r128_dri.c index 48765b15..ef2f9daa 100644 --- a/src/r128_dri.c +++ b/src/r128_dri.c @@ -40,6 +40,7 @@ /* Driver data structures */ #include "r128.h" #include "r128_dri.h" +#include "r128_common.h" #include "r128_reg.h" #include "r128_sarea.h" #include "r128_version.h" @@ -277,7 +278,7 @@ static Bool R128InitVisualConfigs(ScreenPtr pScreen) /* Create the Rage 128-specific context information */ static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual, - drmContext hwContext, void *pVisualConfigPriv, + drm_context_t hwContext, void *pVisualConfigPriv, DRIContextType contextStore) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -288,7 +289,7 @@ static Bool R128CreateContext(ScreenPtr pScreen, VisualPtr visual, } /* Destroy the Rage 128-specific context information */ -static void R128DestroyContext(ScreenPtr pScreen, drmContext hwContext, +static void R128DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, DRIContextType contextStore) { /* Nothing yet */ @@ -1022,12 +1023,16 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) info->pDRIInfo = pDRIInfo; pDRIInfo->drmDriverName = R128_DRIVER_NAME; pDRIInfo->clientDriverName = R128_DRIVER_NAME; - pDRIInfo->busIdString = xalloc(64); - sprintf(pDRIInfo->busIdString, - "PCI:%d:%d:%d", - info->PciInfo->bus, - info->PciInfo->device, - info->PciInfo->func); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, + "PCI:%d:%d:%d", + info->PciInfo->bus, + info->PciInfo->device, + info->PciInfo->func); + } pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR; pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR; pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH; @@ -1329,10 +1334,10 @@ void R128DRICloseScreen(ScreenPtr pScreen) drmUnmap(info->ring, info->ringMapSize); info->ring = NULL; } - if (info->agpMemHandle!=DRM_AGP_NO_HANDLE) { + if (info->agpMemHandle != DRM_AGP_NO_HANDLE) { drmAgpUnbind(info->drmFD, info->agpMemHandle); drmAgpFree(info->drmFD, info->agpMemHandle); - info->agpMemHandle = 0; + info->agpMemHandle = DRM_AGP_NO_HANDLE; drmAgpRelease(info->drmFD); } if (info->pciMemHandle) { @@ -1473,13 +1478,17 @@ static void R128DRITransitionTo2d(ScreenPtr pScreen) R128InfoPtr info = R128PTR(pScrn); R128SAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + /* Try flipping back to the front page if necessary */ + if (pSAREAPriv->pfCurrentPage == 1) + drmCommandNone(info->drmFD, DRM_R128_FLIP); + /* Shut down shadowing if we've made it back to the front page */ if (pSAREAPriv->pfCurrentPage == 0) { R128DisablePageFlip(pScreen); } else { xf86DrvMsg(pScreen->myNum, X_WARNING, "[dri] R128DRITransitionTo2d: " - "kernel failed to unflip buffers.\n"); + "kernel failed to unflip buffers.\n"); } info->have3DWindows = 0; diff --git a/src/r128_dri.h b/src/r128_dri.h index 1339a450..c3ab2759 100644 --- a/src/r128_dri.h +++ b/src/r128_dri.h @@ -40,7 +40,6 @@ #define _R128_DRI_ #include "xf86drm.h" -#include "r128_common.h" /* DRI Driver defaults */ #define R128_DEFAULT_CCE_PIO_MODE R128_PM4_64PIO_64VCBM_64INDBM @@ -88,11 +87,11 @@ typedef struct { int log2TexGran; /* MMIO register data */ - drmHandle registerHandle; + drm_handle_t registerHandle; drmSize registerSize; /* CCE AGP Texture data */ - drmHandle agpTexHandle; + drm_handle_t agpTexHandle; drmSize agpTexMapSize; int log2AGPTexGran; int agpTexOffset; diff --git a/src/r128_driver.c b/src/r128_driver.c index d1fbd569..d990610c 100644 --- a/src/r128_driver.c +++ b/src/r128_driver.c @@ -67,6 +67,7 @@ #ifdef XF86DRI #define _XF86DRI_SERVER_ #include "r128_dri.h" +#include "r128_common.h" #include "r128_sarea.h" #endif @@ -296,6 +297,7 @@ static const char *driSymbols[] = { "DRIScreenInit", "DRIUnlock", "GlxSetVisualConfigs", + "DRICreatePCIBusID", NULL }; diff --git a/src/r128_reg.h b/src/r128_reg.h index a0f21cf5..98b89bfa 100644 --- a/src/r128_reg.h +++ b/src/r128_reg.h @@ -1050,33 +1050,31 @@ # define R128_TEX_CACHE_PALLETE_MODE (1 << 11) # define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) # define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12) -# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12) -# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12) +# define R128_ALPHA_COMB_SUB_SRC_DST_NCLAMP (3 << 12) +# define R128_ALPHA_COMB_FCN_MASK (3 << 12) +# define R128_FOG_VERTEX (0 << 14) # define R128_FOG_TABLE (1 << 14) # define R128_SIGNED_DST_CLAMP (1 << 15) -# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16) -# define R128_ALPHA_BLEND_SRC_ONE (1 << 16) -# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16) -# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16) -# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16) -# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16) -# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16) -# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16) -# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16) -# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16) -# define R128_ALPHA_BLEND_SRC_SAT (10 << 16) -# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16) -# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16) -# define R128_ALPHA_BLEND_DST_ZERO (0 << 20) -# define R128_ALPHA_BLEND_DST_ONE (1 << 20) -# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20) -# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20) -# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20) -# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20) -# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20) -# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20) -# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20) -# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20) + +# define R128_ALPHA_BLEND_ZERO (0 ) +# define R128_ALPHA_BLEND_ONE (1 ) +# define R128_ALPHA_BLEND_SRCCOLOR (2 ) +# define R128_ALPHA_BLEND_INVSRCCOLOR (3 ) +# define R128_ALPHA_BLEND_SRCALPHA (4 ) +# define R128_ALPHA_BLEND_INVSRCALPHA (5 ) +# define R128_ALPHA_BLEND_DSTALPHA (6 ) +# define R128_ALPHA_BLEND_INVDSTALPHA (7 ) +# define R128_ALPHA_BLEND_DSTCOLOR (8 ) +# define R128_ALPHA_BLEND_INVDSTCOLOR (9 ) +# define R128_ALPHA_BLEND_SAT (10) /* aka SRCALPHASAT */ +# define R128_ALPHA_BLEND_BLEND (11) /* aka BOTHSRCALPHA */ +# define R128_ALPHA_BLEND_INVBLEND (12) /* aka BOTHINVSRCALPHA */ +# define R128_ALPHA_BLEND_MASK (15) + +# define R128_ALPHA_BLEND_SRC_SHIFT (16) +# define R128_ALPHA_BLEND_DST_SHIFT (20) + # define R128_ALPHA_TEST_NEVER (0 << 24) # define R128_ALPHA_TEST_LESS (1 << 24) # define R128_ALPHA_TEST_LESSEQUAL (2 << 24) @@ -1085,6 +1083,7 @@ # define R128_ALPHA_TEST_GREATER (5 << 24) # define R128_ALPHA_TEST_NEQUAL (6 << 24) # define R128_ALPHA_TEST_ALWAYS (7 << 24) +# define R128_ALPHA_TEST_MASK (7 << 24) # define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28) # define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28) # define R128_COMPOSITE_SHADOW (1 << 29) @@ -1205,47 +1204,11 @@ # define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8) # define R128_MISC_SCALE_PIX_BLEND (0 << 10) # define R128_MISC_SCALE_PIX_REPLICATE (1 << 10) -# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12) -# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12) -# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12) -# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12) -# define R128_FOG_VERTEX (0 << 14) -# define R128_FOG_TABLE (1 << 14) -# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16) -# define R128_ALPHA_BLEND_SRC_ONE (1 << 16) -# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16) -# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16) -# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16) -# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16) -# define R128_ALPHA_BLEND_SRC_DESTALPHA (6 << 16) -# define R128_ALPHA_BLEND_SRC_INVDESTALPHA (7 << 16) -# define R128_ALPHA_BLEND_SRC_DESTCOLOR (8 << 16) -# define R128_ALPHA_BLEND_SRC_INVDESTCOLOR (9 << 16) -# define R128_ALPHA_BLEND_SRC_SRCALPHASAT (10 << 16) -# define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA (11 << 16) -# define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16) -# define R128_ALPHA_BLEND_SRC_MASK (15 << 16) -# define R128_ALPHA_BLEND_DST_ZERO (0 << 20) -# define R128_ALPHA_BLEND_DST_ONE (1 << 20) -# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20) -# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20) -# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20) -# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20) -# define R128_ALPHA_BLEND_DST_DESTALPHA (6 << 20) -# define R128_ALPHA_BLEND_DST_INVDESTALPHA (7 << 20) -# define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20) -# define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20) -# define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20) -# define R128_ALPHA_BLEND_DST_MASK (15 << 20) -# define R128_ALPHA_TEST_NEVER (0 << 24) -# define R128_ALPHA_TEST_LESS (1 << 24) -# define R128_ALPHA_TEST_LESSEQUAL (2 << 24) -# define R128_ALPHA_TEST_EQUAL (3 << 24) -# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24) -# define R128_ALPHA_TEST_GREATER (5 << 24) -# define R128_ALPHA_TEST_NEQUAL (6 << 24) -# define R128_ALPHA_TEST_ALWAYS (7 << 24) -# define R128_ALPHA_TEST_MASK (7 << 24) +/* Bits [14:12] are the same as R128_SCALE_3D_CNTL */ +/* Bit [15] is unknown */ +/* Bits [26:16] are the same as R128_SCALE_3D_CNTL */ +/* Bits [31:27] are unknown */ + #define R128_TEXTURE_CLR_CMP_CLR_C 0x1ca4 #define R128_TEXTURE_CLR_CMP_MSK_C 0x1ca8 #define R128_FOG_COLOR_C 0x1cac diff --git a/src/r128_sarea.h b/src/r128_sarea.h index 6ffdb412..63f432b8 100644 --- a/src/r128_sarea.h +++ b/src/r128_sarea.h @@ -161,7 +161,7 @@ typedef struct { #ifdef XF86DRI /* The current cliprects, or a subset thereof. */ - XF86DRIClipRectRec boxes[R128_NR_SAREA_CLIPRECTS]; + drm_clip_rect_t boxes[R128_NR_SAREA_CLIPRECTS]; unsigned int nbox; #endif diff --git a/src/radeon.h b/src/radeon.h index bff12e46..8b2c8f91 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v 1.40 2003/07/02 17:31:29 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h,v 1.42 2003/10/07 22:47:12 martin Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -66,6 +66,27 @@ #include "picturestr.h" #endif +/* ------- mergedfb support ------------- */ + /* Psuedo Xinerama support */ +#define NEED_REPLIES /* ? */ +#define EXTENSION_PROC_ARGS void * +#include "extnsionst.h" /* required */ +#include "panoramiXproto.h" /* required */ +#define RADEON_XINERAMA_MAJOR_VERSION 1 +#define RADEON_XINERAMA_MINOR_VERSION 1 + + +/* Relative merge position */ +typedef enum { + radeonLeftOf, + radeonRightOf, + radeonAbove, + radeonBelow, + radeonClone +} RADEONScrn2Rel; + +/* ------------------------------------- */ + #define RADEON_DEBUG 0 /* Turn off debugging output */ #define RADEON_IDLE_RETRY 16 /* Fall out of idle loops after this count */ #define RADEON_TIMEOUT 2000000 /* Fall out of wait loops after this count */ @@ -94,20 +115,6 @@ do { \ #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) typedef struct { - /* All values in XCLKS */ - int ML; /* Memory Read Latency */ - int MB; /* Memory Burst Length */ - int Trcd; /* RAS to CAS delay */ - int Trp; /* RAS percentage */ - int Twr; /* Write Recovery */ - int CL; /* CAS Latency */ - int Tr2w; /* Read to Write Delay */ - int Rloop; /* Loop Latency */ - int Rloop_fudge; /* Add to ML to get Rloop */ - char *name; -} RADEONRAMRec, *RADEONRAMPtr; - -typedef struct { /* Common registers */ CARD32 ovr_clr; CARD32 ovr_wid_left_right; @@ -144,6 +151,7 @@ typedef struct { CARD32 crtc_pitch; CARD32 disp_merge_cntl; CARD32 grph_buffer_cntl; + CARD32 crtc_more_cntl; /* CRTC2 registers */ CARD32 crtc2_gen_cntl; @@ -261,10 +269,16 @@ typedef enum { CHIP_FAMILY_RV280, CHIP_FAMILY_R300, CHIP_FAMILY_R350, - CHIP_FAMILY_RV350 + CHIP_FAMILY_RV350, + CHIP_FAMILY_LAST } RADEONChipFamily; typedef struct { + CARD32 freq; + CARD32 value; +}RADEONTMDSPll; + +typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; PCITAG PciTag; @@ -295,13 +309,6 @@ typedef struct { Bool IsIGP; /* IGP chips */ Bool IsSecondary; /* Second Screen */ Bool IsSwitching; /* Flag for switching mode */ - Bool Clone; /* Force second head to clone primary*/ - RADEONMonitorType CloneType; - RADEONDDCType CloneDDCType; - DisplayModePtr CloneModes; - DisplayModePtr CurCloneMode; - int CloneFrameX0; - int CloneFrameY0; Bool OverlayOnCRTC2; Bool PanelOff; /* Force panel (LCD/DFP) off */ int FPBIOSstart; /* Start of the flat panel info */ @@ -325,7 +332,6 @@ typedef struct { int FeedbackDivider; int PostDivider; Bool UseBiosDividers; - /* EDID data using DDC interface */ Bool ddc_bios; Bool ddc1; @@ -334,7 +340,12 @@ typedef struct { CARD32 DDCReg; RADEONPLLRec pll; - RADEONRAMPtr ram; + RADEONTMDSPll tmds_pll[4]; + int RamWidth; + float sclk; /* in MHz */ + float mclk; /* in MHz */ + Bool IsDDR; + int DispPriority; RADEONSaveRec SavedReg; /* Original (text) mode */ RADEONSaveRec ModeReg; /* Current mode */ @@ -415,14 +426,14 @@ typedef struct { __GLXvisualConfig *pVisualConfigs; RADEONConfigPrivPtr pVisualConfigsPriv; - drmHandle fbHandle; + drm_handle_t fbHandle; drmSize registerSize; - drmHandle registerHandle; + drm_handle_t registerHandle; Bool IsPCI; /* Current card is a PCI card */ drmSize pciSize; - drmHandle pciMemHandle; + drm_handle_t pciMemHandle; unsigned char *PCI; /* Map */ Bool depthMoves; /* Enable depth moves -- slow! */ @@ -431,7 +442,7 @@ typedef struct { int drmMinor; drmSize gartSize; - drmHandle agpMemHandle; /* Handle from drmAgpAlloc */ + drm_handle_t agpMemHandle; /* Handle from drmAgpAlloc */ unsigned long gartOffset; unsigned char *AGP; /* Map */ int agpMode; @@ -448,20 +459,20 @@ typedef struct { /* CP ring buffer data */ unsigned long ringStart; /* Offset into GART space */ - drmHandle ringHandle; /* Handle from drmAddMap */ + drm_handle_t ringHandle; /* Handle from drmAddMap */ drmSize ringMapSize; /* Size of map */ int ringSize; /* Size of ring (in MB) */ unsigned char *ring; /* Map */ int ringSizeLog2QW; unsigned long ringReadOffset; /* Offset into GART space */ - drmHandle ringReadPtrHandle; /* Handle from drmAddMap */ + drm_handle_t ringReadPtrHandle; /* Handle from drmAddMap */ drmSize ringReadMapSize; /* Size of map */ unsigned char *ringReadPtr; /* Map */ /* CP vertex/indirect buffer data */ unsigned long bufStart; /* Offset into GART space */ - drmHandle bufHandle; /* Handle from drmAddMap */ + drm_handle_t bufHandle; /* Handle from drmAddMap */ drmSize bufMapSize; /* Size of map */ int bufSize; /* Size of buffers (in MB) */ unsigned char *buf; /* Map */ @@ -470,7 +481,7 @@ typedef struct { /* CP GART Texture data */ unsigned long gartTexStart; /* Offset into GART space */ - drmHandle gartTexHandle; /* Handle from drmAddMap */ + drm_handle_t gartTexHandle; /* Handle from drmAddMap */ drmSize gartTexMapSize; /* Size of map */ int gartTexSize; /* Size of GART tex space (in MB) */ unsigned char *gartTex; /* Map */ @@ -488,6 +499,7 @@ typedef struct { int depthX; int depthY; + unsigned int fbLocation; int frontOffset; int frontPitch; int backOffset; @@ -540,8 +552,38 @@ typedef struct { #ifdef XFree86LOADER XF86ModReqInfo xaaReq; #endif + + /* merged fb stuff, also covers clone modes */ + Bool MergedFB; + RADEONScrn2Rel CRT2Position; + char * CRT2HSync; + char * CRT2VRefresh; + char * MetaModes; + ScrnInfoPtr CRT2pScrn; + DisplayModePtr CRT1Modes; + DisplayModePtr CRT1CurrentMode; + int CRT1frameX0; + int CRT1frameY0; + int CRT1frameX1; + int CRT1frameY1; + RADEONMonitorType MergeType; + RADEONDDCType MergeDDCType; + void (*PointerMoved)(int index, int x, int y); + /* pseudo xinerama support for mergedfb */ + int maxCRT1_X1, maxCRT1_X2, maxCRT1_Y1, maxCRT1_Y2; + int maxCRT2_X1, maxCRT2_X2, maxCRT2_Y1, maxCRT2_Y2; + int maxClone_X1, maxClone_X2, maxClone_Y1, maxClone_Y2; + Bool UseRADEONXinerama; + Bool CRT2IsScrn0; + ExtensionEntry *XineramaExtEntry; + int RADEONXineramaVX, RADEONXineramaVY; + Bool AtLeastOneNonClone; + int MergedFBXDPI, MergedFBYDPI; + Bool NoVirtual; + } RADEONInfoRec, *RADEONInfoPtr; + #define RADEONWaitForFifo(pScrn, entries) \ do { \ if (info->fifo_slots < entries) \ @@ -569,6 +611,7 @@ extern void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn); extern void RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer); extern Bool RADEONAccelInit(ScreenPtr pScreen); +extern void RADEONAccelInitMMIO(ScreenPtr pScreen, XAAInfoRecPtr a); extern void RADEONEngineInit(ScrnInfoPtr pScrn); extern Bool RADEONCursorInit(ScreenPtr pScreen); extern Bool RADEONDGAInit(ScreenPtr pScreen); @@ -580,6 +623,7 @@ extern void RADEONResetVideo(ScrnInfoPtr pScrn); extern void R300CGWorkaround(ScrnInfoPtr pScrn); #ifdef XF86DRI +extern void RADEONAccelInitCP(ScreenPtr pScreen, XAAInfoRecPtr a); extern Bool RADEONDRIScreenInit(ScreenPtr pScreen); extern void RADEONDRICloseScreen(ScreenPtr pScreen); extern void RADEONDRIResume(ScreenPtr pScreen); diff --git a/src/radeon_accel.c b/src/radeon_accel.c index 8556cc25..0fabcbee 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -79,6 +79,7 @@ #ifdef XF86DRI #define _XF86DRI_SERVER_ #include "radeon_dri.h" +#include "radeon_common.h" #include "radeon_sarea.h" #endif @@ -283,8 +284,8 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; RADEONWaitForFifo(pScrn, 1); - OUTREG(RADEON_DEFAULT_OFFSET, ((INREG(RADEON_DISPLAY_BASE_ADDR) >> 10) - | (pitch64 << 22))); + OUTREG(RADEON_DEFAULT_OFFSET, ((info->fbLocation >> 10) + | (pitch64 << 22))); RADEONWaitForFifo(pScrn, 1); #if X_BYTE_ORDER == X_BIG_ENDIAN @@ -329,15 +330,6 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) info->CurrentLayout.bitsPerPixel)); OUTREG(RADEON_RB3D_CNTL, 0); -#if defined(__powerpc__) -#if defined(XF86_DRI) - if(!info->directRenderingEnabled) -#endif - { - OUTREG(RADEON_MC_FB_LOCATION, 0xffff0000); - OUTREG(RADEON_MC_AGP_LOCATION, 0xfffff000); - } -#endif RADEONEngineReset(pScrn); diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c index 843fd6bb..2dbd6b23 100644 --- a/src/radeon_accelfuncs.c +++ b/src/radeon_accelfuncs.c @@ -181,8 +181,8 @@ FUNC_NAME(RADEONRestoreAccelState)(ScrnInfoPtr pScrn) pitch64 = ((pScrn->displayWidth * (pScrn->bitsPerPixel / 8) + 0x3f)) >> 6; - OUTREG(RADEON_DEFAULT_OFFSET, (((INREG(RADEON_DISPLAY_BASE_ADDR) + pScrn->fbOffset) >> 10) | - (pitch64 << 22))); + OUTREG(RADEON_DEFAULT_OFFSET, ((info->fbLocation + pScrn->fbOffset) >> 10) + | (pitch64 << 22)); /* FIXME: May need to restore other things, like BKGD_CLK FG_CLK... */ @@ -1169,7 +1169,7 @@ RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer) } #endif -static void +void FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1224,9 +1224,10 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) | LEFT_EDGE_CLIPPING_NEGATIVE_X); a->NumScanlineColorExpandBuffers = 1; a->ScanlineColorExpandBuffers = info->scratch_buffer; - info->scratch_save - = xalloc(((pScrn->virtualX+31)/32*4) - + (pScrn->virtualX * info->CurrentLayout.pixel_bytes)); + if (!info->scratch_save) + info->scratch_save + = xalloc(((pScrn->virtualX+31)/32*4) + + (pScrn->virtualX * info->CurrentLayout.pixel_bytes)); info->scratch_buffer[0] = info->scratch_save; a->SetupForScanlineCPUToScreenColorExpandFill = FUNC_NAME(RADEONSetupForScanlineCPUToScreenColorExpandFill); diff --git a/src/radeon_common.h b/src/radeon_common.h index 31e2a0b7..bf118639 100644 --- a/src/radeon_common.h +++ b/src/radeon_common.h @@ -38,6 +38,7 @@ #ifndef _RADEON_COMMON_H_ #define _RADEON_COMMON_H_ +#include <inttypes.h> #include "xf86drm.h" /* WARNING: If you change any of these defines, make sure to change @@ -71,6 +72,7 @@ #define DRM_RADEON_IRQ_EMIT 0x16 #define DRM_RADEON_IRQ_WAIT 0x17 #define DRM_RADEON_CP_RESUME 0x18 +#define DRM_RADEON_SETPARAM 0x19 #define DRM_RADEON_MAX_DRM_COMMAND_INDEX 0x39 @@ -159,7 +161,7 @@ typedef struct { } drmRadeonTexImage; typedef struct { - int offset; + unsigned int offset; int pitch; int format; int width; /* Texture image coordinates */ @@ -275,7 +277,7 @@ typedef struct { int bufsz; char *buf; int nbox; - drmClipRect *boxes; + drm_clip_rect_t *boxes; } drmRadeonCmdBuffer; /* New style per-packet identifiers for use in cmd_buffer ioctl with @@ -358,7 +360,8 @@ typedef struct { #define RADEON_EMIT_PP_TEX_SIZE_0 73 #define RADEON_EMIT_PP_TEX_SIZE_1 74 #define RADEON_EMIT_PP_TEX_SIZE_2 75 -#define RADEON_MAX_STATE_PACKETS 76 +#define R200_EMIT_RB3D_BLENDCOLOR 76 +#define RADEON_MAX_STATE_PACKETS 77 /* Commands understood by cmd_buffer ioctl. More can be added but @@ -400,18 +403,28 @@ typedef union { #define RADEON_WAIT_3D 0x2 +/* 1.3: An ioctl to get parameters that aren't available to the 3d + * client any other way. + */ +#define RADEON_PARAM_GART_BUFFER_OFFSET 1 /* card offset of 1st GART buffer */ +#define RADEON_PARAM_LAST_FRAME 2 +#define RADEON_PARAM_LAST_DISPATCH 3 +#define RADEON_PARAM_LAST_CLEAR 4 +/* Added with DRM version 1.6. */ +#define RADEON_PARAM_IRQ_NR 5 +#define RADEON_PARAM_GART_BASE 6 /* card offset of GART base */ +/* Added with DRM version 1.8. */ +#define RADEON_PARAM_REGISTER_HANDLE 7 /* for drmMap() */ +#define RADEON_PARAM_STATUS_HANDLE 8 +#define RADEON_PARAM_SAREA_HANDLE 9 +#define RADEON_PARAM_GART_TEX_HANDLE 10 +#define RADEON_PARAM_SCRATCH_OFFSET 11 + typedef struct drm_radeon_getparam { int param; int *value; } drmRadeonGetParam; -#define RADEON_PARAM_GART_BUFFER_OFFSET 1 -#define RADEON_PARAM_LAST_FRAME 2 -#define RADEON_PARAM_LAST_DISPATCH 3 -#define RADEON_PARAM_LAST_CLEAR 4 -#define RADEON_PARAM_IRQ_NR 5 -#define RADEON_PARAM_GART_BASE 6 - #define RADEON_MEM_REGION_GART 1 #define RADEON_MEM_REGION_FB 2 @@ -445,4 +458,16 @@ typedef struct drm_radeon_irq_wait { } drmRadeonIrqWait; +/* 1.10: Clients tell the DRM where they think the framebuffer is located in + * the card's address space, via a new generic ioctl to set parameters + */ + +typedef struct drm_radeon_set_param { + unsigned int param; + int64_t value; +} drmRadeonSetParam; + +#define RADEON_SETPARAM_FB_LOCATION 1 + + #endif diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c index ff15cefa..fe0d12bd 100644 --- a/src/radeon_cursor.c +++ b/src/radeon_cursor.c @@ -48,6 +48,7 @@ #include "radeon.h" #include "radeon_macros.h" #include "radeon_reg.h" +#include "radeon_mergedfb.h" /* X and server generic header files */ #include "xf86.h" @@ -89,6 +90,7 @@ static CARD32 mono_cursor_color[] = { #endif + /* Set cursor foreground and background colors */ static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { @@ -138,10 +140,13 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) int xorigin = 0; int yorigin = 0; int total_y = pScrn->frameY1 - pScrn->frameY0; - int X2 = pScrn->frameX0 + x; - int Y2 = pScrn->frameY0 + y; int stride = 256; + if(info->MergedFB) { + RADEONSetCursorPositionMerged(pScrn, x, y); + return; + } + if (x < 0) xorigin = -x+1; if (y < 0) yorigin = -y+1; if (y > total_y) y = total_y; @@ -149,57 +154,6 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - if (info->Clone) { - int X0 = 0; - int Y0 = 0; - - if ((info->CurCloneMode->VDisplay == pScrn->currentMode->VDisplay) && - (info->CurCloneMode->HDisplay == pScrn->currentMode->HDisplay)) { - Y2 = y; - X2 = x; - X0 = pScrn->frameX0; - Y0 = pScrn->frameY0; - } else { - if (y < 0) - Y2 = pScrn->frameY0; - - if (x < 0) - X2 = pScrn->frameX0; - - if (Y2 >= info->CurCloneMode->VDisplay + info->CloneFrameY0) { - Y0 = Y2 - info->CurCloneMode->VDisplay; - Y2 = info->CurCloneMode->VDisplay - 1; - } else if (Y2 < info->CloneFrameY0) { - Y0 = Y2; - Y2 = 0; - } else { - Y2 -= info->CloneFrameY0; - Y0 = info->CloneFrameY0; - } - - if (X2 >= info->CurCloneMode->HDisplay + info->CloneFrameX0) { - X0 = X2 - info->CurCloneMode->HDisplay; - X2 = info->CurCloneMode->HDisplay - 1; - } else if (X2 < info->CloneFrameX0) { - X0 = X2; - X2 = 0; - } else { - X2 -= info->CloneFrameX0; - X0 = info->CloneFrameX0; - } - - if (info->CurCloneMode->Flags & V_DBLSCAN) - Y2 *= 2; - } - - if ((X0 >= 0 || Y0 >= 0) && - ((info->CloneFrameX0 != X0) || (info->CloneFrameY0 != Y0))) { - RADEONDoAdjustFrame(pScrn, X0, Y0, TRUE); - info->CloneFrameX0 = X0; - info->CloneFrameY0 = Y0; - } - } - if (!info->IsSecondary) { OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK | (xorigin << 16) @@ -219,23 +173,6 @@ static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) info->cursor_start + pScrn->fbOffset + yorigin * stride); } - if (info->Clone) { - xorigin = 0; - yorigin = 0; - if (X2 < 0) xorigin = -X2 + 1; - if (Y2 < 0) yorigin = -Y2 + 1; - if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; - if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; - - OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK - | (xorigin << 16) - | yorigin)); - OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK - | ((xorigin ? 0 : X2) << 16) - | (yorigin ? 0 : Y2))); - OUTREG(RADEON_CUR2_OFFSET, - info->cursor_start + pScrn->fbOffset + yorigin * stride); - } } /* Copy cursor image from `image' to video memory. RADEONSetCursorPosition @@ -259,7 +196,7 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); } - if (info->IsSecondary || info->Clone) { + if (info->IsSecondary || info->MergedFB) { save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); save2 |= (CARD32) (2 << 20); OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); @@ -292,7 +229,7 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) if (!info->IsSecondary) OUTREG(RADEON_CRTC_GEN_CNTL, save1); - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREG(RADEON_CRTC2_GEN_CNTL, save2); } @@ -303,7 +240,7 @@ static void RADEONHideCursor(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); if (!info->IsSecondary) @@ -316,7 +253,7 @@ static void RADEONShowCursor(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, ~RADEON_CRTC2_CUR_EN); @@ -369,7 +306,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); } - if (info->IsSecondary || info->Clone) { + if (info->IsSecondary || info->MergedFB) { save2 = INREG(RADEON_CRTC2_GEN_CNTL) & ~(CARD32) (3 << 20); save2 |= (CARD32) (2 << 20); OUTREG(RADEON_CRTC2_GEN_CNTL, save2 & (CARD32)~RADEON_CRTC2_CUR_EN); @@ -407,7 +344,7 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) if (!info->IsSecondary) OUTREG(RADEON_CRTC_GEN_CNTL, save1); - if (info->IsSecondary || info->Clone) + if (info->IsSecondary || info->MergedFB) OUTREG(RADEON_CRTC2_GEN_CNTL, save2); } diff --git a/src/radeon_dri.c b/src/radeon_dri.c index 2d36f872..f0af0949 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -40,12 +40,12 @@ #include "radeon.h" #include "radeon_macros.h" #include "radeon_dri.h" -#include "radeon_pci.h" #include "radeon_reg.h" #include "radeon_version.h" /* X and server generic header files */ #include "xf86.h" +#include "xf86PciInfo.h" #include "windowstr.h" @@ -172,7 +172,7 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) pConfigs[i].stencilSize = 0; pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; - if (accum) { + if (accum || stencil) { pConfigs[i].visualRating = GLX_SLOW_CONFIG; } else { pConfigs[i].visualRating = GLX_NONE; @@ -284,7 +284,7 @@ static Bool RADEONInitVisualConfigs(ScreenPtr pScreen) /* Create the Radeon-specific context information */ static Bool RADEONCreateContext(ScreenPtr pScreen, VisualPtr visual, - drmContext hwContext, void *pVisualConfigPriv, + drm_context_t hwContext, void *pVisualConfigPriv, DRIContextType contextStore) { #ifdef PER_CONTEXT_SAREA @@ -321,7 +321,7 @@ static Bool RADEONCreateContext(ScreenPtr pScreen, VisualPtr visual, } /* Destroy the Radeon-specific context information */ -static void RADEONDestroyContext(ScreenPtr pScreen, drmContext hwContext, +static void RADEONDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, DRIContextType contextStore) { #ifdef PER_CONTEXT_SAREA @@ -1024,12 +1024,10 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) memset(&drmInfo, 0, sizeof(drmRadeonInit)); - if ((info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280) ) - drmInfo.func = DRM_RADEON_INIT_R200_CP; + if ( info->ChipFamily >= CHIP_FAMILY_R200 ) + drmInfo.func = DRM_RADEON_INIT_R200_CP; else - drmInfo.func = DRM_RADEON_INIT_CP; + drmInfo.func = DRM_RADEON_INIT_CP; drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec); drmInfo.is_pci = info->IsPCI; @@ -1235,19 +1233,21 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) info->pDRIInfo = pDRIInfo; pDRIInfo->drmDriverName = RADEON_DRIVER_NAME; - if ( (info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280) ) - pDRIInfo->clientDriverName = R200_DRIVER_NAME; - else - pDRIInfo->clientDriverName = RADEON_DRIVER_NAME; - - pDRIInfo->busIdString = xalloc(64); - sprintf(pDRIInfo->busIdString, - "PCI:%d:%d:%d", - info->PciInfo->bus, - info->PciInfo->device, - info->PciInfo->func); + if ( info->ChipFamily >= CHIP_FAMILY_R200 ) + pDRIInfo->clientDriverName = R200_DRIVER_NAME; + else + pDRIInfo->clientDriverName = RADEON_DRIVER_NAME; + + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, + "PCI:%d:%d:%d", + info->PciInfo->bus, + info->PciInfo->device, + info->PciInfo->func); + } pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR; pDRIInfo->ddxDriverMinorVersion = RADEON_VERSION_MINOR; pDRIInfo->ddxDriverPatchVersion = RADEON_VERSION_PATCH; @@ -1362,9 +1362,10 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) if (version) { int req_minor, req_patch; - if ((info->ChipFamily == CHIP_FAMILY_R200) || - (info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (info->IsIGP) { + req_minor = 10; + req_patch = 0; + } else if (info->ChipFamily >= CHIP_FAMILY_R200) { req_minor = 5; req_patch = 0; } else { @@ -1414,23 +1415,19 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) /* Initialize AGP */ if (!info->IsPCI && !RADEONDRIAgpInit(info, pScreen)) { -#if defined(__alpha__) || defined(__powerpc__) - info->IsPCI = TRUE; - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[agp] AGP failed to initialize " - "-- falling back to PCI mode.\n"); - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[agp] If this is an AGP card, you may want to make sure " - "the agpgart\nkernel module is loaded before the radeon " - "kernel module.\n"); -#else + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] AGP failed to initialize. Disabling the DRI.\n" ); + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] You may want to make sure the agpgart kernel " + "module\nis loaded before the radeon kernel module.\n"); RADEONDRICloseScreen(pScreen); return FALSE; -#endif } /* Initialize PCI */ if (info->IsPCI && !RADEONDRIPciInit(info, pScreen)) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[pci] PCI failed to initialize. Disabling the DRI.\n" ); RADEONDRICloseScreen(pScreen); return FALSE; } @@ -1890,6 +1887,10 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + /* Try flipping back to the front page if necessary */ + if (pSAREAPriv->pfCurrentPage == 1) + drmCommandNone(info->drmFD, DRM_RADEON_FLIP); + /* Shut down shadowing if we've made it back to the front page */ if (pSAREAPriv->pfCurrentPage == 0) { RADEONDisablePageFlip(pScreen); @@ -1898,10 +1899,10 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) } else { xf86DrvMsg(pScreen->myNum, X_WARNING, "[dri] RADEONDRITransitionTo2d: " - "kernel failed to unflip buffers.\n"); + "kernel failed to unflip buffers.\n"); } - xf86FreeOffscreenArea(info->depthTexArea); + xf86FreeOffscreenArea(info->depthTexArea); info->have3DWindows = 0; diff --git a/src/radeon_dri.h b/src/radeon_dri.h index 3f467190..4453fe6f 100644 --- a/src/radeon_dri.h +++ b/src/radeon_dri.h @@ -38,12 +38,14 @@ #define _RADEON_DRI_ #include "xf86drm.h" -#include "radeon_common.h" /* DRI Driver defaults */ #define RADEON_DEFAULT_CP_PIO_MODE RADEON_CSQ_PRIPIO_INDPIO #define RADEON_DEFAULT_CP_BM_MODE RADEON_CSQ_PRIBM_INDBM -#define RADEON_DEFAULT_AGP_MODE 1 +/* Default to AGP 4x mode for IGP chips, there are some problems with 1x and 2x + * modes on AGP master side + */ +#define RADEON_DEFAULT_AGP_MODE (info->IsIGP ? 4 : 1) #define RADEON_DEFAULT_AGP_FAST_WRITE 0 #define RADEON_DEFAULT_GART_SIZE 8 /* MB (must be 2^n and > 4MB) */ #define RADEON_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */ @@ -85,15 +87,15 @@ typedef struct { int log2TexGran; /* MMIO register data */ - drmHandle registerHandle; + drm_handle_t registerHandle; drmSize registerSize; /* CP in-memory status information */ - drmHandle statusHandle; + drm_handle_t statusHandle; drmSize statusSize; /* CP GART Texture data */ - drmHandle gartTexHandle; + drm_handle_t gartTexHandle; drmSize gartTexMapSize; int log2GARTTexGran; int gartTexOffset; diff --git a/src/radeon_dripriv.h b/src/radeon_dripriv.h index 5f011928..59f54589 100644 --- a/src/radeon_dripriv.h +++ b/src/radeon_dripriv.h @@ -53,8 +53,8 @@ typedef struct { typedef struct { #ifdef PER_CONTEXT_SAREA - drmContext ctx_id; - drmHandle sarea_handle; + drm_context_t ctx_id; + drm_handle_t sarea_handle; #else /* Nothing here yet */ int dummy; diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 4f568275..bfc50c43 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -56,15 +56,19 @@ * overlay planes * * Modified by Marc Aurele La France (tsi@xfree86.org) for ATI driver merge. + * + * Mergedfb and pseudo xinerama support added by Alex Deucher (agd5f@yahoo.com) + * based on the sis driver by Thomas Winischhofer. + * */ /* Driver data structures */ #include "radeon.h" #include "radeon_macros.h" -#include "radeon_pci.h" #include "radeon_probe.h" #include "radeon_reg.h" #include "radeon_version.h" +#include "radeon_mergedfb.h" #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -81,6 +85,7 @@ /* X and server generic header files */ #include "xf86.h" #include "xf86_OSproc.h" +#include "xf86PciInfo.h" #include "xf86RAC.h" #include "xf86Resources.h" #include "xf86cmap.h" @@ -93,6 +98,9 @@ #ifndef MAX #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#ifndef MIN +#define MIN(a,b) ((a)>(b)?(b):(a)) +#endif /* Forward definitions for driver functions */ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); @@ -103,6 +111,14 @@ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); +static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); + +static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn); +static int RADEONValidateMergeModes(ScrnInfoPtr pScrn); + +/* psuedo xinerama support */ + +extern Bool RADEONnoPanoramiXExtension; typedef enum { OPTION_NOACCEL, @@ -110,12 +126,13 @@ typedef enum { OPTION_DAC_6BIT, OPTION_DAC_8BIT, #ifdef XF86DRI - OPTION_IS_PCI, + OPTION_BUS_TYPE, OPTION_CP_PIO, OPTION_USEC_TIMEOUT, OPTION_AGP_MODE, OPTION_AGP_FW, OPTION_GART_SIZE, + OPTION_GART_SIZE_OLD, OPTION_RING_SIZE, OPTION_BUFFER_SIZE, OPTION_DEPTH_MOVE, @@ -126,12 +143,18 @@ typedef enum { OPTION_DDC_MODE, OPTION_MONITOR_LAYOUT, OPTION_IGNORE_EDID, - OPTION_CRTC2_OVERLAY, - OPTION_CLONE_MODE, - OPTION_CLONE_HSYNC, - OPTION_CLONE_VREFRESH, OPTION_FBDEV, - OPTION_VIDEO_KEY + OPTION_VIDEO_KEY, + OPTION_MERGEDFB, + OPTION_CRT2HSYNC, + OPTION_CRT2VREFRESH, + OPTION_CRT2POS, + OPTION_METAMODES, + OPTION_MERGEDDPI, + OPTION_NORADEONXINERAMA, + OPTION_CRT2ISSCRN0, + OPTION_DISP_PRIORITY, + OPTION_PANEL_SIZE } RADEONOpts; const OptionInfoRec RADEONOptions[] = { @@ -140,11 +163,12 @@ const OptionInfoRec RADEONOptions[] = { { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DAC_8BIT, "Dac8Bit", OPTV_BOOLEAN, {0}, TRUE }, #ifdef XF86DRI - { OPTION_IS_PCI, "ForcePCIMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_BUS_TYPE, "BusType", OPTV_ANYSTR, {0}, FALSE }, { OPTION_CP_PIO, "CPPIOMode", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USEC_TIMEOUT, "CPusecTimeout", OPTV_INTEGER, {0}, FALSE }, { OPTION_AGP_MODE, "AGPMode", OPTV_INTEGER, {0}, FALSE }, { OPTION_AGP_FW, "AGPFastWrite", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_GART_SIZE_OLD, "AGPSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_GART_SIZE, "GARTSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_RING_SIZE, "RingSize", OPTV_INTEGER, {0}, FALSE }, { OPTION_BUFFER_SIZE, "BufferSize", OPTV_INTEGER, {0}, FALSE }, @@ -156,21 +180,21 @@ const OptionInfoRec RADEONOptions[] = { { OPTION_DDC_MODE, "DDCMode", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR, {0}, FALSE }, { OPTION_IGNORE_EDID, "IgnoreEDID", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CRTC2_OVERLAY , "OverlayOnCRTC2", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CLONE_MODE, "CloneMode", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CLONE_HSYNC, "CloneHSync", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_CLONE_VREFRESH, "CloneVRefresh", OPTV_ANYSTR, {0}, FALSE }, { OPTION_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_MERGEDFB, "MergedFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRT2HSYNC, "CRT2HSync", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_CRT2VREFRESH, "CRT2VRefresh", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_CRT2POS, "CRT2Position", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_METAMODES, "MetaModes", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_MERGEDDPI, "MergedDPI", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_NORADEONXINERAMA, "NoMergedXinerama", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRT2ISSCRN0, "MergedXineramaCRT2IsScreen0", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_DISP_PRIORITY, "DisplayPriority", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; -RADEONRAMRec RADEONRAM[] = { /* Memory Specifications - From Radeon Manual */ - { 4, 4, 1, 2, 1, 2, 1, 16, 12, "64-bit SDR SDRAM" }, - { 4, 4, 3, 3, 2, 3, 1, 16, 12, "64-bit DDR SDRAM" }, -}; - static const char *vgahwSymbols[] = { "vgaHWFreeHWRec", "vgaHWGetHWRec", @@ -302,6 +326,7 @@ static const char *driSymbols[] = { "DRIScreenInit", "DRIUnlock", "GlxSetVisualConfigs", + "DRICreatePCIBusID", NULL }; @@ -381,6 +406,24 @@ static struct {720, 400, 70}, }; +static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = +{ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ + {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x400f7/*0x40111*/}, {0, 0}}, /*CHIP_FAMILY_RV280*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ +}; + extern int gRADEONEntityIndex; struct RADEONInt10Save { @@ -448,15 +491,15 @@ RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr) (((CardTmp >> 8) & 0xff) != ((CardTmp >> 24) & 0xff)))) { /* Restore the saved registers */ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Restoring MEM_CNTL (%08x), setting to %08x\n", - CardTmp, pSave->MEM_CNTL); + "Restoring MEM_CNTL (%08lx), setting to %08lx\n", + (unsigned long)CardTmp, (unsigned long)pSave->MEM_CNTL); OUTREG(RADEON_MEM_CNTL, pSave->MEM_CNTL); CardTmp = INREG(RADEON_CONFIG_MEMSIZE); if (CardTmp != pSave->MEMSIZE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Restoring CONFIG_MEMSIZE (%08x), setting to %08x\n", - CardTmp, pSave->MEMSIZE); + "Restoring CONFIG_MEMSIZE (%08lx), setting to %08lx\n", + (unsigned long)CardTmp, (unsigned long)pSave->MEMSIZE); OUTREG(RADEON_CONFIG_MEMSIZE, pSave->MEMSIZE); } } @@ -464,8 +507,9 @@ RADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr) CardTmp = INREG(RADEON_MPP_TB_CONFIG); if ((CardTmp & 0xff000000u) != (pSave->MPP_TB_CONFIG & 0xff000000u)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Restoring MPP_TB_CONFIG<31:24> (%02x), setting to %02x\n", - CardTmp >> 24, pSave->MPP_TB_CONFIG >> 24); + "Restoring MPP_TB_CONFIG<31:24> (%02lx), setting to %02lx\n", + (unsigned long)CardTmp >> 24, + (unsigned long)pSave->MPP_TB_CONFIG >> 24); CardTmp &= 0x00ffffffu; CardTmp |= (pSave->MPP_TB_CONFIG & 0xff000000u); OUTREG(RADEON_MPP_TB_CONFIG, CardTmp); @@ -484,6 +528,48 @@ static Bool RADEONGetRec(ScrnInfoPtr pScrn) /* Free our private RADEONInfoRec */ static void RADEONFreeRec(ScrnInfoPtr pScrn) { + RADEONInfoPtr info = RADEONPTR(pScrn); + if(info->CRT2HSync) xfree(info->CRT2HSync); + info->CRT2HSync = NULL; + if(info->CRT2VRefresh) xfree(info->CRT2VRefresh); + info->CRT2VRefresh = NULL; + if(info->MetaModes) xfree(info->MetaModes); + info->MetaModes = NULL; + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + } + if(info->CRT1Modes) { + if(info->CRT1Modes != pScrn->modes) { + if(pScrn->modes) { + pScrn->currentMode = pScrn->modes; + do { + DisplayModePtr p = pScrn->currentMode->next; + if(pScrn->currentMode->Private) + xfree(pScrn->currentMode->Private); + xfree(pScrn->currentMode); + pScrn->currentMode = p; + } while(pScrn->currentMode != pScrn->modes); + } + pScrn->currentMode = info->CRT1CurrentMode; + pScrn->modes = info->CRT1Modes; + info->CRT1CurrentMode = NULL; + info->CRT1Modes = NULL; + } + } + if (!pScrn || !pScrn->driverPrivate) return; xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; @@ -673,7 +759,7 @@ static void RADEONBlank(ScrnInfoPtr pScrn) default: break; } - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS, ~(RADEON_CRTC2_DISP_DIS)); @@ -704,7 +790,7 @@ static void RADEONUnblank(ScrnInfoPtr pScrn) default: break; } - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~(RADEON_CRTC2_DISP_DIS)); @@ -785,7 +871,7 @@ static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCT OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 3; i++) { + for (i = 0; i < 10; i++) { usleep(15000); if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) break; @@ -1301,19 +1387,6 @@ static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn, xf86Int10InfoPtr pIn if (!pRADEONEnt->MonType2) pRADEONEnt->MonType2 = RADEONCrtIsPhysicallyConnected(pScrn, !pRADEONEnt->ReversedDAC); - /* no display detected on DVI port*/ - if (pRADEONEnt->MonType1 == MT_NONE) { - if (pRADEONEnt->MonType2 != MT_NONE) { - /* Only one detected on VGA, let it to be primary */ - pRADEONEnt->MonType1 = pRADEONEnt->MonType2; - pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; - pRADEONEnt->MonType2 = MT_NONE; - } else { - /* Non detected, Default to a CRT connected */ - pRADEONEnt->MonType1 = MT_CRT; - } - } - if(pRADEONEnt->ReversedTMDS) { /* always keep internal TMDS as primary head */ if (pRADEONEnt->MonType1 == MT_DFP || @@ -1330,6 +1403,20 @@ static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn, xf86Int10InfoPtr pIn } } } + + /* no display detected on DVI port*/ + if (pRADEONEnt->MonType1 == MT_NONE) { + if (pRADEONEnt->MonType2 != MT_NONE) { + /* Only one detected on VGA, let it to be primary */ + pRADEONEnt->MonType1 = pRADEONEnt->MonType2; + pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2; + pRADEONEnt->MonType2 = MT_NONE; + pRADEONEnt->MonInfo2 = NULL; + } else { + /* Non detected, Default to a CRT connected */ + pRADEONEnt->MonType1 = MT_CRT; + } + } } if(s) { @@ -1363,9 +1450,6 @@ static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn, xf86Int10InfoPtr pIn xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); info->OverlayOnCRTC2 = FALSE; - if (xf86ReturnOptValBool(info->Options, OPTION_CRTC2_OVERLAY, FALSE)) { - info->OverlayOnCRTC2 = TRUE; - } if (pRADEONEnt->MonType2 == MT_NONE) pRADEONEnt->HasSecondary = FALSE; @@ -1421,8 +1505,8 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONMMIO = info->MMIO; - info->Clone = FALSE; - info->CloneType = MT_NONE; + /* info->MergedFB = FALSE; */ + info->MergeType = MT_NONE; if(info->HasCRTC2) { if(info->IsSecondary) { @@ -1431,8 +1515,9 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->DisplayType = pRADEONEnt->MonType1; if(!pRADEONEnt->HasSecondary) { - if ((info->CloneType = pRADEONEnt->MonType2)) - info->Clone = TRUE; + if ((info->MergeType = pRADEONEnt->MonType2)) { + /* info->MergedFB = TRUE; */ + } } } } else { @@ -1443,9 +1528,9 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) (info->IsSecondary ? "Secondary" : "Primary"), info->DisplayType); - if (info->Clone) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone Display == Type %d\n", - info->CloneType); + if (info->MergedFB) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Secondary Display == Type %d\n", + info->MergeType); info->HBlank = 0; info->HOverPlus = 0; @@ -1456,7 +1541,8 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->DotClock = 0; info->UseBiosDividers = FALSE; - if (info->DisplayType == MT_LCD && info->VBIOS) { + if (info->DisplayType == MT_LCD && info->VBIOS && + !(xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { tmp = RADEON_BIOS16(info->FPBIOSstart + 0x40); if (!tmp) { info->PanelPwrDly = 200; @@ -1491,10 +1577,14 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) (info->FeedbackDivider > 3)) { info->UseBiosDividers = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS provided dividers will be used."); + "BIOS provided dividers will be used.\n"); } - for (i = 0; i < 20; i++) { + /* We don't use a while loop here just in case we have a corrupted BIOS image. + The max number of table entries is 23 at present, but may grow in future. + To ensure it works with future revisions we loop it to 32. + */ + for (i = 0; i < 32; i++) { tmp0 = RADEON_BIOS16(tmp+64+i*2); if (tmp0 == 0) break; if ((RADEON_BIOS16(tmp0) == info->PanelXRes) && @@ -1513,9 +1603,60 @@ static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->Flags = 0; } } + + if (info->DotClock == 0) { + DisplayModePtr tmp_mode = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No valid timing info from BIOS.\n"); + /* No timing information for the native mode, + use whatever specified in the Modeline. + If no Modeline specified, we'll just pick + the VESA mode at 60Hz refresh rate which + is likely to be the best for a flat panel. + */ + tmp_mode = pScrn->monitor->Modes; + while(tmp_mode) { + if ((tmp_mode->HDisplay == info->PanelXRes) && + (tmp_mode->VDisplay == info->PanelYRes)) { + + float refresh = + (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; + if ((abs(60.0 - refresh) < 1.0) || + (tmp_mode->type == 0)) { + info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + info->DotClock = tmp_mode->Clock; + info->Flags = 0; + break; + } + tmp_mode = tmp_mode->next; + } + } + if ((info->DotClock == 0) && !pRADEONEnt->MonInfo1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Panel size is not correctly detected.\n" + "Please try to use PanelSize option for correct settings.\n"); + return FALSE; + } + } } } } + + if (info->VBIOS) { + tmp = RADEON_BIOS16(info->FPBIOSstart + 0x30); + info->sclk = RADEON_BIOS16(tmp + 8) / 100.0; + info->mclk = RADEON_BIOS16(tmp + 10) / 100.0; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No valid info for SCLK/MCLK for display bandwidth calculation.\n"); + info->sclk = 200.00; + info->mclk = 200.00; + } + return TRUE; } @@ -1633,6 +1774,56 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) return TRUE; } +static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 tmp; + int i, n; + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = 0; + info->tmds_pll[i].freq = 0; + } + + if (info->VBIOS) { + tmp = RADEON_BIOS16(info->FPBIOSstart + 0x34); + if (tmp) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DFP table revision: %d\n", RADEON_BIOS8(tmp)); + if (RADEON_BIOS8(tmp) == 3) { + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; i<n; i++) { + info->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); + } + return; + } + + /* revision 4 has some problem as it appears in RV280, + comment it off for new, use default instead */ + /* + else if (RADEON_BIOS8(tmp) == 4) { + int stride = 0; + n = RADEON_BIOS8(tmp + 5) + 1; + if (n > 4) n = 4; + for (i=0; i<n; i++) { + info->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); + info->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); + if (i == 0) stride += 10; + else stride += 6; + } + return; + } + */ + } + } + + for (i=0; i<4; i++) { + info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; + info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; + } +} /* Read PLL parameters from BIOS block. Default to typical values if * there is no BIOS. @@ -1658,7 +1849,6 @@ static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn) case PCI_CHIP_R200_QL: case PCI_CHIP_R200_QN: case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_Ql: case PCI_CHIP_R200_BB: pll->reference_freq = 2700; pll->reference_div = 12; @@ -1789,6 +1979,99 @@ static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn) return TRUE; } +/* Set up MC_FB_LOCATION and related registers */ +static void +RADEONSetFBLocation(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 mc_fb_location; + CARD32 mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); + + if (info->IsIGP) { + mc_fb_location = INREG(RADEON_NB_TOM); + + OUTREG(RADEON_GRPH2_BUFFER_CNTL, + INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000); + + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) { + /* This is to workaround the asic bug for RMX, some versions + of BIOS don't have this register initialized correctly. + */ + OUTREGP(RADEON_CRTC_MORE_CNTL, RADEON_CRTC_H_CUTOFF_ACTIVE_EN, + ~RADEON_CRTC_H_CUTOFF_ACTIVE_EN); + } + } else +#ifdef XF86DRI + if ( info->directRenderingEnabled && info->drmMinor < 10 ) { + mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U; + } else +#endif + { + CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE); + + mc_fb_location = (aper0_base >> 16) + | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1) + ) & 0xffff0000U); + } + + info->fbLocation = (mc_fb_location & 0xffff) << 16; + + if (((mc_agp_location & 0xffff) << 16) != + ((mc_fb_location & 0xffff0000U) + 0x10000)) { + mc_agp_location = mc_fb_location & 0xffff0000U; + mc_agp_location |= (mc_agp_location + 0x10000) >> 16; + } + + RADEONWaitForIdleMMIO(pScrn); + + OUTREG(RADEON_MC_FB_LOCATION, mc_fb_location); + OUTREG(RADEON_MC_AGP_LOCATION, mc_agp_location); + OUTREG(RADEON_DISPLAY_BASE_ADDR, info->fbLocation); + if (info->HasCRTC2) + OUTREG(RADEON_DISPLAY2_BASE_ADDR, info->fbLocation); + OUTREG(RADEON_OV0_BASE_ADDR, info->fbLocation); +} + +static void RADEONGetVRamType(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp; + + if (info->IsIGP || (info->ChipFamily >= CHIP_FAMILY_R300) || + (INREG(RADEON_MEM_SDRAM_MODE_REG) & (1<<30))) + info->IsDDR = TRUE; + else + info->IsDDR = FALSE; + + tmp = INREG(RADEON_MEM_CNTL); + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { + tmp &= R300_MEM_NUM_CHANNELS_MASK; + switch (tmp) { + case 0: info->RamWidth = 64; break; + case 1: info->RamWidth = 128; break; + case 2: info->RamWidth = 256; break; + default: info->RamWidth = 128; break; + } + } else if ((info->ChipFamily == CHIP_FAMILY_RV100) || + (info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)){ + if (tmp & RV100_HALF_MODE) info->RamWidth = 32; + else info->RamWidth = 64; + } else { + if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) info->RamWidth = 128; + else info->RamWidth = 64; + } + + /* This may not be correct, as some cards can have half of channel disabled + * ToDo: identify these cases + */ +} + /* This is called by RADEONPreInit to handle config file overrides for * things like chipset and memory regions. Also determine memory size * and type. If memory type ever needs an override, put it in this @@ -1799,9 +2082,11 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); EntityInfoPtr pEnt = info->pEnt; GDevPtr dev = pEnt->device; - int offset = 0; /* RAM Type */ MessageType from; unsigned char *RADEONMMIO = info->MMIO; +#ifdef XF86DRI + const char *s; +#endif /* Chipset */ from = X_PROBED; @@ -1868,45 +2153,27 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) break; case PCI_CHIP_R200_BB: + case PCI_CHIP_R200_BC: case PCI_CHIP_R200_QH: - case PCI_CHIP_R200_QI: - case PCI_CHIP_R200_QJ: - case PCI_CHIP_R200_QK: case PCI_CHIP_R200_QL: case PCI_CHIP_R200_QM: - case PCI_CHIP_R200_QN: - case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_Qh: - case PCI_CHIP_R200_Qi: - case PCI_CHIP_R200_Qj: - case PCI_CHIP_R200_Qk: - case PCI_CHIP_R200_Ql: info->ChipFamily = CHIP_FAMILY_R200; break; - case PCI_CHIP_RV200_QW: /* RV200 desktop */ - case PCI_CHIP_RV200_QX: - info->ChipFamily = CHIP_FAMILY_RV200; - break; - case PCI_CHIP_RADEON_LW: case PCI_CHIP_RADEON_LX: info->IsMobility = TRUE; + case PCI_CHIP_RV200_QW: /* RV200 desktop */ + case PCI_CHIP_RV200_QX: info->ChipFamily = CHIP_FAMILY_RV200; break; - case PCI_CHIP_RV250_Id: - case PCI_CHIP_RV250_Ie: - case PCI_CHIP_RV250_If: - case PCI_CHIP_RV250_Ig: - info->ChipFamily = CHIP_FAMILY_RV250; - break; - case PCI_CHIP_RV250_Ld: - case PCI_CHIP_RV250_Le: case PCI_CHIP_RV250_Lf: case PCI_CHIP_RV250_Lg: info->IsMobility = TRUE; + case PCI_CHIP_RV250_If: + case PCI_CHIP_RV250_Ig: info->ChipFamily = CHIP_FAMILY_RV250; break; @@ -1917,18 +2184,13 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->IsIGP = TRUE; break; + case PCI_CHIP_RV280_5C61: + case PCI_CHIP_RV280_5C63: + info->IsMobility = TRUE; case PCI_CHIP_RV280_5960: case PCI_CHIP_RV280_5961: case PCI_CHIP_RV280_5962: - case PCI_CHIP_RV280_5963: - info->ChipFamily = CHIP_FAMILY_RV280; - break; - - case PCI_CHIP_RV280_5968: - case PCI_CHIP_RV280_5969: - case PCI_CHIP_RV280_596A: - case PCI_CHIP_RV280_596B: - info->IsMobility = TRUE; + case PCI_CHIP_RV280_5964: info->ChipFamily = CHIP_FAMILY_RV280; break; @@ -1944,15 +2206,29 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) break; case PCI_CHIP_RV350_NP: + case PCI_CHIP_RV350_NQ: + case PCI_CHIP_RV350_NR: + case PCI_CHIP_RV350_NS: + case PCI_CHIP_RV350_NT: + case PCI_CHIP_RV350_NV: info->IsMobility = TRUE; case PCI_CHIP_RV350_AP: - case PCI_CHIP_RV350_AR: + case PCI_CHIP_RV350_AQ: + case PCI_CHIP_RV360_AR: + case PCI_CHIP_RV350_AS: + case PCI_CHIP_RV350_AT: + case PCI_CHIP_RV350_AV: info->ChipFamily = CHIP_FAMILY_RV350; break; + case PCI_CHIP_R350_AH: + case PCI_CHIP_R350_AI: + case PCI_CHIP_R350_AJ: case PCI_CHIP_R350_AK: case PCI_CHIP_R350_NH: + case PCI_CHIP_R350_NI: case PCI_CHIP_R350_NK: + case PCI_CHIP_R360_NJ: info->ChipFamily = CHIP_FAMILY_R350; break; @@ -1969,7 +2245,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) pScrn->memPhysBase = info->LinearAddr; if (dev->MemBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Linear address override, using 0x%08x instead of 0x%08x\n", + "Linear address override, using 0x%08lx instead of 0x%08lx\n", dev->MemBase, info->LinearAddr); info->LinearAddr = dev->MemBase; @@ -1987,7 +2263,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; if (dev->BiosBase) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS address override, using 0x%08x instead of 0x%08x\n", + "BIOS address override, using 0x%08lx instead of 0x%08lx\n", dev->BiosBase, info->BIOSAddr); info->BIOSAddr = dev->BiosBase; @@ -2002,34 +2278,18 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) from = X_PROBED; if (info->FBDev) pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; - else if ((info->ChipFamily == CHIP_FAMILY_RS100) || + else if ((info->ChipFamily == CHIP_FAMILY_RS100) || (info->ChipFamily == CHIP_FAMILY_RS200) || (info->ChipFamily == CHIP_FAMILY_RS300)) { CARD32 tom = INREG(RADEON_NB_TOM); - pScrn->videoRam = (((tom >> 16) - - (tom & 0xffff) + 1) << 6); - OUTREG(RADEON_MC_FB_LOCATION, tom); - OUTREG(RADEON_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(RADEON_DISPLAY2_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(RADEON_OV0_BASE_ADDR, (tom & 0xffff) << 16); - /* This is supposed to fix the crtc2 noise problem. - */ - OUTREG(RADEON_GRPH2_BUFFER_CNTL, - INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000); - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200)) { - /* This is to workaround the asic bug for RMX, some versions - of BIOS dosen't have this register initialized correctly. - */ - OUTREGP(RADEON_CRTC_MORE_CNTL, RADEON_CRTC_H_CUTOFF_ACTIVE_EN, - ~RADEON_CRTC_H_CUTOFF_ACTIVE_EN); - } + pScrn->videoRam = (((tom >> 16) - + (tom & 0xffff) + 1) << 6); - } - else + OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024); + } else { pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024; + } /* Some production boards of m6 will return 0 if it's 8 MB */ if (pScrn->videoRam == 0) pScrn->videoRam = 8192; @@ -2046,8 +2306,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info1 = RADEONPTR(pRADEONEnt->pPrimaryScrn); info1->FbMapSize = pScrn->videoRam * 1024; info->LinearAddr += pScrn->videoRam * 1024; - info1->Clone = FALSE; - info1->CurCloneMode = NULL; + info1->MergedFB = FALSE; } info->R300CGWorkaround = @@ -2058,13 +2317,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) info->MemCntl = INREG(RADEON_SDRAM_MODE_REG); info->BusCntl = INREG(RADEON_BUS_CNTL); - /* RAM */ - switch (info->MemCntl >> 30) { - case 0: offset = 0; break; /* 64-bit SDR SDRAM */ - case 1: offset = 1; break; /* 64-bit DDR SDRAM */ - default: offset = 0; - } - info->ram = &RADEONRAM[offset]; + RADEONGetVRamType(pScrn); if (dev->videoRam) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -2077,71 +2330,44 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn) pScrn->videoRam &= ~1023; info->FbMapSize = pScrn->videoRam * 1024; xf86DrvMsg(pScrn->scrnIndex, from, - "VideoRAM: %d kByte (%s)\n", pScrn->videoRam, info->ram->name); + "VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); #ifdef XF86DRI /* AGP/PCI */ - if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI-only mode\n"); - } else { - switch (info->Chipset) { -#if 0 - case PCI_CHIP_RADEON_XX: info->IsPCI = TRUE; break; -#endif - case PCI_CHIP_RV100_QY: - case PCI_CHIP_RV100_QZ: - case PCI_CHIP_RADEON_LW: - case PCI_CHIP_RADEON_LX: - case PCI_CHIP_RADEON_LY: - case PCI_CHIP_RADEON_LZ: - case PCI_CHIP_RADEON_QD: - case PCI_CHIP_RADEON_QE: - case PCI_CHIP_RADEON_QF: - case PCI_CHIP_RADEON_QG: - case PCI_CHIP_R200_BB: - case PCI_CHIP_R200_QH: - case PCI_CHIP_R200_QI: - case PCI_CHIP_R200_QJ: - case PCI_CHIP_R200_QK: - case PCI_CHIP_R200_QL: - case PCI_CHIP_R200_QM: - case PCI_CHIP_R200_QN: - case PCI_CHIP_R200_QO: - case PCI_CHIP_R200_Qh: - case PCI_CHIP_R200_Qi: - case PCI_CHIP_R200_Qj: - case PCI_CHIP_R200_Qk: - case PCI_CHIP_R200_Ql: - case PCI_CHIP_RV200_QW: - case PCI_CHIP_RV200_QX: - case PCI_CHIP_RV250_Id: - case PCI_CHIP_RV250_Ie: - case PCI_CHIP_RV250_If: - case PCI_CHIP_RV250_Ig: - case PCI_CHIP_RV250_Ld: - case PCI_CHIP_RV250_Le: - case PCI_CHIP_RV250_Lf: - case PCI_CHIP_RV250_Lg: - case PCI_CHIP_RV280_5960: - case PCI_CHIP_RV280_5961: - case PCI_CHIP_RV280_5962: - case PCI_CHIP_RV280_5963: - case PCI_CHIP_RV280_5968: - case PCI_CHIP_RV280_5969: - case PCI_CHIP_RV280_596A: - case PCI_CHIP_RV280_596B: - case PCI_CHIP_R300_AD: - case PCI_CHIP_R300_AE: - case PCI_CHIP_R300_AF: - case PCI_CHIP_R300_AG: - case PCI_CHIP_R300_ND: - case PCI_CHIP_R300_NE: - case PCI_CHIP_R300_NF: - case PCI_CHIP_R300_NG: - default: info->IsPCI = FALSE; break; + if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { + if (strcmp(s, "AGP") == 0) { + info->IsPCI = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into AGP mode\n"); + } else if (strcmp(s, "PCI") == 0) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n"); + } else if (strcmp(s, "PCIE") == 0) { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI Express not supported yet, use PCI mode\n"); + } else { + s = NULL; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Invalid BusType option, use detected type\n"); } } + + if (!s) { + CARD32 tmp = pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG); + /* There are signatures in BIOS and PCI-SSID for a PCI card, but they are not very reliable. + Following detection method works for all cards tested so far. + Note, checking AGP_ENABLE bit after drmAgpEnable call can also give the correct result. + However, calling drmAgpEnable on a PCI card can cause some strange lockup when the server + restarts next time. + */ + pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, tmp | RADEON_AGP_ENABLE); + if (pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG) & RADEON_AGP_ENABLE) { + info->IsPCI = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP card detected\n"); + } else { + info->IsPCI = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PCI card detected\n"); + } + pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, tmp); + } #endif return TRUE; @@ -2172,6 +2398,9 @@ static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) val |= (Clock ? 0:RADEON_GPIO_EN_1); val |= (data ? 0:RADEON_GPIO_EN_0); OUTREG(info->DDCReg, val); + + /* read back to improve reliability on some cards. */ + val = INREG(info->DDCReg); } static Bool RADEONI2cInit(ScrnInfoPtr pScrn) @@ -2480,25 +2709,29 @@ static DisplayModePtr RADEONDDCModes(ScrnInfoPtr pScrn) /* XFree86's xf86ValidateModes routine doesn't work well with DDC modes, * so here is our own validation routine. */ -static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, - RADEONMonitorType DisplayType) +static int RADEONValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName, + RADEONMonitorType DisplayType, int crtc2) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn1); DisplayModePtr p; DisplayModePtr last = NULL; DisplayModePtr first = NULL; DisplayModePtr ddcModes = NULL; int count = 0; int i, width, height; + ScrnInfoPtr pScrn = pScrn1; - pScrn->virtualX = pScrn->display->virtualX; - pScrn->virtualY = pScrn->display->virtualY; + if (crtc2) + pScrn = info->CRT2pScrn; + + pScrn->virtualX = pScrn1->display->virtualX; + pScrn->virtualY = pScrn1->display->virtualY; if (pScrn->monitor->DDC && !info->UseBiosDividers) { int maxVirtX = pScrn->virtualX; int maxVirtY = pScrn->virtualY; - if ((DisplayType != MT_CRT) && !info->IsSecondary) { + if ((DisplayType != MT_CRT) && (!info->IsSecondary) && (!crtc2)) { /* The panel size we collected from BIOS may not be the * maximum size supported by the panel. If not, we update * it now. These will be used if no matching mode can be @@ -2514,7 +2747,7 @@ static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, /* If primary head is a flat panel, use RMX by default */ if ((!info->IsSecondary && DisplayType != MT_CRT) && - !info->ddc_mode) { + (!info->ddc_mode) && (!crtc2)) { /* These values are effective values after expansion. * They are not really used to set CRTC registers. */ @@ -2621,8 +2854,13 @@ static int RADEONValidateDDCModes(ScrnInfoPtr pScrn, char **ppModeName, p->type |= M_T_USERDEF; } - pScrn->virtualX = pScrn->display->virtualX = maxVirtX; - pScrn->virtualY = pScrn->display->virtualY = maxVirtY; + if (crtc2) { + pScrn->virtualX = maxVirtX; + pScrn->virtualY = maxVirtY; + } else { + pScrn->virtualX = pScrn->display->virtualX = maxVirtX; + pScrn->virtualY = pScrn->display->virtualY = maxVirtY; + } } /* Close the doubly-linked mode list, if we found any usable modes */ @@ -2680,7 +2918,7 @@ static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) pScrn->virtualY = MAX(pScrn->virtualY, info->PanelYRes); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No valid mode specified, force to native mdoe\n"); + "No valid mode specified, force to native mode\n"); } return new; @@ -2914,243 +3152,166 @@ static void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) } } -static int RADEONValidateCloneModes(ScrnInfoPtr pScrn) +static int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn1); ClockRangePtr clockRanges; - DisplayModePtr tmp_mode = NULL; - DisplayModePtr clone_mode, save_mode; - int modesFound = 0; - int count = 0; - int tmp_hdisplay = 0; - int tmp_vdisplay = 0; - int i, save_n_hsync, save_n_vrefresh; - range save_hsync, save_vrefresh; - char *s; - char **clone_mode_names = NULL; - Bool ddc_mode = info->ddc_mode; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + int modesFound; + ScrnInfoPtr pScrn = info->CRT2pScrn; - /* Save all infomations that will be changed by clone mode validateion */ - save_mode = pScrn->modes; - pScrn->modes = NULL; + /* fill in pScrn2 */ + pScrn->videoRam = pScrn1->videoRam; + pScrn->depth = pScrn1->depth; + pScrn->numClocks = pScrn1->numClocks; + pScrn->progClock = pScrn1->progClock; + pScrn->fbFormat = pScrn1->fbFormat; + pScrn->videoRam = pScrn1->videoRam; + pScrn->maxHValue = pScrn1->maxHValue; + pScrn->maxVValue = pScrn1->maxVValue; + pScrn->xInc = pScrn1->xInc; - /* Clone display mode names, duplicate all mode names for primary - * head. Allocate one more, in case pScrn->display->modes[0] == - * NULL */ - while (pScrn->display->modes[count]) count++; - clone_mode_names = xnfalloc((count+2) * sizeof(char*)); - for (i = 0; i < count; i++) { - clone_mode_names[i] = xnfalloc(strlen(pScrn->display->modes[i]) + 1); - strcpy(clone_mode_names[i], pScrn->display->modes[i]); + if (info->NoVirtual) { + pScrn1->display->virtualX = 0; + pScrn1->display->virtualY = 0; } - clone_mode_names[count] = NULL; - clone_mode_names[count+1] = NULL; - pScrn->progClock = 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, Xconfigurator + * may not be able to probe both monitors correctly through + * vbe probe function (RADEONProbeDDC). 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) + RADEONSetSyncRangeFromEdid(pScrn, 1); + if (pScrn->monitor->nVrefresh <= 0) + RADEONSetSyncRangeFromEdid(pScrn, 0); + } + /* 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; - clockRanges->interlaceAllowed = (info->CloneType == MT_CRT); - clockRanges->doubleScanAllowed = (info->CloneType == MT_CRT); + clockRanges->interlaceAllowed = (info->MergeType == MT_CRT); + clockRanges->doubleScanAllowed = (info->MergeType == MT_CRT); - /* Only take one clone mode from config file for now, rest of clone - * modes will copy from primary head. + /* We'll use our own mode validation routine for DFP/LCD, since + * xf86ValidateModes does not work correctly with the DFP/LCD modes + * 'stretched' from their native mode. */ - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_MODE))) { - if (sscanf(s, "%dx%d", &tmp_hdisplay, &tmp_vdisplay) == 2) { - if(count > 0) free(clone_mode_names[0]); - else count++; - clone_mode_names[0] = xnfalloc(strlen(s)+1); - sprintf(clone_mode_names[0], "%dx%d", tmp_hdisplay, tmp_vdisplay); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone mode %s in config file is used\n"); - } - } - - for (i = 0; i < count; i++) { - if (sscanf(clone_mode_names[i], "%dx%d", - &tmp_hdisplay, &tmp_vdisplay) == 2) { - if (pScrn->display->virtualX < tmp_hdisplay) - pScrn->display->virtualX = tmp_hdisplay; - if (pScrn->display->virtualY < tmp_vdisplay) - pScrn->display->virtualY = tmp_vdisplay; - } - } + if (info->MergeType == MT_CRT && !info->ddc_mode) { - save_hsync = pScrn->monitor->hsync[0]; - save_vrefresh = pScrn->monitor->vrefresh[0]; - save_n_hsync = pScrn->monitor->nHsync; - save_n_vrefresh = pScrn->monitor->nVrefresh; - - pScrn->monitor->DDC = NULL; - pScrn->monitor->nHsync = 0; - pScrn->monitor->nVrefresh = 0; + modesFound = + xf86ValidateModes(pScrn, + pScrn->monitor->Modes, + pScrn1->display->modes, + clockRanges, + NULL, /* linePitches */ + 8 * 64, /* minPitch */ + 8 * 1024, /* maxPitch */ + 64 * pScrn1->bitsPerPixel, /* pitchInc */ + 128, /* minHeight */ + 8 * 1024, /*2048,*/ /* maxHeight */ + pScrn1->display->virtualX ? pScrn1->virtualX : 0, + pScrn1->display->virtualY ? pScrn1->virtualY : 0, + info->FbMapSize, + LOOKUP_BEST_REFRESH); - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_HSYNC))) { - if (sscanf(s, "%f-%f", &pScrn->monitor->hsync[0].lo, - &pScrn->monitor->hsync[0].hi) == 2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "HSync for CloneMode from config file: %s\n", s); - pScrn->monitor->nHsync = 1; - } else { - pScrn->monitor->nHsync = 0; - } - } + if (modesFound == -1) return 0; - if ((s = xf86GetOptValString(info->Options, OPTION_CLONE_VREFRESH))) { - if (sscanf(s, "%f-%f", &pScrn->monitor->vrefresh[0].lo, - &pScrn->monitor->vrefresh[0].hi) == 2) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "VRefresh for CloneMode from config file: %s\n", s); - pScrn->monitor->nVrefresh = 1; - } else { - pScrn->monitor->nVrefresh = 0; + xf86PruneDriverModes(pScrn); + if (!modesFound || !pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + return 0; } - } - - pScrn->monitor->DDC = pRADEONEnt->MonInfo2; - if (pScrn->monitor->DDC) { - if ((pScrn->monitor->nVrefresh == 0) || (pScrn->monitor->nHsync == 0)) { - if (pScrn->monitor->nHsync == 0) - RADEONSetSyncRangeFromEdid(pScrn, 1); - if (pScrn->monitor->nVrefresh == 0) - RADEONSetSyncRangeFromEdid(pScrn, 0); - } - } else if (info->ddc_mode) { - ddc_mode = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No DDC data available for clone mode, " - "DDCMode option is dismissed\n"); - } - if (info->CloneType == MT_CRT && !ddc_mode) { - modesFound = - xf86ValidateModes(pScrn, pScrn->monitor->Modes, - clone_mode_names, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - 2048, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); } else { - /* Try to add DDC modes */ - info->IsSecondary = TRUE; /*fake secondary head*/ - modesFound = RADEONValidateDDCModes(pScrn, clone_mode_names, - info->CloneType); - info->IsSecondary = FALSE; + /* First, free any allocated modes during configuration, since + * we don't need them + */ + while (pScrn->modes) + xf86DeleteMode(&pScrn->modes, pScrn->modes); + while (pScrn->modePool) + xf86DeleteMode(&pScrn->modePool, pScrn->modePool); + + /* Next try to add DDC modes */ + modesFound = RADEONValidateDDCModes(pScrn, pScrn1->display->modes, + info->MergeType, 1); /* If that fails and we're connect to a flat panel, then try to * add the flat panel modes */ - if (modesFound < 1 && info->CloneType != MT_CRT) { - modesFound = - xf86ValidateModes(pScrn, pScrn->monitor->Modes, - clone_mode_names, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - 2048, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - } - } - - if (modesFound > 0) { - int valid = 0; - save_mode = pScrn->modes; - xf86SetCrtcForModes(pScrn, 0); - xf86PrintModes(pScrn); - for (i = 0; i < modesFound; i++) { - - while (pScrn->modes->status != MODE_OK) { - pScrn->modes = pScrn->modes->next; - } - if (!pScrn->modes) break; - - if (pScrn->modes->Clock != 0.0) { - - clone_mode = xnfcalloc (1, sizeof (DisplayModeRec)); - if (!clone_mode) break; - memcpy(clone_mode, pScrn->modes, sizeof(DisplayModeRec)); - clone_mode->name = xnfalloc(strlen(pScrn->modes->name) + 1); - strcpy(clone_mode->name, pScrn->modes->name); - - if (!info->CurCloneMode) { - info->CloneModes = clone_mode; - info->CurCloneMode = clone_mode; - clone_mode->prev = NULL; - } else { - clone_mode->prev = tmp_mode; - clone_mode->prev->next = clone_mode; - } - valid++; + if (info->MergeType != MT_CRT) { - tmp_mode = clone_mode; - clone_mode->next = NULL; + /* some panels have DDC, but don't have internal scaler. + * in this case, we need to validate additional modes + * by using on-chip RMX. + */ + int user_modes_asked = 0, user_modes_found = 0, i; + DisplayModePtr tmp_mode = pScrn->modes; + while (pScrn1->display->modes[user_modes_asked]) user_modes_asked++; + if (tmp_mode) { + for (i = 0; i < modesFound; i++) { + if (tmp_mode->type & M_T_USERDEF) user_modes_found++; + tmp_mode = tmp_mode->next; + } } - pScrn->modes = pScrn->modes->next; - } - - /* no longer needed, free it */ - pScrn->modes = save_mode; - while (pScrn->modes) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - pScrn->modes = NULL; - /* modepool is no longer needed, free it */ - while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - pScrn->modePool = NULL; + if ((modesFound <= 1) || (user_modes_found < user_modes_asked)) { + /* when panel size is not valid, try to validate + * mode using xf86ValidateModes routine + * This can happen when DDC is disabled. + */ + /* if (info->PanelXRes < 320 || info->PanelYRes < 200) */ + modesFound = + xf86ValidateModes(pScrn, + pScrn->monitor->Modes, + pScrn1->display->modes, + clockRanges, + NULL, /* linePitches */ + 8 * 64, /* minPitch */ + 8 * 1024, /* maxPitch */ + 64 * pScrn1->bitsPerPixel, /* pitchInc */ + 128, /* minHeight */ + 8 * 1024, /*2048,*/ /* maxHeight */ + pScrn1->display->virtualX, + pScrn1->display->virtualY, + info->FbMapSize, + LOOKUP_BEST_REFRESH); - modesFound = valid; - } + } + } - /* Clone_mode_names list is no longer needed, free it. */ - if (clone_mode_names) { - for (i = 0; clone_mode_names[i]; i++) { - free(clone_mode_names[i]); - clone_mode_names[i] = NULL; + /* Setup the screen's clockRanges for the VidMode extension */ + if (!pScrn->clockRanges) { + pScrn->clockRanges = xnfcalloc(sizeof(*(pScrn->clockRanges)), 1); + memcpy(pScrn->clockRanges, clockRanges, sizeof(*clockRanges)); + pScrn->clockRanges->strategy = LOOKUP_BEST_REFRESH; } - free(clone_mode_names); - clone_mode_names = NULL; - } - - /* We need to restore all changed info for the primary head */ - - pScrn->monitor->hsync[0] = save_hsync; - pScrn->monitor->vrefresh[0] = save_vrefresh; - pScrn->monitor->nHsync = save_n_hsync; - pScrn->monitor->nVrefresh = save_n_vrefresh; - - /* - * Also delete the clockRanges (if it was setup) since it will be - * set up during the primary head initialization. - */ - while (pScrn->clockRanges) { - ClockRangesPtr CRtmp = pScrn->clockRanges; - pScrn->clockRanges = pScrn->clockRanges->next; - xfree(CRtmp); + /* Fail if we still don't have any valid modes */ + if (modesFound < 1) { + if (info->MergeType == MT_CRT) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid DDC modes found for this CRT\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Try turning off the \"DDCMode\" option\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid mode found for this DFP/LCD\n"); + } + return 0; + } } - - return modesFound; } + /* This is called by RADEONPreInit to validate modes and compute * parameters for all of the valid modes. */ @@ -3160,6 +3321,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) ClockRangePtr clockRanges; int modesFound; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + char *s; /* This option has two purposes: * @@ -3188,48 +3350,21 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) * * Note: This option will be dismissed if no DDC data is available. */ + + if (info->MergedFB) { + if (!(pScrn->display->virtualX)) + info->NoVirtual = TRUE; + else + info->NoVirtual = FALSE; + } + info->ddc_mode = xf86ReturnOptValBool(info->Options, OPTION_DDC_MODE, FALSE); - /* don't use RMX if we have a dual-tdms panels */ + /* don't use RMX if we have a dual-tmds panels */ if (pRADEONEnt->MonType2 == MT_DFP) info->ddc_mode = TRUE; - /* Here is a hack for cloning first display on the second head. If - * we don't do this, when both heads are connected, the same CRTC - * will be used to drive them according to the capability of the - * primary head. This can cause an unstable or blank screen, or - * even worse it can damage a monitor. This feature is also - * important for laptops (using M6, M7), where the panel can't be - * disconnect when one wants to use the CRT port. Although 2 - * Screens can be set up in the config file for displaying same - * content on two monitors, it has problems with cursor, overlay, - * DRI. - */ - if (info->HasCRTC2) { - if (info->Clone) { - - /* If we have 2 screens from the config file, we don't need - * to do clone thing, let each screen handles one head. - */ - if (!pRADEONEnt->HasSecondary) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Clone modes validation ------------ \n"); - - modesFound = RADEONValidateCloneModes(pScrn); - if (modesFound < 1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid mode found for CRTC2 clone\n"); - info->Clone = FALSE; - info->CurCloneMode = NULL; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total of %d clone modes found ------------ \n\n", - modesFound); - } - } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Validating modes on %s head ---------\n", info->IsSecondary ? "Secondary" : "Primary"); @@ -3245,6 +3380,59 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) "No DDC data available, DDCMode option is dismissed\n"); } + if ((info->DisplayType == MT_DFP) || + (info->DisplayType == MT_LCD)) { + if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { + int PanelX, PanelY; + DisplayModePtr tmp_mode = NULL; + if (sscanf(s, "%dx%d", &PanelX, &PanelY) == 2) { + info->PanelXRes = PanelX; + info->PanelYRes = PanelY; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Panel size is forced to: %s\n", s); + + /* We can't trust BIOS or DDC timings anymore, + Use whatever specified in the Modeline. + If no Modeline specified, we'll just pick the VESA mode at + 60Hz refresh rate which is likely to be the best for a flat panel. + */ + info->ddc_mode = FALSE; + pScrn->monitor->DDC = NULL; + tmp_mode = pScrn->monitor->Modes; + while(tmp_mode) { + if ((tmp_mode->HDisplay == PanelX) && + (tmp_mode->VDisplay == PanelY)) { + + float refresh = + (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; + if ((abs(60.0 - refresh) < 1.0) || + (tmp_mode->type == 0)) { + info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + info->DotClock = tmp_mode->Clock; + info->Flags = 0; + break; + } + } + tmp_mode = tmp_mode->next; + } + if (info->DotClock == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid timing info for specified panel size.\n" + "Please specify the Modeline for this panel\n"); + return FALSE; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Invalid PanelSize value: %s\n", s); + } + } + } + if (pScrn->monitor->DDC) { /* If we still don't know sync range yet, let's try EDID. * @@ -3317,7 +3505,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) /* Next try to add DDC modes */ modesFound = RADEONValidateDDCModes(pScrn, pScrn->display->modes, - info->DisplayType); + info->DisplayType, 0); /* If that fails and we're connect to a flat panel, then try to * add the flat panel modes @@ -3388,30 +3576,110 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) xf86SetCrtcForModes(pScrn, 0); - /* We need to adjust virtual size if the clone modes have larger - * display size. - */ - if (info->Clone && info->CloneModes) { - DisplayModePtr clone_mode = info->CloneModes; - while (1) { - if ((clone_mode->HDisplay > pScrn->virtualX) || - (clone_mode->VDisplay > pScrn->virtualY)) { - pScrn->virtualX = - pScrn->display->virtualX = clone_mode->HDisplay; - pScrn->virtualY = - pScrn->display->virtualY = clone_mode->VDisplay; - RADEONSetPitch(pScrn); + if (info->HasCRTC2) { + if (info->MergedFB) { + + /* If we have 2 screens from the config file, we don't need + * to do clone thing, let each screen handles one head. + */ + if (!pRADEONEnt->HasSecondary) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Validating CRTC2 modes for MergedFB ------------ \n"); + + modesFound = RADEONValidateMergeModes(pScrn); + if (modesFound < 1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid mode found for CRTC2, disabling MergedFB\n"); + info->MergedFB = FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Total of %d CRTC2 modes found for MergedFB------------ \n", + modesFound); } - if (!clone_mode->next) break; - clone_mode = clone_mode->next; } } pScrn->currentMode = pScrn->modes; + if(info->MergedFB) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Modes for CRT1: ********************\n"); + } xf86PrintModes(pScrn); + if(info->MergedFB) { + + xf86SetCrtcForModes(info->CRT2pScrn, INTERLACE_HALVE_V); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Modes for CRT2: ********************\n"); + + xf86PrintModes(info->CRT2pScrn); + + info->CRT1Modes = pScrn->modes; + info->CRT1CurrentMode = pScrn->currentMode; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Generating MergedFB mode list\n"); + + if (info->NoVirtual) { + pScrn->display->virtualX = 0; + pScrn->display->virtualY = 0; + } + pScrn->modes = RADEONGenerateModeList(pScrn, info->MetaModes, + info->CRT1Modes, info->CRT2pScrn->modes, + info->CRT2Position); + + if(!pScrn->modes) { + + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to parse MetaModes or no modes found. MergeFB mode disabled.\n"); + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + } + pScrn->modes = info->CRT1Modes; + info->CRT1Modes = NULL; + info->MergedFB = FALSE; + + } + } + + if (info->MergedFB) { + /* If no virtual dimension was given by the user, + * calculate a sane one now. Adapts pScrn->virtualX, + * pScrn->virtualY and pScrn->displayWidth. + */ + RADEONRecalcDefaultVirtualSize(pScrn); + info->CRT2pScrn->virtualX = pScrn->virtualX; + info->CRT2pScrn->virtualY = pScrn->virtualY; + RADEONSetPitch(pScrn); + RADEONSetPitch(info->CRT2pScrn); + + pScrn->modes = pScrn->modes->next; /* We get the last from GenerateModeList() */ + pScrn->currentMode = pScrn->modes; + + /* Update CurrentLayout */ + info->CurrentLayout.mode = pScrn->currentMode; + info->CurrentLayout.displayWidth = pScrn->displayWidth; + } + /* Set DPI */ - xf86SetDpi(pScrn, 0, 0); + /* xf86SetDpi(pScrn, 0, 0); */ + + if(info->MergedFB) + RADEONMergedFBSetDpi(pScrn, info->CRT2pScrn, info->CRT2Position); + else + xf86SetDpi(pScrn, 0, 0); /* Get ScreenInit function */ if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; @@ -3523,8 +3791,10 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) } } - if (xf86GetOptValInteger(info->Options, - OPTION_GART_SIZE, (int *)&(info->gartSize))) { + if ((xf86GetOptValInteger(info->Options, + OPTION_GART_SIZE, (int *)&(info->gartSize))) || + (xf86GetOptValInteger(info->Options, + OPTION_GART_SIZE_OLD, (int *)&(info->gartSize)))) { switch (info->gartSize) { case 4: case 8: @@ -3638,6 +3908,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) RADEONInfoPtr info; xf86Int10InfoPtr pInt10 = NULL; void *int10_save = NULL; + const char *s; + RADEONTRACE(("RADEONPreInit\n")); if (pScrn->numEntities != 1) return FALSE; @@ -3646,9 +3918,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info = RADEONPTR(pScrn); info->IsSecondary = FALSE; - info->Clone = FALSE; - info->CurCloneMode = NULL; - info->CloneModes = NULL; + info->MergedFB = FALSE; info->IsSwitching = FALSE; info->MMIO = NULL; @@ -3662,7 +3932,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info->MMIOAddr = info->PciInfo->memBase[2] & 0xffffff00; if (info->pEnt->device->IOBase) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "MMIO address override, using 0x%08x instead of 0x%08x\n", + "MMIO address override, using 0x%08lx instead of 0x%08lx\n", info->pEnt->device->IOBase, info->MMIOAddr); info->MMIOAddr = info->pEnt->device->IOBase; @@ -3770,6 +4040,18 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info->videoKey = 0x1E; } + info->DispPriority = 1; + if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) { + if (strcmp(s, "AUTO") == 0) { + info->DispPriority = 1; + } else if (strcmp(s, "BIOS") == 0) { + info->DispPriority = 0; + } else if (strcmp(s, "HIGH") == 0) { + info->DispPriority = 2; + } else + info->DispPriority = 1; + } + if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) { /* check for Linux framebuffer device */ @@ -3804,6 +4086,16 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONGetBIOSParameters(pScrn, pInt10)) goto fail; + + if (info->DisplayType == MT_DFP) + RADEONGetTMDSInfo(pScrn); + + /* collect MergedFB options */ + /* only parse mergedfb options on the primary head. + Mergedfb is already disabled in xinerama/screen based + multihead */ + if (!info->IsSecondary) + RADEONGetMergedFBOptions(pScrn); if (!RADEONGetPLLParameters(pScrn)) goto fail; @@ -3940,7 +4232,7 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, } } - if (info->Clone) { + if (info->MergedFB) { PAL_SELECT(1); if (info->CurrentLayout.depth == 15) { /* 15bpp mode. This sends 32 values. */ @@ -4057,14 +4349,6 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - if (info->CurCloneMode) { - info->CloneFrameX0 = - (pScrn->virtualX - info->CurCloneMode->HDisplay) / 2; - info->CloneFrameY0 = - (pScrn->virtualY - info->CurCloneMode->VDisplay) / 2; - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE); - } - /* Visual setup */ miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, @@ -4093,48 +4377,52 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) "Acceleration disabled, not initializing the DRI\n"); info->directRenderingEnabled = FALSE; } else if (maxy <= pScrn->virtualY * 3) { - xf86DrvMsg(scrnIndex, X_WARNING, - "Static buffer allocation failed -- " - "need at least %d kB video memory\n", + xf86DrvMsg(scrnIndex, X_ERROR, + "Static buffer allocation failed. Disabling DRI.\n"); + xf86DrvMsg(scrnIndex, X_ERROR, + "At least %d kB of video memory needed at this " + "resolution and depth.\n", (pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes * 3 + 1023) / 1024); info->directRenderingEnabled = FALSE; - } else if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + } else if (info->ChipFamily >= CHIP_FAMILY_R300) { info->directRenderingEnabled = FALSE; xf86DrvMsg(scrnIndex, X_WARNING, "Direct rendering not yet supported on " - "IGP320/330/340/350, 7000, 9000 integrated chips\n"); - } else if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350) || - (info->ChipFamily == CHIP_FAMILY_RV350)) { + "Radeon 9500 and newer cards\n"); + } else if (info->IsSecondary) { + info->directRenderingEnabled = FALSE; + } else if (xf86IsEntityShared(info->pEnt->index)) { + /* Xinerama has sync problem with DRI, disable it for now */ info->directRenderingEnabled = FALSE; xf86DrvMsg(scrnIndex, X_WARNING, - "Direct rendering not yet supported on " - "Radeon 9500/9700 and newer cards\n"); - } else { - if (info->IsSecondary) - info->directRenderingEnabled = FALSE; - else { - /* Xinerama has sync problem with DRI, disable it for now */ - if (xf86IsEntityShared(info->pEnt->index)) { - info->directRenderingEnabled = FALSE; - xf86DrvMsg(scrnIndex, X_WARNING, - "Direct Rendering Disabled -- " - "Dual-head configuration is not working with " - "DRI at present.\n" - "Please use only one Device/Screen " - "section in your XFConfig file.\n"); - } else { - info->directRenderingEnabled = - RADEONDRIScreenInit(pScreen); - } + "Direct Rendering Disabled -- " + "Dual-head configuration is not working with " + "DRI at present.\n" + "Please use the radeon MergedFB option if you " + "want Dual-head with DRI.\n"); +#if 0 + } else if ( pScrn->virtualX > 2048 || pScrn->virtualY > 2048 ) { + if (info->No2048Limit) { + info->directRenderingEnabled = RADEONDRIScreenInit(pScreen); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRI forced on with virtual screen of greater than 2048.\n"); + } else { + info->directRenderingEnabled = FALSE; + xf86DrvMsg(scrnIndex, X_WARNING, + "Direct Rendering Disabled -- " + "Virtual resolution exceeds 2048 " + "(hardware limitation)\n"); } +#endif + } else { + info->directRenderingEnabled = RADEONDRIScreenInit(pScreen); } } #endif + RADEONSetFBLocation(pScrn); + if (!fbScreenInit(pScreen, info->FB, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, @@ -4366,13 +4654,13 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) info->textureSize/1024, info->textureOffset); info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | - (info->frontOffset >> 10)); + ((info->frontOffset + info->fbLocation) >> 10)); info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | - (info->backOffset >> 10)); + ((info->backOffset + info->fbLocation) >> 10)); info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | - (info->depthOffset >> 10)); + ((info->depthOffset + info->fbLocation) >> 10)); } else #endif { @@ -4462,7 +4750,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) int width, height; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursor (scanline %d)\n", + "Using hardware cursor (scanline %ld)\n", info->cursor_start / pScrn->displayWidth / info->CurrentLayout.pixel_bytes); if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, @@ -4503,6 +4791,17 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) info->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = RADEONCloseScreen; + /* Wrap some funcs for MergedFB */ + if(info->MergedFB) { + info->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = RADEONMergePointerMoved; + /* Psuedo xinerama */ + if(info->UseRADEONXinerama) { + RADEONnoPanoramiXExtension = FALSE; + RADEONXineramaExtensionInit(pScrn); + } + } + /* Note unused options */ if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); @@ -4513,9 +4812,15 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* Now that mi, fb, drm and others have done their thing, complete the DRI setup. */ - info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); + if (!(info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen))) { + RADEONAccelInitMMIO(pScreen, info->accel); + } } if (info->directRenderingEnabled) { + if ((info->DispPriority == 1) && (!info->IsPCI)) { + /* we need to re-calculate bandwidth because of AGPMode difference. */ + RADEONInitDispBandwidth(pScrn); + } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering disabled\n"); @@ -4561,7 +4866,7 @@ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, CARD32 tmp; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - if (pRADEONEnt->HasSecondary || info->Clone) { + if (pRADEONEnt->HasSecondary || info->MergedFB) { tmp = INREG(RADEON_DAC_CNTL2); OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); usleep(100000); @@ -4622,6 +4927,7 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); OUTREG(RADEON_CRTC_PITCH, restore->crtc_pitch); OUTREG(RADEON_DISP_MERGE_CNTL, restore->disp_merge_cntl); + OUTREG(RADEON_CRTC_MORE_CNTL, restore->crtc_more_cntl); } /* Write CRTC2 registers */ @@ -4659,7 +4965,7 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->CloneType == MT_DFP) { + info->MergeType == MT_DFP) { OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp2_h_sync_strt_wid); OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid); OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); @@ -4820,6 +5126,7 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, ~(RADEON_PLL_DIV_SEL)); if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_RS300) || (info->ChipFamily == CHIP_FAMILY_R350) || (info->ChipFamily == CHIP_FAMILY_RV350)) { if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { @@ -4861,7 +5168,7 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, | RADEON_PPLL_ATOMIC_UPDATE_EN | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); - xf86DrvMsg(0, X_INFO, "Wrote: rd=%d, fd=%d, pd=%d\n", + xf86DrvMsg(0, X_INFO, "Wrote: rd=%ld, fd=%ld, pd=%ld\n", restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, (restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); @@ -5020,7 +5327,7 @@ static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) if (!pRADEONEnt->IsSecondaryRestored) RADEONRestoreCommonRegisters(pScrn, restore); - if (info->Clone) { + if (info->MergedFB) { RADEONRestoreCrtc2Registers(pScrn, restore); RADEONRestorePLL2Registers(pScrn, restore); } @@ -5061,6 +5368,8 @@ static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->cap1_trig_cntl = INREG(RADEON_CAP1_TRIG_CNTL); save->bus_cntl = INREG(RADEON_BUS_CNTL); save->surface_cntl = INREG(RADEON_SURFACE_CNTL); + save->grph_buffer_cntl = INREG(RADEON_GRPH_BUFFER_CNTL); + save->grph2_buffer_cntl = INREG(RADEON_GRPH2_BUFFER_CNTL); } /* Read miscellaneous registers which might be destroyed by an fbdevHW call */ @@ -5102,6 +5411,7 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); save->crtc_pitch = INREG(RADEON_CRTC_PITCH); save->disp_merge_cntl = INREG(RADEON_DISP_MERGE_CNTL); + save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); } /* Read flat panel registers */ @@ -5122,6 +5432,11 @@ static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL); save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL); save->bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH); + + if (info->ChipFamily == CHIP_FAMILY_RV280) { + /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ + save->tmds_pll_cntl ^= (1 << 22); + } } /* Read CRTC2 registers */ @@ -5218,7 +5533,7 @@ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONSaveCrtcRegisters(pScrn, save); RADEONSaveFPRegisters(pScrn, save); - if (info->Clone) { + if (info->MergedFB) { RADEONSaveCrtc2Registers(pScrn, save); RADEONSavePLL2Registers(pScrn, save); } @@ -5290,12 +5605,14 @@ static void RADEONRestore(ScrnInfoPtr pScrn) if (info->R300CGWorkaround) R300CGWorkaround(pScrn); OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset); OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype); + OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl); + OUTREG(RADEON_GRPH2_BUFFER_CNTL, restore->grph2_buffer_cntl); #if 0 /* M6 card has trouble restoring text mode for its CRT. * This is fixed elsewhere and will be removed in the future. */ - if ((xf86IsEntityShared(info->pEnt->index) || info->Clone) + if ((xf86IsEntityShared(info->pEnt->index) || info->MergedFB) && info->IsM6) OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); #endif @@ -5362,6 +5679,324 @@ static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; } +/* Calculate display buffer watermark to prevent buffer underflow */ +static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONInfoPtr info2 = NULL; + + DisplayModePtr mode1, mode2; + + CARD32 temp, data, mem_trcd, mem_trp, mem_tras, mem_trbs=0; + float mem_tcas; + int k1, c; + CARD32 MemTrcdExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrpExtMemCntl[4] = {1, 2, 3, 4}; + CARD32 MemTrasExtMemCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + CARD32 MemTrcdMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrpMemTimingCntl[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + CARD32 MemTrasMemTimingCntl[16] = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + float MemTcas[8] = {0, 1, 2, 3, 0, 1.5, 2.5, 0}; + float MemTcas2[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + float MemTrbs[8] = {1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5}; + + float mem_bw, peak_disp_bw; + float min_mem_eff = 0.8; + float sclk_eff, sclk_delay; + float mc_latency_mclk, mc_latency_sclk, cur_latency_mclk, cur_latency_sclk; + float disp_latency, disp_latency_overhead, disp_drain_rate, disp_drain_rate2; + float pix_clk, pix_clk2; /* in MHz */ + int cur_size = 16; /* in octawords */ + int critical_point, critical_point2; + int stop_req, max_stop_req; + float read_return_rate, time_disp1_drop_priority; + + if (pRADEONEnt->pSecondaryScrn) { + if (info->IsSecondary) return; + info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); + } else if (info->MergedFB) info2 = info; + + /* + * Determine if there is enough bandwidth for current display mode + */ + mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1); + + mode1 = info->CurrentLayout.mode; + if (info->MergedFB) { + mode1 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; + mode2 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; + } else if ((pRADEONEnt->HasSecondary) && info2) { + mode2 = info2->CurrentLayout.mode; + } else { + mode2 = NULL; + } + + pix_clk = mode1->Clock/1000.0; + if (mode2) + pix_clk2 = mode2->Clock/1000.0; + else + pix_clk2 = 0; + + peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); + if (info2) + peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); + + if (peak_disp_bw >= mem_bw * min_mem_eff) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "You may not have enough display bandwidth for current mode\n" + "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); + } + + /* CRTC1 + Set GRPH_BUFFER_CNTL register using h/w defined optimal values. + GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] + */ + stop_req = mode1->HDisplay * info->CurrentLayout.pixel_bytes / 16; + + /* setup Max GRPH_STOP_REQ default value */ + if ((info->ChipFamily == CHIP_FAMILY_RV100) || + (info->ChipFamily == CHIP_FAMILY_RV200) || + (info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280) || + (info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200) || + (info->ChipFamily == CHIP_FAMILY_RS300)) + max_stop_req = 0x5c; + else + max_stop_req = 0x7c; + if (stop_req > max_stop_req) + stop_req = max_stop_req; + + /* Get values from the EXT_MEM_CNTL register...converting its contents. */ + temp = INREG(RADEON_MEM_TIMING_CNTL); + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_trcd = MemTrcdExtMemCntl[(temp & 0x0c) >> 2]; + mem_trp = MemTrpExtMemCntl[ (temp & 0x03) >> 0]; + mem_tras = MemTrasExtMemCntl[(temp & 0x70) >> 4]; + } else { /* RV200 and later */ + mem_trcd = MemTrcdMemTimingCntl[(temp & 0x07) >> 0]; + mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8]; + mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12]; + } + + /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ + temp = INREG(RADEON_MEM_SDRAM_MODE_REG); + data = (temp & (7<<20)) >> 20; + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + mem_tcas = MemTcas [data]; + } else { + mem_tcas = MemTcas2 [data]; + } + + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { + + /* on the R300, Tcas is included in Trbs. + */ + temp = INREG(RADEON_MEM_CNTL); + data = (R300_MEM_NUM_CHANNELS_MASK & temp); + if (data == 2) { + if (R300_MEM_USE_CD_CH_ONLY & temp) { + temp = INREG(R300_MC_IND_INDEX); + temp &= ~R300_MC_IND_ADDR_MASK; + temp |= R300_MC_READ_CNTL_CD_mcind; + OUTREG(R300_MC_IND_INDEX, temp); + temp = INREG(R300_MC_IND_DATA); + data = (R300_MEM_RBS_POSITION_C_MASK & temp); + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + } else { + temp = INREG(R300_MC_READ_CNTL_AB); + data = (R300_MEM_RBS_POSITION_A_MASK & temp); + } + + mem_trbs = MemTrbs[data]; + mem_tcas += mem_trbs; + } + + if ((info->ChipFamily == CHIP_FAMILY_RV100) || info->IsIGP) { /* RV100, M6, IGPs */ + /* DDR64 SCLK_EFF = SCLK for analysis */ + sclk_eff = info->sclk; + } else { +#ifdef XF86DRI + if (info->directRenderingEnabled) + sclk_eff = info->sclk - (info->agpMode * 50.0 / 3.0); + else +#endif + sclk_eff = info->sclk; + } + + /* Find the memory controller latency for the display client. + */ + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350)) { + /*not enough for R350 ???*/ + /* + if (!mode2) sclk_delay = 150; + else { + if (info->RamWidth == 256) sclk_delay = 87; + else sclk_delay = 97; + } + */ + sclk_delay = 250; + } else { + if ((info->ChipFamily == CHIP_FAMILY_RV100) || + info->IsIGP) { + if (info->IsDDR) sclk_delay = 41; + else sclk_delay = 33; + } else { + if (info->RamWidth == 128) sclk_delay = 57; + else sclk_delay = 41; + } + } + + mc_latency_sclk = sclk_delay / sclk_eff; + + if (info->IsDDR) { + if (info->RamWidth == 32) { + k1 = 40; + c = 3; + } else { + k1 = 20; + c = 1; + } + } else { + k1 = 40; + c = 3; + } + mc_latency_mclk = ((2.0*mem_trcd + mem_tcas*c + 4.0*mem_tras + 4.0*mem_trp + k1) / + info->mclk) + (4.0 / sclk_eff); + + /* + HW cursor time assuming worst case of full size colour cursor. + */ + cur_latency_mclk = (mem_trp + MAX(mem_tras, (mem_trcd + 2*(cur_size - (info->IsDDR+1))))) / info->mclk; + cur_latency_sclk = cur_size / sclk_eff; + + /* + Find the total latency for the display data. + */ + disp_latency_overhead = 8.0 / info->sclk; + mc_latency_mclk = mc_latency_mclk + disp_latency_overhead + cur_latency_mclk; + mc_latency_sclk = mc_latency_sclk + disp_latency_overhead + cur_latency_sclk; + disp_latency = MAX(mc_latency_mclk, mc_latency_sclk); + + /* + Find the drain rate of the display buffer. + */ + disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); + if (info2) + disp_drain_rate2 = pix_clk2 / (16.0/info2->CurrentLayout.pixel_bytes); + else + disp_drain_rate2 = 0; + + /* + Find the critical point of the display buffer. + */ + critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5); + + /* ???? */ + /* + temp = (info->SavedReg.grph_buffer_cntl & RADEON_GRPH_CRITICAL_POINT_MASK) >> RADEON_GRPH_CRITICAL_POINT_SHIFT; + if (critical_point < temp) critical_point = temp; + */ + if (info->DispPriority == 2) { + if (mode2) { + /*??some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ + if (info->ChipFamily == CHIP_FAMILY_R300) + critical_point += 0x10; + else + critical_point = 0; + } + else + critical_point = 0; + } + + /* + The critical point should never be above max_stop_req-4. Setting + GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. + */ + if (max_stop_req - critical_point < 4) critical_point = 0; + + temp = info->SavedReg.grph_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + /* + Write the result into the register. + */ + OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", + info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); + + if (mode2) { + stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; + + if (stop_req > max_stop_req) stop_req = max_stop_req; + + temp = info->SavedReg.grph2_buffer_cntl; + temp &= ~(RADEON_GRPH_STOP_REQ_MASK); + temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); + temp &= ~(RADEON_GRPH_START_REQ_MASK); + if ((info->ChipFamily == CHIP_FAMILY_R350) && + (stop_req > 0x15)) { + stop_req -= 0x10; + } + temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); + temp |= RADEON_GRPH_BUFFER_SIZE; + temp &= ~(RADEON_GRPH_CRITICAL_CNTL | + RADEON_GRPH_CRITICAL_AT_SOF | + RADEON_GRPH_STOP_CNTL); + + if ((info->ChipFamily == CHIP_FAMILY_RS100) || + (info->ChipFamily == CHIP_FAMILY_RS200)) + critical_point2 = 0; + else { + read_return_rate = MIN(info->sclk, info->mclk*(info->RamWidth*(info->IsDDR+1)/128)); + time_disp1_drop_priority = critical_point / (read_return_rate - disp_drain_rate); + + critical_point2 = (CARD32)((disp_latency + time_disp1_drop_priority + + disp_latency) * disp_drain_rate2 + 0.5); + + if (info->DispPriority == 2) { + if (info->ChipFamily == CHIP_FAMILY_R300) + critical_point2 += 0x10; + else + critical_point2 = 0; + } + + if (max_stop_req - critical_point2 < 4) critical_point2 = 0; + + } + + OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | + (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); + + RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", + info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); + } +} + /* Define CRTC registers for requested video mode */ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, DisplayModePtr mode, RADEONInfoPtr info) @@ -5486,6 +6121,16 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8)); save->crtc_pitch |= save->crtc_pitch << 16; + + /* Some versions of BIOS setup CRTC_MORE_CNTL for a DFP, if we + have a CRT here, it should be cleared to avoild a blank screen. + */ + if (info->DisplayType == MT_CRT) + save->crtc_more_cntl = (info->SavedReg.crtc_more_cntl & + ~(RADEON_CRTC_H_CUTOFF_ACTIVE_EN | + RADEON_CRTC_V_CUTOFF_ACTIVE_EN)); + else + save->crtc_more_cntl = info->SavedReg.crtc_more_cntl; save->surface_cntl = 0; save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; @@ -5637,16 +6282,23 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, save->crtc2_offset = 0; save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); - + /* this should be right */ + if (info->MergedFB) { + save->crtc2_pitch = (((info->CRT2pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / + (pScrn->bitsPerPixel * 8)); + save->crtc2_pitch |= save->crtc2_pitch << 16; + } else { save->crtc2_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8)); save->crtc2_pitch |= save->crtc2_pitch << 16; + } save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); if ((info->DisplayType == MT_DFP && info->IsSecondary) || - info->CloneType == MT_DFP) { + info->MergeType == MT_DFP) { save->crtc2_gen_cntl = (RADEON_CRTC2_EN | (format << 8)); save->fp2_h_sync_strt_wid = save->crtc2_h_sync_strt_wid; save->fp2_v_sync_strt_wid = save->crtc2_v_sync_strt_wid; @@ -5674,16 +6326,8 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, /* FIXME: When there are two DFPs, the 2nd DFP is driven by the * external TMDS transmitter. It may have a problem at - * high dot clock for certain panels. Since we don't - * know how to control the external TMDS transmitter, not - * much we can do here. + * high dot clock for certain panels. */ -#if 0 - if (save->dot_clock_freq > 15000) - save->tmds_pll_cntl = 0xA3F; - else if(save->tmds_pll_cntl != 0xA3F) - save->tmds_pll_cntl = info->SavedReg.tmds_pll_cntl; -#endif /* If BIOS has not turned it on, we'll keep it on so that we'll * have a valid VGA screen even after X quits or VT is switched @@ -5810,16 +6454,6 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, save->lvds_gen_cntl = orig->lvds_gen_cntl; save->lvds_pll_cntl = orig->lvds_pll_cntl; - /* This is needed for some panel at high resolution (>=1600x1200) - */ - if ((save->dot_clock_freq > 15000) && - (info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) - save->tmds_pll_cntl = 0xA3F; - else - save->tmds_pll_cntl = orig->tmds_pll_cntl; - info->PanelOff = FALSE; /* This option is used to force the ONLY DEVICE in XFConfig to use * CRT port, instead of default DVI port. @@ -5828,8 +6462,9 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, info->PanelOff = TRUE; } + save->tmds_pll_cntl = orig->tmds_pll_cntl; save->tmds_transmitter_cntl= orig->tmds_transmitter_cntl; - if (info->PanelOff && info->Clone) { + if (info->PanelOff && info->MergedFB) { info->OverlayOnCRTC2 = TRUE; if (info->DisplayType == MT_LCD) { /* Turning off LVDS_ON seems to make panel white blooming. @@ -5847,7 +6482,7 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, /* BIOS will use this setting to reset displays upon lid close/open. * Here we let BIOS controls LCD, but the driver will control the external CRT. */ - if (info->Clone || pRADEONEnt->HasSecondary) + if (info->MergedFB || pRADEONEnt->HasSecondary) save->bios_5_scratch = 0x01020201; else save->bios_5_scratch = orig->bios_5_scratch; @@ -5856,13 +6491,28 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig, save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); } else if (info->DisplayType == MT_DFP) { - /* This is needed for some panel at high resolution (>=1600x1200) - */ - if ((save->dot_clock_freq > 15000) && - (info->ChipFamily != CHIP_FAMILY_R300) && - (info->ChipFamily != CHIP_FAMILY_R350) && - (info->ChipFamily != CHIP_FAMILY_RV350)) - save->tmds_pll_cntl = 0xA3F; + int i; + CARD32 tmp = orig->tmds_pll_cntl & 0xfffff; + for (i=0; i<4; i++) { + if (info->tmds_pll[i].freq == 0) break; + if (save->dot_clock_freq < info->tmds_pll[i].freq) { + tmp = info->tmds_pll[i].value ; + break; + } + } + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350) || + (info->ChipFamily == CHIP_FAMILY_RV350) || + (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (tmp & 0xfff00000) + save->tmds_pll_cntl = tmp; + else + save->tmds_pll_cntl = (orig->tmds_pll_cntl & 0xfff00000) | tmp; + } else save->tmds_pll_cntl = tmp; + + RADEONTRACE(("TMDS_PLL from %x to %x\n", + orig->tmds_pll_cntl, + save->tmds_pll_cntl)); save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLRST); if ((info->ChipFamily == CHIP_FAMILY_R300) || @@ -6070,6 +6720,23 @@ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, if (!RADEONInitCrtc2Registers(pScrn, save, mode, info)) return FALSE; RADEONInitPLL2Registers(save, &info->pll, dot_clock); + } else if (info->MergedFB) { + RADEONInitCommonRegisters(save, info); + if (!RADEONInitCrtcRegisters(pScrn, save, + ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, info)) + return FALSE; + dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT1)->Clock / 1000.0; + if (dot_clock) { + RADEONInitPLLRegisters(save, &info->pll, dot_clock); + } 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; + } + RADEONInitCrtc2Registers(pScrn, save, + ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info); + dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT2)->Clock / 1000.0; + RADEONInitPLL2Registers(save, &info->pll, dot_clock); } else { RADEONInitCommonRegisters(save, info); if (!RADEONInitCrtcRegisters(pScrn, save, mode, info)) @@ -6089,16 +6756,25 @@ static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, save->htotal_cntl = info->SavedReg.htotal_cntl; } - if (info->Clone && info->CurCloneMode) { - RADEONInitCrtc2Registers(pScrn, save, info->CurCloneMode, info); - dot_clock = info->CurCloneMode->Clock / 1000.0; - RADEONInitPLL2Registers(save, &info->pll, dot_clock); - } /* Not used for now: */ /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ } - RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); + /* make RMX work for mergedfb modes on the LCD */ + if (info->MergedFB) { + if ((info->MergeType == MT_LCD) || (info->MergeType == MT_DFP)) { + /* I suppose crtc2 could drive the FP as well... */ + RADEONInitFPRegisters(pScrn, &info->SavedReg, save, + ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info); + } + else { + RADEONInitFPRegisters(pScrn, &info->SavedReg, save, + ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, info); + } + } + else { + RADEONInitFPRegisters(pScrn, &info->SavedReg, save, mode, info); + } RADEONTRACE(("RADEONInit returns %p\n", save)); return TRUE; @@ -6117,6 +6793,10 @@ static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) RADEONUnblank(pScrn); info->CurrentLayout.mode = mode; + + if (info->DispPriority) + RADEONInitDispBandwidth(pScrn); + return TRUE; } @@ -6159,56 +6839,7 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); } else { info->IsSwitching = TRUE; - if (info->Clone && info->CloneModes) { - DisplayModePtr clone_mode = info->CloneModes; - - /* Try to match a mode on primary head - * FIXME: This may not be good if both heads don't have - * exactly the same list of mode. - */ - while (1) { - if ((clone_mode->HDisplay == mode->HDisplay) && - (clone_mode->VDisplay == mode->VDisplay) && - (!info->PanelOff)) { - info->CloneFrameX0 = (info->CurCloneMode->HDisplay + - info->CloneFrameX0 - - clone_mode->HDisplay - 1) / 2; - info->CloneFrameY0 = - (info->CurCloneMode->VDisplay + info->CloneFrameY0 - - clone_mode->VDisplay - 1) / 2; - info->CurCloneMode = clone_mode; - break; - } - - if (!clone_mode->next) { - info->CurCloneMode = info->CloneModes; - break; - } - - clone_mode = clone_mode->next; - } - } ret = RADEONModeInit(xf86Screens[scrnIndex], mode); - - if (info->CurCloneMode) { - if (info->CloneFrameX0 + info->CurCloneMode->HDisplay >= - pScrn->virtualX) - info->CloneFrameX0 = - pScrn->virtualX - info->CurCloneMode->HDisplay; - else if (info->CloneFrameX0 < 0) - info->CloneFrameX0 = 0; - - if (info->CloneFrameY0 + info->CurCloneMode->VDisplay >= - pScrn->virtualY) - info->CloneFrameY0 = - pScrn->virtualY - info->CurCloneMode->VDisplay; - else if (info->CloneFrameY0 < 0) - info->CloneFrameY0 = 0; - - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, - TRUE); - } - info->IsSwitching = FALSE; } @@ -6224,6 +6855,13 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #endif + /* Since RandR (indirectly) uses SwitchMode(), we need to + * update our Xinerama info here, too, in case of resizing + */ + if(info->MergedFB) { + RADEONUpdateXineramaScreenInfo(pScrn); + } + return ret; } @@ -6310,7 +6948,9 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) if (info->accelOn) info->accel->Sync(pScrn); - if (info->FBDev) { + if(info->MergedFB) { + RADEONAdjustFrameMerged(scrnIndex, x, y, flags); + } else if (info->FBDev) { fbdevHWAdjustFrame(scrnIndex, x, y, flags); } else { RADEONDoAdjustFrame(pScrn, x, y, FALSE); @@ -6363,9 +7003,6 @@ Bool RADEONEnterVT(int scrnIndex, int flags) #endif pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - if (info->CurCloneMode) { - RADEONDoAdjustFrame(pScrn, info->CloneFrameX0, info->CloneFrameY0, TRUE); - } return TRUE; } @@ -6447,9 +7084,44 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) void RADEONFreeScreen(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); RADEONTRACE(("RADEONFreeScreen\n")); + if(info->MergedFB) { + if(pScrn->modes) { + pScrn->currentMode = pScrn->modes; + do { + DisplayModePtr p = pScrn->currentMode->next; + if(pScrn->currentMode->Private) + xfree(pScrn->currentMode->Private); + xfree(pScrn->currentMode); + pScrn->currentMode = p; + } while(pScrn->currentMode != pScrn->modes); + } + pScrn->currentMode = info->CRT1CurrentMode; + pScrn->modes = info->CRT1Modes; + info->CRT1CurrentMode = NULL; + info->CRT1Modes = NULL; + + if(info->CRT2pScrn) { + if(info->CRT2pScrn->modes) { + while(info->CRT2pScrn->modes) + xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); + } + if(info->CRT2pScrn->monitor) { + if(info->CRT2pScrn->monitor->Modes) { + while(info->CRT2pScrn->monitor->Modes) + xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); + } + if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); + xfree(info->CRT2pScrn->monitor); + } + xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + } + } + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); RADEONFreeRec(pScrn); @@ -6487,7 +7159,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); } @@ -6500,7 +7172,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS, ~mask2); @@ -6517,7 +7189,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS, ~mask2); @@ -6532,7 +7204,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (info->IsSecondary) OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); else { - if (info->Clone) + if (info->MergedFB) OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); } @@ -6549,7 +7221,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, } } } else { - if ((info->Clone) && (info->CloneType == MT_DFP)) { + if ((info->MergedFB) && (info->MergeType == MT_DFP)) { OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_ON, ~RADEON_FP2_ON); if (info->ChipFamily >= CHIP_FAMILY_R200) { @@ -6578,7 +7250,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, } } } else { - if ((info->Clone) && (info->CloneType == MT_DFP)) { + if ((info->MergedFB) && (info->MergeType == MT_DFP)) { OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_ON); if (info->ChipFamily >= CHIP_FAMILY_R200) { @@ -6612,3 +7284,185 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, if (info->CPStarted) DRIUnlock(pScrn->pScreen); #endif } + +static void +RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + char *strptr; + char *default_hsync = "28-33"; + char *default_vrefresh = "43-72"; + Bool val; + Bool default_range = FALSE; + static const char *mybadparm = "\"%s\" is is not a valid parameter for option \"%s\"\n"; + + if (info->FBDev == TRUE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MergedFB does not work with Option UseFBDev, MergedFB mode is disabled\n"); + info->MergedFB = FALSE; + return; + } + + /* collect MergedFB options */ + info->MergedFB = TRUE; + info->UseRADEONXinerama = TRUE; + info->CRT2IsScrn0 = FALSE; + info->CRT2Position = radeonClone; + info->MergedFBXDPI = info->MergedFBYDPI = 0; + + if (info->MergeType == MT_NONE) { + info->MergedFB = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to detect secondary monitor, MergedFB/Clone mode disabled\n"); + } else if (!pRADEONEnt->MonInfo2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to detect secondary monitor DDC, default HSync and VRefresh used\n"); + default_range = TRUE; + } + + if (xf86GetOptValBool(info->Options, OPTION_MERGEDFB, &val)) { + if (val) { + info->MergedFB = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MergedFB mode forced on.\n"); + } else { + info->MergedFB = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MergedFB mode forced off.\n"); + } + } + + /* Do some MergedFB mode initialisation */ + if(info->MergedFB) { + info->CRT2pScrn = xalloc(sizeof(ScrnInfoRec)); + if(!info->CRT2pScrn) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for merged pScrn, MergedFB mode is disabled\n"); + info->MergedFB = FALSE; + } else { + memcpy(info->CRT2pScrn, pScrn, sizeof(ScrnInfoRec)); + } + } + if(info->MergedFB) { + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2POS); + if(strptr) { + if((!strcmp(strptr,"LeftOf")) || (!strcmp(strptr,"leftof"))) { + info->CRT2Position = radeonLeftOf; + info->CRT2IsScrn0 = TRUE; + } + else if((!strcmp(strptr,"RightOf")) || (!strcmp(strptr,"rightof"))) { + info->CRT2Position = radeonRightOf; + info->CRT2IsScrn0 = FALSE; + } + else if((!strcmp(strptr,"Above")) || (!strcmp(strptr,"above"))) { + info->CRT2Position = radeonAbove; + info->CRT2IsScrn0 = FALSE; + } + else if((!strcmp(strptr,"Below")) || (!strcmp(strptr,"below"))) { + info->CRT2Position = radeonBelow; + info->CRT2IsScrn0 = TRUE; + } + else if((!strcmp(strptr,"Clone")) || (!strcmp(strptr,"clone"))) { + info->CRT2Position = radeonClone; + /*info->CRT2IsScrn0 = FALSE; */ + info->CRT2IsScrn0 = TRUE; + } + else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid parameter for Option \"CRT2Position\"\n", strptr); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid parameters are \"RightOf\", \"LeftOf\", \"Above\", \"Below\", or \"Clone\"\n"); + } + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_METAMODES); + if(strptr) { + info->MetaModes = xalloc(strlen(strptr) + 1); + if(info->MetaModes) memcpy(info->MetaModes, strptr, strlen(strptr) + 1); + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2HSYNC); + if(strptr) { + info->CRT2HSync = xalloc(strlen(strptr) + 1); + if(info->CRT2HSync) memcpy(info->CRT2HSync, strptr, strlen(strptr) + 1); + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2VREFRESH); + if(strptr) { + info->CRT2VRefresh = xalloc(strlen(strptr) + 1); + if(info->CRT2VRefresh) memcpy(info->CRT2VRefresh, strptr, strlen(strptr) + 1); + } + + if(xf86GetOptValBool(info->Options, OPTION_NORADEONXINERAMA, &val)) { + if (val) + info->UseRADEONXinerama = FALSE; + } + if(info->UseRADEONXinerama) { + if(xf86GetOptValBool(info->Options, OPTION_CRT2ISSCRN0, &val)) { + if(val) info->CRT2IsScrn0 = TRUE; + else info->CRT2IsScrn0 = FALSE; + } + } + strptr = (char *)xf86GetOptValString(info->Options, OPTION_MERGEDDPI); + if(strptr) { + int val1 = 0, val2 = 0; + sscanf(strptr, "%d %d", &val1, &val2); + if(val1 && val2) { + info->MergedFBXDPI = val1; + info->MergedFBYDPI = val2; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, mybadparm, strptr, "MergedDPI"); + } + } + } + + if(info->MergedFB) { + /* fill in monitor */ + info->CRT2pScrn->monitor = xalloc(sizeof(MonRec)); + if(info->CRT2pScrn->monitor) { + DisplayModePtr tempm = NULL, currentm = NULL, newm = NULL; + memcpy(info->CRT2pScrn->monitor, pScrn->monitor, sizeof(MonRec)); + info->CRT2pScrn->monitor->DDC = NULL; + info->CRT2pScrn->monitor->Modes = NULL; + info->CRT2pScrn->monitor->id = "CRT2 Monitor"; + tempm = pScrn->monitor->Modes; + while(tempm) { + if(!(newm = xalloc(sizeof(DisplayModeRec)))) break; + memcpy(newm, tempm, sizeof(DisplayModeRec)); + if(!(newm->name = xalloc(strlen(tempm->name) + 1))) { + xfree(newm); + break; + } + strcpy(newm->name, tempm->name); + if(!info->CRT2pScrn->monitor->Modes) + info->CRT2pScrn->monitor->Modes = newm; + if(currentm) { + currentm->next = newm; + newm->prev = currentm; + } + currentm = newm; + tempm = tempm->next; + } + + /* xf86SetDDCproperties(info->CRT2pScrn, pRADEONEnt->MonInfo2); */ + info->CRT2pScrn->monitor->DDC = pRADEONEnt->MonInfo2; + if (default_range) { + RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, default_hsync, MAX_HSYNC); + RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, default_vrefresh, MAX_VREFRESH); + } + if(info->CRT2HSync) { + info->CRT2pScrn->monitor->nHsync = + RADEONStrToRanges(info->CRT2pScrn->monitor->hsync, info->CRT2HSync, MAX_HSYNC); + } + if(info->CRT2VRefresh) { + info->CRT2pScrn->monitor->nVrefresh = + RADEONStrToRanges(info->CRT2pScrn->monitor->vrefresh, info->CRT2VRefresh, MAX_VREFRESH); + } + + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate memory for CRT2 monitor, MergedFB mode disabled.\n"); + if(info->CRT2pScrn) xfree(info->CRT2pScrn); + info->CRT2pScrn = NULL; + info->MergedFB = FALSE; + } + } +} diff --git a/src/radeon_probe.c b/src/radeon_probe.c index 58a8a114..adb336ab 100644 --- a/src/radeon_probe.c +++ b/src/radeon_probe.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c,v 1.27 2003/07/02 17:31:30 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_probe.c,v 1.30 2003/10/07 22:47:12 martin Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -38,7 +38,6 @@ #include "atimodule.h" #include "ativersion.h" -#include "radeon_pci.h" #include "radeon_probe.h" #include "radeon_version.h" @@ -88,8 +87,8 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_RADEON_QE, "ATI Radeon QE (AGP)" }, { PCI_CHIP_RADEON_QF, "ATI Radeon QF (AGP)" }, { PCI_CHIP_RADEON_QG, "ATI Radeon QG (AGP)" }, - { PCI_CHIP_RV100_QY, "ATI Radeon VE/7000 QY (AGP)" }, - { PCI_CHIP_RV100_QZ, "ATI Radeon VE/7000 QZ (AGP)" }, + { PCI_CHIP_RV100_QY, "ATI Radeon VE/7000 QY (AGP/PCI)" }, + { PCI_CHIP_RV100_QZ, "ATI Radeon VE/7000 QZ (AGP/PCI)" }, { PCI_CHIP_RADEON_LW, "ATI Radeon Mobility M7 LW (AGP)" }, { PCI_CHIP_RADEON_LX, "ATI Mobility FireGL 7800 M7 LX (AGP)" }, { PCI_CHIP_RADEON_LY, "ATI Radeon Mobility M6 LY (AGP)" }, @@ -101,53 +100,53 @@ SymTabRec RADEONChipsets[] = { { PCI_CHIP_RS250_4237, "ATI Radeon 7000 IGP (A4+) 4237" }, { PCI_CHIP_RS250_4437, "ATI Radeon Mobility 7000 IGP 4437" }, { PCI_CHIP_R200_QH, "ATI FireGL 8700/8800 QH (AGP)" }, - { PCI_CHIP_R200_QI, "ATI Radeon 8500 QI (AGP)" }, - { PCI_CHIP_R200_QJ, "ATI Radeon 8500 QJ (AGP)" }, - { PCI_CHIP_R200_QK, "ATI Radeon 8500 QK (AGP)" }, { PCI_CHIP_R200_QL, "ATI Radeon 8500 QL (AGP)" }, { PCI_CHIP_R200_QM, "ATI Radeon 9100 QM (AGP)" }, - { PCI_CHIP_R200_QN, "ATI Radeon 8500 QN (AGP)" }, - { PCI_CHIP_R200_QO, "ATI Radeon 8500 QO (AGP)" }, - { PCI_CHIP_R200_Qh, "ATI Radeon 8500 Qh (AGP)" }, - { PCI_CHIP_R200_Qi, "ATI Radeon 8500 Qi (AGP)" }, - { PCI_CHIP_R200_Qj, "ATI Radeon 8500 Qj (AGP)" }, - { PCI_CHIP_R200_Qk, "ATI Radeon 8500 Qk (AGP)" }, - { PCI_CHIP_R200_Ql, "ATI Radeon 8500 Ql (AGP)" }, - { PCI_CHIP_R200_BB, "ATI Radeon 8500 BB (AGP)" }, - { PCI_CHIP_RV200_QW, "ATI Radeon 7500 QW (AGP)" }, - { PCI_CHIP_RV200_QX, "ATI Radeon 7500 QX (AGP)" }, - { PCI_CHIP_RV250_Id, "ATI Radeon 9000 Id (AGP)" }, - { PCI_CHIP_RV250_Ie, "ATI Radeon 9000 Ie (AGP)" }, - { PCI_CHIP_RV250_If, "ATI Radeon 9000 If (AGP)" }, - { PCI_CHIP_RV250_Ig, "ATI Radeon 9000 Ig (AGP)" }, - { PCI_CHIP_RV250_Ld, "ATI Radeon Mobility M9 Ld (AGP)" }, - { PCI_CHIP_RV250_Le, "ATI Radeon Mobility M9 Le (AGP)" }, - { PCI_CHIP_RV250_Lf, "ATI Radeon Mobility M9 Lf (AGP)" }, - { PCI_CHIP_RV250_Lg, "ATI Radeon Mobility M9 Lg (AGP)" }, - { PCI_CHIP_RS300_5834, "ATI Radeon 9000 IGP (A5) 5834" }, - { PCI_CHIP_RS300_5835, "ATI Radeon Mobility 9000 IGP (U3) 5835" }, - { PCI_CHIP_RV280_5960, "ATI Radeon 9200 5960 (AGP)" }, + { PCI_CHIP_R200_BB, "ATI Radeon 8500 AIW BB (AGP)" }, + { PCI_CHIP_R200_BC, "ATI Radeon 8500 AIW BC (AGP)" }, + { PCI_CHIP_RV200_QW, "ATI Radeon 7500 QW (AGP/PCI)" }, + { PCI_CHIP_RV200_QX, "ATI Radeon 7500 QX (AGP/PCI)" }, + { PCI_CHIP_RV250_If, "ATI Radeon 9000/PRO If (AGP/PCI)" }, + { PCI_CHIP_RV250_Ig, "ATI Radeon 9000 Ig (AGP/PCI)" }, + { PCI_CHIP_RV250_Ld, "ATI FireGL Mobility 9000 (M9) Ld (AGP)" }, + { PCI_CHIP_RV250_Lf, "ATI Radeon Mobility 9000 (M9) Lf (AGP)" }, + { PCI_CHIP_RV250_Lg, "ATI Radeon Mobility 9000 (M9) Lg (AGP)" }, + { PCI_CHIP_RS300_5834, "ATI Radeon 9100 IGP (A5) 5834" }, + { PCI_CHIP_RS300_5835, "ATI Radeon Mobility 9100 IGP (U3) 5835" }, + { PCI_CHIP_RV280_5960, "ATI Radeon 9200PRO 5960 (AGP)" }, { PCI_CHIP_RV280_5961, "ATI Radeon 9200 5961 (AGP)" }, { PCI_CHIP_RV280_5962, "ATI Radeon 9200 5962 (AGP)" }, - { PCI_CHIP_RV280_5963, "ATI Radeon 9200 5963 (AGP)" }, - { PCI_CHIP_RV280_5968, "ATI Radeon M9+ 5968 (AGP)" }, - { PCI_CHIP_RV280_5969, "ATI Radeon M9+ 5969 (AGP)" }, - { PCI_CHIP_RV280_596A, "ATI Radeon M9+ 596A (AGP)" }, - { PCI_CHIP_RV280_596B, "ATI Radeon M9+ 596B (AGP)" }, + { PCI_CHIP_RV280_5964, "ATI Radeon 9200SE 5964 (AGP)" }, + { PCI_CHIP_RV280_5C61, "ATI Radeon Mobility 9200 (M9+) 5C61 (AGP)" }, + { PCI_CHIP_RV280_5C63, "ATI Radeon Mobility 9200 (M9+) 5C63 (AGP)" }, { PCI_CHIP_R300_AD, "ATI Radeon 9500 AD (AGP)" }, { PCI_CHIP_R300_AE, "ATI Radeon 9500 AE (AGP)" }, - { PCI_CHIP_R300_AF, "ATI Radeon 9500 AF (AGP)" }, - { PCI_CHIP_R300_AG, "ATI FireGL Z1/X1 AG (AGP)" }, + { PCI_CHIP_R300_AF, "ATI Radeon 9600TX AF (AGP)" }, + { PCI_CHIP_R300_AG, "ATI FireGL Z1 AG (AGP)" }, { PCI_CHIP_R300_ND, "ATI Radeon 9700 Pro ND (AGP)" }, { PCI_CHIP_R300_NE, "ATI Radeon 9700/9500Pro NE (AGP)" }, { PCI_CHIP_R300_NF, "ATI Radeon 9700 NF (AGP)" }, { PCI_CHIP_R300_NG, "ATI FireGL X1 NG (AGP)" }, { PCI_CHIP_RV350_AP, "ATI Radeon 9600 AP (AGP)" }, - { PCI_CHIP_RV350_AR, "ATI Radeon 9600PRO AR (AGP)" }, - { PCI_CHIP_RV350_NP, "ATI Radeon Mobility M10 NP (AGP)" }, - { PCI_CHIP_R350_AK, "ATI FireGL (R350) AK (AGP)" }, - { PCI_CHIP_R350_NH, "ATI Radeon 9800 NH (AGP)" }, - { PCI_CHIP_R350_NK, "ATI FireGL (R350) NL (AGP)" }, + { PCI_CHIP_RV350_AQ, "ATI Radeon 9600SE AQ (AGP)" }, + { PCI_CHIP_RV360_AR, "ATI Radeon 9600XT AR (AGP)" }, + { PCI_CHIP_RV350_AS, "ATI Radeon 9600 AS (AGP)" }, + { PCI_CHIP_RV350_AT, "ATI FireGL T2 AT (AGP)" }, + { PCI_CHIP_RV350_AV, "ATI FireGL RV360 AV (AGP)" }, + { PCI_CHIP_RV350_NP, "ATI Radeon Mobility 9600 (M10) NP (AGP)" }, + { PCI_CHIP_RV350_NQ, "ATI Radeon Mobility 9600 (M10) NQ (AGP)" }, + { PCI_CHIP_RV350_NR, "ATI Radeon Mobility 9600 (M11) NR (AGP)" }, + { PCI_CHIP_RV350_NS, "ATI Radeon Mobility 9600 (M10) NS (AGP)" }, + { PCI_CHIP_RV350_NT, "ATI FireGL Mobility T2 (M10) NT (AGP)" }, + { PCI_CHIP_RV350_NV, "ATI FireGL Mobility T2 (M11) NV (AGP)" }, + { PCI_CHIP_R350_AH, "ATI Radeon 9800SE AH (AGP)" }, + { PCI_CHIP_R350_AI, "ATI Radeon 9800 AI (AGP)" }, + { PCI_CHIP_R350_AJ, "ATI Radeon 9800 AJ (AGP)" }, + { PCI_CHIP_R350_AK, "ATI FireGL X2 AK (AGP)" }, + { PCI_CHIP_R350_NH, "ATI Radeon 9800PRO NH (AGP)" }, + { PCI_CHIP_R350_NI, "ATI Radeon 9800 NI (AGP)" }, + { PCI_CHIP_R350_NK, "ATI FireGL X2 NK (AGP)" }, + { PCI_CHIP_R360_NJ, "ATI Radeon 9800XT NJ (AGP)" }, { -1, NULL } }; @@ -169,27 +168,15 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_RS250_4237, PCI_CHIP_RS250_4237, RES_SHARED_VGA }, { PCI_CHIP_RS250_4437, PCI_CHIP_RS250_4437, RES_SHARED_VGA }, { PCI_CHIP_R200_QH, PCI_CHIP_R200_QH, RES_SHARED_VGA }, - { PCI_CHIP_R200_QI, PCI_CHIP_R200_QI, RES_SHARED_VGA }, - { PCI_CHIP_R200_QJ, PCI_CHIP_R200_QJ, RES_SHARED_VGA }, - { PCI_CHIP_R200_QK, PCI_CHIP_R200_QK, RES_SHARED_VGA }, { PCI_CHIP_R200_QL, PCI_CHIP_R200_QL, RES_SHARED_VGA }, { PCI_CHIP_R200_QM, PCI_CHIP_R200_QM, RES_SHARED_VGA }, - { PCI_CHIP_R200_QN, PCI_CHIP_R200_QN, RES_SHARED_VGA }, - { PCI_CHIP_R200_QO, PCI_CHIP_R200_QO, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qh, PCI_CHIP_R200_Qh, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qi, PCI_CHIP_R200_Qi, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qj, PCI_CHIP_R200_Qj, RES_SHARED_VGA }, - { PCI_CHIP_R200_Qk, PCI_CHIP_R200_Qk, RES_SHARED_VGA }, - { PCI_CHIP_R200_Ql, PCI_CHIP_R200_Ql, RES_SHARED_VGA }, { PCI_CHIP_R200_BB, PCI_CHIP_R200_BB, RES_SHARED_VGA }, + { PCI_CHIP_R200_BC, PCI_CHIP_R200_BC, RES_SHARED_VGA }, { PCI_CHIP_RV200_QW, PCI_CHIP_RV200_QW, RES_SHARED_VGA }, { PCI_CHIP_RV200_QX, PCI_CHIP_RV200_QX, RES_SHARED_VGA }, - { PCI_CHIP_RV250_Id, PCI_CHIP_RV250_Id, RES_SHARED_VGA }, - { PCI_CHIP_RV250_Ie, PCI_CHIP_RV250_Ie, RES_SHARED_VGA }, { PCI_CHIP_RV250_If, PCI_CHIP_RV250_If, RES_SHARED_VGA }, { PCI_CHIP_RV250_Ig, PCI_CHIP_RV250_Ig, RES_SHARED_VGA }, { PCI_CHIP_RV250_Ld, PCI_CHIP_RV250_Ld, RES_SHARED_VGA }, - { PCI_CHIP_RV250_Le, PCI_CHIP_RV250_Le, RES_SHARED_VGA }, { PCI_CHIP_RV250_Lf, PCI_CHIP_RV250_Lf, RES_SHARED_VGA }, { PCI_CHIP_RV250_Lg, PCI_CHIP_RV250_Lg, RES_SHARED_VGA }, { PCI_CHIP_RS300_5834, PCI_CHIP_RS300_5834, RES_SHARED_VGA }, @@ -197,11 +184,9 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_RV280_5960, PCI_CHIP_RV280_5960, RES_SHARED_VGA }, { PCI_CHIP_RV280_5961, PCI_CHIP_RV280_5961, RES_SHARED_VGA }, { PCI_CHIP_RV280_5962, PCI_CHIP_RV280_5962, RES_SHARED_VGA }, - { PCI_CHIP_RV280_5963, PCI_CHIP_RV280_5963, RES_SHARED_VGA }, - { PCI_CHIP_RV280_5968, PCI_CHIP_RV280_5968, RES_SHARED_VGA }, - { PCI_CHIP_RV280_5969, PCI_CHIP_RV280_5969, RES_SHARED_VGA }, - { PCI_CHIP_RV280_596A, PCI_CHIP_RV280_596A, RES_SHARED_VGA }, - { PCI_CHIP_RV280_596B, PCI_CHIP_RV280_596A, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5964, PCI_CHIP_RV280_5964, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5C61, PCI_CHIP_RV280_5C61, RES_SHARED_VGA }, + { PCI_CHIP_RV280_5C63, PCI_CHIP_RV280_5C63, RES_SHARED_VGA }, { PCI_CHIP_R300_AD, PCI_CHIP_R300_AD, RES_SHARED_VGA }, { PCI_CHIP_R300_AE, PCI_CHIP_R300_AE, RES_SHARED_VGA }, { PCI_CHIP_R300_AF, PCI_CHIP_R300_AF, RES_SHARED_VGA }, @@ -211,11 +196,25 @@ PciChipsets RADEONPciChipsets[] = { { PCI_CHIP_R300_NF, PCI_CHIP_R300_NF, RES_SHARED_VGA }, { PCI_CHIP_R300_NG, PCI_CHIP_R300_NG, RES_SHARED_VGA }, { PCI_CHIP_RV350_AP, PCI_CHIP_RV350_AP, RES_SHARED_VGA }, - { PCI_CHIP_RV350_AR, PCI_CHIP_RV350_AR, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AQ, PCI_CHIP_RV350_AQ, RES_SHARED_VGA }, + { PCI_CHIP_RV360_AR, PCI_CHIP_RV360_AR, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AS, PCI_CHIP_RV350_AS, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AT, PCI_CHIP_RV350_AT, RES_SHARED_VGA }, + { PCI_CHIP_RV350_AV, PCI_CHIP_RV350_AV, RES_SHARED_VGA }, { PCI_CHIP_RV350_NP, PCI_CHIP_RV350_NP, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NQ, PCI_CHIP_RV350_NQ, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NR, PCI_CHIP_RV350_NR, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NS, PCI_CHIP_RV350_NS, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NT, PCI_CHIP_RV350_NT, RES_SHARED_VGA }, + { PCI_CHIP_RV350_NV, PCI_CHIP_RV350_NV, RES_SHARED_VGA }, + { PCI_CHIP_R350_AH, PCI_CHIP_R350_AH, RES_SHARED_VGA }, + { PCI_CHIP_R350_AI, PCI_CHIP_R350_AI, RES_SHARED_VGA }, + { PCI_CHIP_R350_AJ, PCI_CHIP_R350_AJ, RES_SHARED_VGA }, { PCI_CHIP_R350_AK, PCI_CHIP_R350_AK, RES_SHARED_VGA }, { PCI_CHIP_R350_NH, PCI_CHIP_R350_NH, RES_SHARED_VGA }, + { PCI_CHIP_R350_NI, PCI_CHIP_R350_NI, RES_SHARED_VGA }, { PCI_CHIP_R350_NK, PCI_CHIP_R350_NK, RES_SHARED_VGA }, + { PCI_CHIP_R360_NJ, PCI_CHIP_R360_NJ, RES_SHARED_VGA }, { -1, -1, RES_UNDEFINED } }; diff --git a/src/radeon_reg.h b/src/radeon_reg.h index 73b5da16..4bd4d14e 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.28 2003/07/02 17:31:30 martin Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.30 2003/10/07 22:47:12 martin Exp $ */ /* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. @@ -66,6 +66,8 @@ # define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) # define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) #define RADEON_AGP_COMMAND 0x0f60 /* PCI */ +#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ +# define RADEON_AGP_ENABLE (1<<8) #define RADEON_AGP_PLL_CNTL 0x000b /* PLL */ #define RADEON_AGP_STATUS 0x0f5c /* PCI */ # define RADEON_AGP_1X_MODE 0x01 @@ -233,9 +235,27 @@ #define RADEON_CRC_CMDFIFO_ADDR 0x0740 #define RADEON_CRC_CMDFIFO_DOUT 0x0744 #define RADEON_GRPH_BUFFER_CNTL 0x02f0 -# define GRPH_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH_START_REQ_MASK (0x7f) +# define RADEON_GRPH_START_REQ_SHIFT 0 +# define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH_STOP_REQ_SHIFT 8 +# define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH_BUFFER_SIZE (1<<29) +# define RADEON_GRPH_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH_STOP_CNTL (1<<31) #define RADEON_GRPH2_BUFFER_CNTL 0x03f0 -# define GRPH2_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH2_START_REQ_MASK (0x7f) +# define RADEON_GRPH2_START_REQ_SHIFT 0 +# define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8) +# define RADEON_GRPH2_STOP_REQ_SHIFT 8 +# define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16) +# define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16 +# define RADEON_GRPH2_CRITICAL_CNTL (1<<28) +# define RADEON_GRPH2_BUFFER_SIZE (1<<29) +# define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30) +# define RADEON_GRPH2_STOP_CNTL (1<<31) #define RADEON_CRTC_CRNT_FRAME 0x0214 #define RADEON_CRTC_EXT_CNTL 0x0054 # define RADEON_CRTC_VGA_XOVERSCAN (1 << 0) @@ -278,6 +298,7 @@ # define RADEON_CRTC2_VSYNC_DIS (1 << 29) #define RADEON_CRTC_MORE_CNTL 0x27c # define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) +# define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) #define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 #define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 # define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) @@ -754,6 +775,12 @@ #define RADEON_MEM_ADDR_CONFIG 0x0148 #define RADEON_MEM_BASE 0x0f10 /* PCI */ #define RADEON_MEM_CNTL 0x0140 +# define RADEON_MEM_NUM_CHANNELS_MASK 0x01 +# define RADEON_MEM_USE_B_CH_ONLY (1<<1) +# define RV100_HALF_MODE (1<<3) +# define R300_MEM_NUM_CHANNELS_MASK 0x03 +# define R300_MEM_USE_CD_CH_ONLY (1<<2) +#define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */ #define RADEON_MEM_INIT_LAT_TIMER 0x0154 #define RADEON_MEM_INTF_CNTL 0x014c #define RADEON_MEM_SDRAM_MODE_REG 0x0158 @@ -766,7 +793,13 @@ #define RADEON_MPLL_CNTL 0x000e /* PLL */ #define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */ #define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */ - +#define R300_MC_IND_INDEX 0x01f8 +# define R300_MC_IND_ADDR_MASK 0x3f +#define R300_MC_IND_DATA 0x01fc +#define R300_MC_READ_CNTL_AB 0x017c +# define R300_MEM_RBS_POSITION_A_MASK 0x03 +#define R300_MC_READ_CNTL_CD_mcind 0x24 +# define R300_MEM_RBS_POSITION_C_MASK 0x03 #define RADEON_N_VIF_COUNT 0x0248 diff --git a/src/radeon_sarea.h b/src/radeon_sarea.h index 95db1f37..556fca6f 100644 --- a/src/radeon_sarea.h +++ b/src/radeon_sarea.h @@ -195,7 +195,7 @@ typedef struct { unsigned int vc_format; /* The current cliprects, or a subset thereof */ - XF86DRIClipRectRec boxes[RADEON_NR_SAREA_CLIPRECTS]; + drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS]; unsigned int nbox; /* Counters for throttling of rendering clients */ diff --git a/src/radeon_video.c b/src/radeon_video.c index a7c20fd1..3f47e499 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -4,6 +4,7 @@ #include "radeon_macros.h" #include "radeon_probe.h" #include "radeon_reg.h" +#include "radeon_mergedfb.h" #include "xf86.h" #include "dixstruct.h" @@ -38,11 +39,13 @@ static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now); + #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer; static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity; static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults; +static Atom xvSwitchCRT; typedef struct { CARD32 transform_index; @@ -63,12 +66,14 @@ typedef struct { Time offTime; Time freeTime; Bool autopaint_colorkey; + Bool crt2; /* 0=CRT1, 1=CRT2 */ } RADEONPortPrivRec, *RADEONPortPrivPtr; #define GET_PORT_PRIVATE(pScrn) \ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + void RADEONInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -124,7 +129,7 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] = }; -#define NUM_ATTRIBUTES 9+3 +#define NUM_ATTRIBUTES 9+4 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { @@ -140,6 +145,7 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, + {XvSettable | XvGettable, 0, 1, "XV_SWITCHCRT"}, }; #define NUM_IMAGES 4 @@ -434,6 +440,7 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr pPriv; unsigned char *RADEONMMIO = info->MMIO; + CARD32 dot_clock; if(!(adapt = xf86XVAllocateVideoAdaptorRec(pScrn))) return NULL; @@ -460,16 +467,28 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) pPriv->hue = 0; pPriv->currentBuffer = 0; pPriv->autopaint_colorkey = TRUE; + if (info->OverlayOnCRTC2) + pPriv->crt2 = TRUE; + else + pPriv->crt2 = FALSE; /* * Unlike older Mach64 chips, RADEON has only two ECP settings: * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) * for higher clocks, sure makes life nicer */ - if(info->ModeReg.dot_clock_freq < 17500) - pPriv->ecp_div = 0; + + /* Figure out which head we are on */ + if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) + dot_clock = info->ModeReg.dot_clock_freq_2; else - pPriv->ecp_div = 1; + dot_clock = info->ModeReg.dot_clock_freq; + + if(dot_clock < 17500) + pPriv->ecp_div = 0; + else + pPriv->ecp_div = 1; + #if 0 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div); @@ -478,6 +497,11 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (pPriv->ecp_div << 8)); + /* I suspect we may need a usleep after writing to the PLL. if you play a video too soon + after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey + on the right edge video output. */ + + if ((info->ChipFamily == CHIP_FAMILY_RS100) || (info->ChipFamily == CHIP_FAMILY_RS200) || (info->ChipFamily == CHIP_FAMILY_RS300)) { @@ -540,6 +564,7 @@ RADEONSetupImageVideo(ScreenPtr pScreen) xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); + xvSwitchCRT = MAKE_ATOM("XV_SWITCHCRT"); RADEONResetVideo(pScrn); @@ -655,6 +680,15 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, RADEONSetColorKey (pScrn, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } + else if(attribute == xvSwitchCRT) + { + pPriv->crt2 = ClipValue (value, 0, 1); + pPriv->crt2 = value; + if (pPriv->crt2) + info->OverlayOnCRTC2 = TRUE; + else + info->OverlayOnCRTC2 = FALSE; + } else return BadMatch; @@ -705,6 +739,8 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->doubleBuffer ? 1 : 0; else if(attribute == xvColorKey) *value = pPriv->colorKey; + else if(attribute == xvSwitchCRT) + *value = pPriv->crt2 ? 1 : 0; else return BadMatch; @@ -854,28 +890,65 @@ RADEONDisplayVideo( int v_inc_shift; int y_mult; int x_off; + int y_off; CARD32 scaler_src; + CARD32 dot_clock; + DisplayModePtr overlay_mode; /* Unlike older Mach64 chips, RADEON has only two ECP settings: 0 for PIXCLK < 175Mhz, and 1 (divide by 2) for higher clocks, sure makes life nicer Here we need to find ecp_div again, as the user may have switched resolutions */ - if(info->ModeReg.dot_clock_freq < 17500) - ecp_div = 0; + + + /* Figure out which head we are on for dot clock */ + if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) + dot_clock = info->ModeReg.dot_clock_freq_2; + else + dot_clock = info->ModeReg.dot_clock_freq; + + if (dot_clock < 17500) + ecp_div = 0; else ecp_div = 1; - + OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8)); + /* I suspect we may need a usleep after writing to the PLL. if you play a video too soon + after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey + on the right edge video output. */ + v_inc_shift = 20; - if (pScrn->currentMode->Flags & V_INTERLACE) - v_inc_shift++; - if (pScrn->currentMode->Flags & V_DBLSCAN) - v_inc_shift--; - if (pScrn->currentMode->Flags & RADEON_USE_RMX) { - v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; + y_mult = 1; + + if (info->MergedFB) { + if (info->OverlayOnCRTC2) + overlay_mode = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; + else + overlay_mode = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; + if (overlay_mode->Flags & V_INTERLACE) + v_inc_shift++; + if (overlay_mode->Flags & V_DBLSCAN) { + v_inc_shift--; + y_mult = 2; + } + if (overlay_mode->Flags & RADEON_USE_RMX) { + v_inc = ((src_h * overlay_mode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; + } else { + v_inc = (src_h << v_inc_shift) / drw_h; + } } else { - v_inc = (src_h << v_inc_shift) / drw_h; + if (pScrn->currentMode->Flags & V_INTERLACE) + v_inc_shift++; + if (pScrn->currentMode->Flags & V_DBLSCAN) { + v_inc_shift--; + y_mult = 2; + } + if (pScrn->currentMode->Flags & RADEON_USE_RMX) { + v_inc = ((src_h * pScrn->currentMode->CrtcVDisplay / info->PanelYRes) << v_inc_shift) / drw_h; + } else { + v_inc = (src_h << v_inc_shift) / drw_h; + } } h_inc = ((src_w << (12 + ecp_div)) / drw_w); step_by = 1; @@ -917,10 +990,8 @@ RADEONDisplayVideo( OUTREG(RADEON_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); OUTREG(RADEON_OV0_STEP_BY, step_by | (step_by << 8)); - y_mult = 1; - if (pScrn->currentMode->Flags & V_DBLSCAN) - y_mult = 2; x_off = 8; + y_off = 0; if ((info->ChipFamily == CHIP_FAMILY_R300) || (info->ChipFamily == CHIP_FAMILY_R350) || @@ -928,34 +999,40 @@ RADEONDisplayVideo( (info->ChipFamily == CHIP_FAMILY_R200)) x_off = 0; + /* needed to make the overlay work on crtc1 in leftof and above modes */ + if (info->MergedFB) { + RADEONScrn2Rel srel = + ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; + overlay_mode = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; + if (srel == radeonLeftOf) { + x_off -= overlay_mode->CrtcHDisplay; + /* y_off -= pScrn->frameY0; */ + } + if (srel == radeonAbove) { + y_off -= overlay_mode->CrtcVDisplay; + /* x_off -= pScrn->frameX0; */ + } + } + /* Put the hardware overlay on CRTC2: * * Since one hardware overlay can not be displayed on two heads * at the same time, we might need to consider using software * rendering for the second head. */ - if ((info->Clone && info->OverlayOnCRTC2) || info->IsSecondary) { - x_off = 0; - OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 - + x_off - - info->CloneFrameX0 - + pScrn->frameX0) | - ((dstBox->y1*y_mult - - info->CloneFrameY0 - + pScrn->frameY0) << 16))); - OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2 - + x_off - - info->CloneFrameX0 - + pScrn->frameX0) | - ((dstBox->y2*y_mult - - info->CloneFrameY0 - + pScrn->frameY0) << 16))); - scaler_src = (1 << 14); + + if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) { + x_off = 0; + OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) | + ((dstBox->y1*y_mult) << 16))); + OUTREG(RADEON_OV1_Y_X_END, ((dstBox->x2 + x_off) | + ((dstBox->y2*y_mult) << 16))); + scaler_src = (1 << 14); } else { OUTREG(RADEON_OV0_Y_X_START, ((dstBox->x1 + x_off) | - ((dstBox->y1*y_mult) << 16))); + (((dstBox->y1*y_mult) + y_off) << 16))); OUTREG(RADEON_OV0_Y_X_END, ((dstBox->x2 + x_off) | - ((dstBox->y2*y_mult) << 16))); + (((dstBox->y2*y_mult) + y_off) << 16))); scaler_src = 0; } @@ -1064,14 +1141,24 @@ RADEONPutImage( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; + if (info->MergedFB) + RADEONChooseOverlayCRTC(pScrn, &dstBox); + if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; + if (info->MergedFB && info->OverlayOnCRTC2) { + dstBox.x1 -= info->CRT2pScrn->frameX0; + dstBox.x2 -= info->CRT2pScrn->frameX0; + dstBox.y1 -= info->CRT2pScrn->frameY0; + dstBox.y2 -= info->CRT2pScrn->frameY0; + } else { + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + } bpp = pScrn->bitsPerPixel >> 3; pitch = bpp * pScrn->displayWidth; @@ -1392,14 +1479,24 @@ RADEONDisplaySurface( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; + if (info->MergedFB) + RADEONChooseOverlayCRTC(pScrn, &dstBox); + if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, surface->width, surface->height)) return Success; - dstBox.x1 -= pScrn->frameX0; - dstBox.x2 -= pScrn->frameX0; - dstBox.y1 -= pScrn->frameY0; - dstBox.y2 -= pScrn->frameY0; + if (info->MergedFB && info->OverlayOnCRTC2) { + dstBox.x1 -= info->CRT2pScrn->frameX0; + dstBox.x2 -= info->CRT2pScrn->frameX0; + dstBox.y1 -= info->CRT2pScrn->frameY0; + dstBox.y2 -= info->CRT2pScrn->frameY0; + } else { + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + } RADEONResetVideo(pScrn); |