summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2004-06-16 09:25:58 +0000
committerEric Anholt <anholt@freebsd.org>2004-06-16 09:25:58 +0000
commitbea8085e04136b0ef513c17bb65c54069ec531e1 (patch)
tree8f9c7a4da5c6b8bb7db35eb8928d035d787157a0
parent7b588cda922992a8ee2d04853ba1533cf43592a3 (diff)
DRI trunk-20040613 importDRI-trunk-20040613
-rw-r--r--man/radeon.man237
-rw-r--r--src/atiaccel.c9
-rw-r--r--src/atichip.c34
-rw-r--r--src/atichip.h3
-rw-r--r--src/aticonfig.c43
-rw-r--r--src/aticonsole.c64
-rw-r--r--src/atiload.c57
-rw-r--r--src/atiload.h9
-rw-r--r--src/atilock.c9
-rw-r--r--src/atimach64.c54
-rw-r--r--src/atimach64accel.c177
-rw-r--r--src/atimach64cursor.c13
-rw-r--r--src/atimach64io.h68
-rw-r--r--src/atimisc.c10
-rw-r--r--src/atioption.c52
-rw-r--r--src/atioption.h14
-rw-r--r--src/atiprobe.c23
-rw-r--r--src/atiregs.h13
-rw-r--r--src/atiscreen.c286
-rw-r--r--src/atistruct.h51
-rw-r--r--src/r128.h18
-rw-r--r--src/r128_accel.c1
-rw-r--r--src/r128_dri.c31
-rw-r--r--src/r128_dri.h5
-rw-r--r--src/r128_driver.c2
-rw-r--r--src/r128_reg.h95
-rw-r--r--src/r128_sarea.h2
-rw-r--r--src/radeon.h110
-rw-r--r--src/radeon_accel.c14
-rw-r--r--src/radeon_accelfuncs.c13
-rw-r--r--src/radeon_common.h45
-rw-r--r--src/radeon_cursor.c89
-rw-r--r--src/radeon_dri.c77
-rw-r--r--src/radeon_dri.h12
-rw-r--r--src/radeon_dripriv.h4
-rw-r--r--src/radeon_driver.c2046
-rw-r--r--src/radeon_probe.c117
-rw-r--r--src/radeon_reg.h41
-rw-r--r--src/radeon_sarea.h2
-rw-r--r--src/radeon_video.c185
40 files changed, 3098 insertions, 1037 deletions
diff --git a/man/radeon.man b/man/radeon.man
index 6eeec44..0a11d53 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 626cb34..04edd30 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 f1fa25e..3c2b094 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 96d56ba..4cc30a0 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 3cad3e2..eb1f428 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 b025cdd..1d65df7 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 a7eebd1..9449205 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 a695579..3447825 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 b07744d..4ba06e5 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 89ee7c9..72f4a10 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 1202918..b7b8e07 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 8cd76db..6b55d42 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 e4db52a..d9da1d2 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 a84eac4..61801eb 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 6b84128..1bd90ec 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 2e629b8..6a907db 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 5e2c31b..8dc80ba 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 943dbad..b0c3d84 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 daf5a8c..ec784cb 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 8b98931..cbaf1b8 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))
diff --git a/src/r128.h b/src/r128.h
index deaf523..eac70f8 100644
--- a/src/r128.h
+++ b/src/r128.h
@@ -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 9329ad2..9887796 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 48765b1..ef2f9da 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 1339a45..c3ab275 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 d1fbd56..d990610 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 a0f21cf..98b89bf 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 6ffdb41..63f432b 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 bff12e4..8b2c8f9 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 8556cc2..0fabcbe 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 843fd6b..2dbd6b2 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 31e2a0b..bf11863 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 ff15cef..fe0d12b 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 2d36f87..f0af094 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 3f46719..4453fe6 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 5f01192..59f5458 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 4f56827..bfc50c4 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 58a8a11..adb336a 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 73b5da1..4bd4d14 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 95db1f3..556fca6 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 a7c20fd..3f47e49 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);