summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.r128.sgml1
-rw-r--r--man/radeon.man257
-rw-r--r--src/atiaccel.c9
-rw-r--r--src/atichip.c45
-rw-r--r--src/atichip.h9
-rw-r--r--src/aticonfig.c45
-rw-r--r--src/aticonsole.c68
-rw-r--r--src/atidri.c1508
-rw-r--r--src/atidri.h47
-rw-r--r--src/atidripriv.h59
-rw-r--r--src/atifillin.c24
-rw-r--r--src/atifillin.h22
-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.c179
-rw-r--r--src/atimach64cursor.c13
-rw-r--r--src/atimach64io.h68
-rw-r--r--src/atimisc.c12
-rw-r--r--src/atimodule.c9
-rw-r--r--src/atioption.c52
-rw-r--r--src/atioption.h14
-rw-r--r--src/atipreinit.c2
-rw-r--r--src/atiprobe.c40
-rw-r--r--src/atiregs.h13
-rw-r--r--src/atiscreen.c290
-rw-r--r--src/atistruct.h51
-rw-r--r--src/mach64_common.h131
-rw-r--r--src/mach64_dri.h126
-rw-r--r--src/mach64_sarea.h163
-rw-r--r--src/r128.h18
-rw-r--r--src/r128_accel.c1
-rw-r--r--src/r128_chipset.h54
-rw-r--r--src/r128_dri.c45
-rw-r--r--src/r128_dri.h5
-rw-r--r--src/r128_driver.c43
-rw-r--r--src/r128_misc.c2
-rw-r--r--src/r128_probe.c95
-rw-r--r--src/r128_probe.h7
-rw-r--r--src/r128_reg.h95
-rw-r--r--src/r128_sarea.h2
-rw-r--r--src/radeon.h152
-rw-r--r--src/radeon_accel.c45
-rw-r--r--src/radeon_accelfuncs.c67
-rw-r--r--src/radeon_bios.c514
-rw-r--r--src/radeon_chipset.h96
-rw-r--r--src/radeon_common.h34
-rw-r--r--src/radeon_cursor.c99
-rw-r--r--src/radeon_dri.c94
-rw-r--r--src/radeon_dri.h12
-rw-r--r--src/radeon_dripriv.h4
-rw-r--r--src/radeon_driver.c3242
-rw-r--r--src/radeon_macros.h8
-rw-r--r--src/radeon_mergedfb.c1562
-rw-r--r--src/radeon_mergedfb.h124
-rw-r--r--src/radeon_misc.c2
-rw-r--r--src/radeon_probe.c150
-rw-r--r--src/radeon_probe.h77
-rw-r--r--src/radeon_reg.h617
-rw-r--r--src/radeon_render.c992
-rw-r--r--src/radeon_sarea.h2
-rw-r--r--src/radeon_video.c779
63 files changed, 10417 insertions, 2008 deletions
diff --git a/README.r128.sgml b/README.r128.sgml
index d8532f25..8d7f4480 100644
--- a/README.r128.sgml
+++ b/README.r128.sgml
@@ -8,7 +8,6 @@
<date>13 June 2000
<ident>
-$Id$
</ident>
<toc>
diff --git a/man/radeon.man b/man/radeon.man
index c09ac46f..264068c7 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -29,16 +29,16 @@ 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, 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
@@ -47,7 +47,10 @@ Radeon 8500, 9100, FireGL 8800/8700
Radeon 9000PRO/9000, M9
.TP 12
.B RS300
-Radeon 9100 IGP (2D only)
+Radeon 9100 IGP
+.TP 12
+.B RS350
+Radeon 9200 IGP
.TP 12
.B RV280
Radeon 9200PRO/9200/9200SE, M9+
@@ -64,8 +67,20 @@ Radeon 9800XT (2d only)
.B RV350
Radeon 9600PRO/9600SE/9600, M10/M11, FireGL T2 (2D only)
.TP 12
-.B RV360
+.B RV360
Radeon 9600XT (2d only)
+.TP 12
+.B RV370
+Radeon X300, M22 (2d only)
+.TP 12
+.B RV380
+Radeon X600, M24 (2d only)
+.TP 12
+.B R420
+Radeon X800 (2d only)
+.TP 12
+.B R423
+Radeon X800 PCIE (2d only)
.SH CONFIGURATION DETAILS
Please refer to __xconfigfile__(__filemansuffix__) for general configuration
@@ -117,8 +132,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.
@@ -159,12 +174,6 @@ PCIE \-\- PCI Express (falls back to PCI at present)
.br
The default is
.B auto detect.
-.TP
-.BI "Option \*qForcePCIMode\*q \*q" boolean \*q
-Force to use PCI GART for DRI acceleration.
-This option is deprecated in favor of the
-.BI BusType
-option above and will be removed in the next release.
.TP
.BI "Option \*qDDCMode\*q \*q" boolean \*q
Force to use the modes queried from the connected monitor.
@@ -200,7 +209,7 @@ NONE \-\- Not connected
CRT \-\- Analog CRT monitor
.br
TMDS \-\- Desktop flat panel
-.br
+.br
LVDS \-\- Laptop flat panel
.br
This option can be used in following format:
@@ -218,9 +227,9 @@ Primary/Secondary head for dual\-head cards:
DVI port on DVI+VGA cards
.br
LCD output on laptops
-.br
-Internal TMDS prot on DVI+DVI cards
-.br
+.br
+Internal TMDS port on DVI+DVI cards
+.br
.B Secondary head:
.br
VGA port on DVI+VGA cards
@@ -231,32 +240,126 @@ 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.
-.br
-For example, Option "CloneMode" "1024x768"
+.TP
+.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
+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
-Set the horizontal sync range for the secondary monitor.
+.TP
+.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
+.TP
+.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.
@@ -267,18 +370,52 @@ Force hardware overlay to clone head.
The default value is
.B off.
.TP
+.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 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
for monitor detection. This is different from NoDDC option.
.br
The default value is
.B off.
-.TP
+.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
+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
@@ -286,9 +423,9 @@ For example, Option "PanelSize" "1400x1050"
.br
The default value is
.B none.
-.TP
+.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.
@@ -297,6 +434,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.
.TP
.BI "Option \*qForceMinDotClock\*q \*q" frequency \*q
@@ -309,6 +450,50 @@ You have been warned. The
.B frequency
parameter may be specified as a float value with standard suffixes like
"k", "kHz", "M", "MHz".
+.TP
+.BI "Option \*qRenderAccel\*q \*q" boolean \*q
+Enables or disables hardware Render acceleration. This driver does not
+support component alpha (subpixel) rendering. It is only supported on
+Radeon series up to and including 9200 (9500/9700 and newer
+unsupported). The default is to
+.B enable
+Render acceleration.
+.TP
+.BI "Option \*qSubPixelOrder\*q \*q" "string" \*q
+Force subpixel order to specified order.
+Subpixel order is used for subpixel decimation on flat panels.
+.br
+NONE \-\- No subpixel (CRT like displays)
+.br
+RGB \-\- in horizontal RGB order (most flat panels)
+.br
+BGR \-\- in horizontal BGR order (some flat panels)
+
+.br
+This option is intended to be used in following cases:
+.br
+1. The default subpixel order is incorrect for your panel.
+.br
+2. Enable subpixel decimation on analog panels.
+.br
+3. Adjust to one display type in dual-head clone mode setup.
+.br
+4. Get better performance with Render acceleration on
+digital panels (use NONE setting).
+.br
+The default is
+.B NONE
+for CRT,
+.B RGB
+for digital panels
+.TP
+.BI "Option \*qDynamicClocks\*q \*q" boolean \*q
+Enable dynamic clock scaling. The on-chip clocks will scale dynamically
+based on usage. This can help reduce heat and increase battery
+life by reducing power usage. Some users report reduced 3D preformance
+with this enabled. The default is
+.B off.
+.TP
.SH SEE ALSO
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
diff --git a/src/atiaccel.c b/src/atiaccel.c
index 3c358cf0..8b60fbda 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_DEVEL
+
+ /* 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 4d4861bc..3c369bf0 100644
--- a/src/atichip.c
+++ b/src/atichip.c
@@ -95,13 +95,18 @@ const char *ATIChipNames[] =
"ATI Radeon 8500/9100",
"ATI Radeon 9000",
"ATI Radeon Mobility M9",
- "ATI Radeon 9000 IGP",
+ "ATI Radeon 9100 IGP",
+ "ATI Radeon 9200 IGP",
"ATI Radeon 9200",
"ATI Radeon Mobility M9+",
"ATI Radeon 9700/9500",
"ATI Radeon 9600",
"ATI Radeon 9800",
"ATI Radeon 9800XT",
+ "ATI Radeon X300/M22",
+ "ATI Radeon X600/M24",
+ "ATI Radeon X800/M18",
+ "ATI Radeon X800 PCIE",
"ATI unknown Radeon",
"ATI Rage HDTV"
};
@@ -688,6 +693,10 @@ ATIChipID
case NewChipID('X', '5'):
return ATI_CHIP_RS300;
+ case NewChipID('x', '4'):
+ case NewChipID('x', '5'):
+ return ATI_CHIP_RS350;
+
case NewChipID('Y', '\''):
case NewChipID('Y', 'a'):
case NewChipID('Y', 'b'):
@@ -734,6 +743,40 @@ ATIChipID
case NewChipID('N', 'J'):
return ATI_CHIP_R360;
+ case NewChipID('[', '\''):
+ case NewChipID('[', 'b'):
+ case NewChipID('[', 'd'):
+ case NewChipID('[', 'e'):
+ case NewChipID('T', '\''):
+ case NewChipID('T', 'd'):
+ return ATI_CHIP_RV370;
+
+ case NewChipID('>', 'P'):
+ case NewChipID('>', 'T'):
+ case NewChipID('1', 'P'):
+ case NewChipID('1', 'T'):
+ return ATI_CHIP_RV380;
+
+ case NewChipID('J', 'H'):
+ case NewChipID('J', 'I'):
+ case NewChipID('J', 'J'):
+ case NewChipID('J', 'K'):
+ case NewChipID('J', 'L'):
+ case NewChipID('J', 'M'):
+ case NewChipID('J', 'N'):
+ case NewChipID('J', 'P'):
+ return ATI_CHIP_R420;
+
+ case NewChipID('U', 'H'):
+ case NewChipID('U', 'I'):
+ case NewChipID('U', 'J'):
+ case NewChipID('U', 'K'):
+ case NewChipID('U', 'Q'):
+ case NewChipID('U', 'R'):
+ case NewChipID('U', 'T'):
+ case NewChipID(']', 'W'):
+ return ATI_CHIP_R423;
+
case NewChipID('H', 'D'):
return ATI_CHIP_HDTV;
diff --git a/src/atichip.h b/src/atichip.h
index e47947d8..40841e14 100644
--- a/src/atichip.h
+++ b/src/atichip.h
@@ -97,13 +97,18 @@ typedef enum
ATI_CHIP_R200, /* R200 */
ATI_CHIP_RV250, /* RV250 */
ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */
- ATI_CHIP_RS300, /* Radoen 9000 IGP */
+ ATI_CHIP_RS300, /* Radoen 9100 IGP */
+ ATI_CHIP_RS350, /* Radoen 9200 IGP */
ATI_CHIP_RV280, /* RV250 */
ATI_CHIP_RADEONMOBILITY9PLUS, /* Radeon M9+ */
ATI_CHIP_R300, /* R300 */
- ATI_CHIP_RV350, /* RV350 */
+ ATI_CHIP_RV350, /* RV350/M10/M11 */
ATI_CHIP_R350, /* R350 */
ATI_CHIP_R360, /* R360 */
+ ATI_CHIP_RV370, /* RV370/M22 */
+ ATI_CHIP_RV380, /* RV380/M24 */
+ ATI_CHIP_R420, /* R420/M18 */
+ ATI_CHIP_R423, /* R423 */
ATI_CHIP_Radeon, /* Last among Radeon's */
ATI_CHIP_HDTV /* HDTV */
} ATIChipType;
diff --git a/src/aticonfig.c b/src/aticonfig.c
index cee9e180..40ee24f6 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.
*/
@@ -118,6 +123,17 @@ ATIProcessOptions
#endif /* AVOID_CPIO */
+#ifdef XF86DRI_DEVEL
+
+# 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_DEVEL */
+
# 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
@@ -164,6 +180,9 @@ ATIProcessOptions
}
Blend = PanelDisplay = TRUE;
+#ifdef XF86DRI_DEVEL
+ DMAMode = "mmio";
+#endif
xf86ProcessOptions(pScreenInfo->scrnIndex, pScreenInfo->options,
PublicOption);
@@ -210,6 +229,32 @@ ATIProcessOptions
else
pATI->OptionPanelDisplay = !CRTScreen;
+#ifdef XF86DRI_DEVEL
+
+ 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_DEVEL */
+
/* Validate and set cursor options */
pATI->Cursor = ATI_CURSOR_SOFTWARE;
if (SWCursor || !HWCursor)
diff --git a/src/aticonsole.c b/src/aticonsole.c
index 80062d4f..1b87a956 100644
--- a/src/aticonsole.c
+++ b/src/aticonsole.c
@@ -19,19 +19,33 @@
* 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"
+#ifdef XF86DRI_DEVEL
+#include "mach64_common.h"
+#endif
+
+#include "mach64_common.h"
+
+
+
#include "xf86.h"
/*
@@ -242,7 +256,28 @@ ATISwitchMode
if (pScreenInfo->vtSema)
{
pScreenInfo->currentMode = pMode;
+
+#ifdef XF86DRI_DEVEL
+
+ if (pATI->directRenderingEnabled)
+ {
+ DRILock(pScreenInfo->pScreen,0);
+ ATIDRIWaitForIdle(pATI);
+ }
+
+#endif /* XF86DRI_DEVEL */
+
ATIModeSet(pScreenInfo, pATI, &pATI->NewHW);
+
+#ifdef XF86DRI_DEVEL
+
+ if (pATI->directRenderingEnabled)
+ {
+ DRIUnlock(pScreenInfo->pScreen);
+ }
+
+#endif /* XF86DRI_DEVEL */
+
}
SetTimeSinceLastInputEvent();
@@ -274,7 +309,19 @@ ATIEnterVT
/* The rest of this isn't needed for shadowfb */
if (pATI->OptionShadowFB)
+ {
+
+#ifdef XF86DRI_DEVEL
+
+ if (pATI->directRenderingEnabled)
+ {
+ DRIUnlock(pScreen);
+ }
+
+#endif /* XF86DRI_DEVEL */
+
return TRUE;
+ }
#ifndef AVOID_CPIO
@@ -299,6 +346,15 @@ ATIEnterVT
pScreenPixmap->devPrivate.ptr = NULL;
}
+#ifdef XF86DRI_DEVEL
+
+ if (pATI->directRenderingEnabled)
+ {
+ DRIUnlock(pScreen);
+ }
+
+#endif /* XF86DRI_DEVEL */
+
return Entered;
}
@@ -316,6 +372,18 @@ ATILeaveVT
)
{
ScrnInfoPtr pScreenInfo = xf86Screens[iScreen];
+ ScreenPtr pScreen = pScreenInfo->pScreen;
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+#ifdef XF86DRI_DEVEL
+
+ if (pATI->directRenderingEnabled)
+ {
+ DRILock(pScreen,0);
+ ATIDRIWaitForIdle(pATI);
+ }
+
+#endif /* XF86DRI_DEVEL */
ATILeaveGraphics(pScreenInfo, ATIPTR(pScreenInfo));
}
diff --git a/src/atidri.c b/src/atidri.c
new file mode 100644
index 00000000..d5e1c898
--- /dev/null
+++ b/src/atidri.c
@@ -0,0 +1,1508 @@
+/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * Copyright 2000 Gareth Hughes
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * GARETH HUGHES 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.
+ */
+
+/*
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ * Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+/* Driver data structures */
+#include "ati.h"
+#include "atibus.h"
+#include "atidri.h"
+#include "atiregs.h"
+#include "atistruct.h"
+#include "ativersion.h"
+
+#include "atimach64io.h"
+#include "mach64_dri.h"
+#include "mach64_common.h"
+#include "mach64_sarea.h"
+
+/* X and server generic header files */
+#include "xf86.h"
+#include "windowstr.h"
+
+/* GLX/DRI/DRM definitions */
+#define _XF86DRI_SERVER_
+#include "GL/glxtokens.h"
+#include "sarea.h"
+
+static char ATIKernelDriverName[] = "mach64";
+static char ATIClientDriverName[] = "mach64";
+
+/* Initialize the visual configs that are supported by the hardware.
+ * These are combined with the visual configs that the indirect
+ * rendering core supports, and the intersection is exported to the
+ * client.
+ */
+static Bool ATIInitVisualConfigs( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ int numConfigs = 0;
+ __GLXvisualConfig *pConfigs = NULL;
+ ATIConfigPrivPtr pATIConfigs = NULL;
+ ATIConfigPrivPtr *pATIConfigPtrs = NULL;
+ int i, accum, stencil, db;
+
+ switch ( pATI->bitsPerPixel ) {
+ case 8: /* 8bpp mode is not support */
+ case 15: /* FIXME */
+ case 24: /* FIXME */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] ATIInitVisualConfigs failed (%d bpp not supported). "
+ "Disabling DRI.\n", pATI->bitsPerPixel);
+ return FALSE;
+
+#define ATI_USE_ACCUM 1
+#define ATI_USE_STENCIL 1
+
+ case 16:
+
+ if ( pATI->depth != 16) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] ATIInitVisualConfigs failed (depth %d at 16 bpp not supported). "
+ "Disabling DRI.\n", pATI->depth);
+ return FALSE;
+ }
+
+ numConfigs = 1;
+ if ( ATI_USE_ACCUM ) numConfigs *= 2;
+ if ( ATI_USE_STENCIL ) numConfigs *= 2;
+ numConfigs *= 2; /* single- and double-buffered */
+
+ pConfigs = (__GLXvisualConfig*)
+ xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
+ if ( !pConfigs ) {
+ return FALSE;
+ }
+ pATIConfigs = (ATIConfigPrivPtr)
+ xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
+ if ( !pATIConfigs ) {
+ xfree( pConfigs );
+ return FALSE;
+ }
+ pATIConfigPtrs = (ATIConfigPrivPtr*)
+ xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
+ if ( !pATIConfigPtrs ) {
+ xfree( pConfigs );
+ xfree( pATIConfigs );
+ return FALSE;
+ }
+
+ i = 0;
+ for (db = 0; db <= 1; db++) {
+ for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
+ for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
+ pATIConfigPtrs[i] = &pATIConfigs[i];
+
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 5;
+ pConfigs[i].greenSize = 6;
+ pConfigs[i].blueSize = 5;
+ pConfigs[i].alphaSize = 0;
+ pConfigs[i].redMask = 0x0000F800;
+ pConfigs[i].greenMask = 0x000007E0;
+ pConfigs[i].blueMask = 0x0000001F;
+ pConfigs[i].alphaMask = 0x00000000;
+ if ( accum ) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 16;
+ pConfigs[i].depthSize = 16;
+ if ( stencil ) { /* Simulated in software */
+ pConfigs[i].stencilSize = 8;
+ } else {
+ pConfigs[i].stencilSize = 0;
+ }
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if ( accum || stencil ) {
+ pConfigs[i].visualRating = GLX_SLOW_CONFIG;
+ } else {
+ pConfigs[i].visualRating = GLX_NONE;
+ }
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ break;
+
+ case 32:
+ numConfigs = 1;
+ if ( ATI_USE_ACCUM ) numConfigs *= 2;
+ if ( ATI_USE_STENCIL ) numConfigs *= 2;
+ numConfigs *= 2; /* single- and double-buffered */
+
+ pConfigs = (__GLXvisualConfig*)
+ xnfcalloc( sizeof(__GLXvisualConfig), numConfigs );
+ if ( !pConfigs ) {
+ return FALSE;
+ }
+ pATIConfigs = (ATIConfigPrivPtr)
+ xnfcalloc( sizeof(ATIConfigPrivRec), numConfigs );
+ if ( !pATIConfigs ) {
+ xfree( pConfigs );
+ return FALSE;
+ }
+ pATIConfigPtrs = (ATIConfigPrivPtr*)
+ xnfcalloc( sizeof(ATIConfigPrivPtr), numConfigs );
+ if ( !pATIConfigPtrs ) {
+ xfree( pConfigs );
+ xfree( pATIConfigs );
+ return FALSE;
+ }
+
+ i = 0;
+ for (db = 0; db <= 1; db++) {
+ for ( accum = 0 ; accum <= ATI_USE_ACCUM ; accum++ ) {
+ for ( stencil = 0 ; stencil <= ATI_USE_STENCIL ; stencil++ ) {
+ pATIConfigPtrs[i] = &pATIConfigs[i];
+
+ pConfigs[i].vid = -1;
+ pConfigs[i].class = -1;
+ pConfigs[i].rgba = TRUE;
+ pConfigs[i].redSize = 8;
+ pConfigs[i].greenSize = 8;
+ pConfigs[i].blueSize = 8;
+ pConfigs[i].alphaSize = 0;
+ pConfigs[i].redMask = 0x00FF0000;
+ pConfigs[i].greenMask = 0x0000FF00;
+ pConfigs[i].blueMask = 0x000000FF;
+ pConfigs[i].alphaMask = 0x00000000;
+ if ( accum ) { /* Simulated in software */
+ pConfigs[i].accumRedSize = 16;
+ pConfigs[i].accumGreenSize = 16;
+ pConfigs[i].accumBlueSize = 16;
+ pConfigs[i].accumAlphaSize = 0;
+ } else {
+ pConfigs[i].accumRedSize = 0;
+ pConfigs[i].accumGreenSize = 0;
+ pConfigs[i].accumBlueSize = 0;
+ pConfigs[i].accumAlphaSize = 0;
+ }
+ pConfigs[i].doubleBuffer = db ? TRUE : FALSE;
+ pConfigs[i].stereo = FALSE;
+ pConfigs[i].bufferSize = 24;
+ if ( stencil ) { /* Simulated in software */
+ pConfigs[i].depthSize = 16;
+ pConfigs[i].stencilSize = 8;
+ } else {
+ pConfigs[i].depthSize = 16;
+ pConfigs[i].stencilSize = 0;
+ }
+ pConfigs[i].auxBuffers = 0;
+ pConfigs[i].level = 0;
+ if ( accum || stencil ) {
+ pConfigs[i].visualRating = GLX_SLOW_CONFIG;
+ } else {
+ pConfigs[i].visualRating = GLX_NONE;
+ }
+ pConfigs[i].transparentPixel = GLX_NONE;
+ pConfigs[i].transparentRed = 0;
+ pConfigs[i].transparentGreen = 0;
+ pConfigs[i].transparentBlue = 0;
+ pConfigs[i].transparentAlpha = 0;
+ pConfigs[i].transparentIndex = 0;
+ i++;
+ }
+ }
+ }
+ break;
+ }
+
+ pATI->numVisualConfigs = numConfigs;
+ pATI->pVisualConfigs = pConfigs;
+ pATI->pVisualConfigsPriv = pATIConfigs;
+ GlxSetVisualConfigs( numConfigs, pConfigs, (void**)pATIConfigPtrs );
+ return TRUE;
+}
+
+/* Create the ATI-specific context information */
+static Bool ATICreateContext( ScreenPtr pScreen, VisualPtr visual,
+ drm_context_t hwContext, void *pVisualConfigPriv,
+ DRIContextType contextStore )
+{
+ /* Nothing yet */
+ return TRUE;
+}
+
+/* Destroy the ATI-specific context information */
+static void ATIDestroyContext( ScreenPtr pScreen, drm_context_t hwContext,
+ DRIContextType contextStore )
+{
+ /* Nothing yet */
+}
+
+/* Called when the X server is woken up to allow the last client's
+ * context to be saved and the X server's context to be loaded.
+ * The client detects when it's context is not currently loaded and
+ * then loads it itself. The X server's context is loaded in the
+ * XAA Sync callback if NeedDRISync is set.
+ */
+static void ATIEnterServer( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if ( pATI->directRenderingEnabled && pATI->pXAAInfo ) {
+ pATI->pXAAInfo->NeedToSync = TRUE;
+ pATI->NeedDRISync = TRUE;
+ }
+}
+
+/* Called when the X server goes to sleep to allow the X server's
+ * context to be saved and the last client's context to be loaded.
+ * The client detects when it's context is not currently loaded and
+ * then loads it itself. The X server keeps track of it's own state.
+ */
+static void ATILeaveServer( ScreenPtr pScreen )
+{
+ /* Nothing yet */
+}
+
+/* Contexts can be swapped by the X server if necessary. This callback
+ * is currently only used to perform any functions necessary when
+ * entering or leaving the X server, and in the future might not be
+ * necessary.
+ */
+static void ATIDRISwapContext( ScreenPtr pScreen,
+ DRISyncType syncType,
+ DRIContextType oldContextType,
+ void *oldContext,
+ DRIContextType newContextType,
+ void *newContext )
+{
+ if ( ( syncType == DRI_3D_SYNC ) && ( oldContextType == DRI_2D_CONTEXT ) &&
+ ( newContextType == DRI_2D_CONTEXT ) ) {
+ /* Entering from Wakeup */
+ ATIEnterServer( pScreen );
+ }
+ if ( ( syncType == DRI_2D_SYNC ) && ( oldContextType == DRI_NO_CONTEXT ) &&
+ ( newContextType == DRI_2D_CONTEXT ) ) {
+ /* Exiting from Block Handler */
+ ATILeaveServer( pScreen );
+ }
+}
+
+static void ATIDRITransitionTo2d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if (pATI->backArea) {
+ xf86FreeOffscreenArea(pATI->backArea);
+ pATI->backArea = NULL;
+ }
+ if (pATI->depthTexArea) {
+ xf86FreeOffscreenArea(pATI->depthTexArea);
+ pATI->depthTexArea = NULL;
+ }
+ pATI->have3DWindows = FALSE;
+}
+
+static void ATIDRITransitionTo3d(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ FBAreaPtr fbArea;
+ int width, height;
+
+ xf86PurgeUnlockedOffscreenAreas(pScreen);
+
+ xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0);
+
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "Largest offscreen area available: %d x %d\n",
+ width, height);
+
+ fbArea = xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
+ height - pATI->depthTexLines -
+ pATI->backLines,
+ pScreenInfo->displayWidth, NULL, NULL, NULL);
+
+ if (!fbArea)
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve placeholder "
+ "offscreen area, you might experience screen corruption\n");
+
+ if (!pATI->backArea) {
+ pATI->backArea =
+ xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
+ pATI->backLines,
+ pScreenInfo->displayWidth,
+ NULL, NULL, NULL);
+ }
+ if (!pATI->backArea)
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
+ "for back buffer, you might experience screen corruption\n");
+
+ if (!pATI->depthTexArea) {
+ pATI->depthTexArea =
+ xf86AllocateOffscreenArea(pScreen, pScreenInfo->displayWidth,
+ pATI->depthTexLines,
+ pScreenInfo->displayWidth,
+ NULL, NULL, NULL);
+ }
+ if (!pATI->depthTexArea)
+ xf86DrvMsg(pScreen->myNum, X_ERROR, "Unable to reserve offscreen area "
+ "for depth buffer and textures, you might experience screen corruption\n");
+
+ if (fbArea)
+ xf86FreeOffscreenArea(fbArea);
+
+ pATI->have3DWindows = TRUE;
+}
+
+/* Initialize the state of the back and depth buffers. */
+static void ATIDRIInitBuffers( WindowPtr pWin, RegionPtr prgn, CARD32 indx )
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+ XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
+ BoxPtr pbox, pboxSave;
+ int nbox, nboxSave;
+ int depth;
+
+ depth = 0x0000ffff;
+
+ if (!pXAAInfo)
+ return;
+
+ if (!pXAAInfo->SetupForSolidFill)
+ return;
+
+ /* FIXME: Only initialize the back and depth buffers for contexts
+ that request them */
+
+ /* FIXME: Use drm clear? (see Radeon driver) */
+
+ pboxSave = pbox = REGION_RECTS(prgn);
+ nboxSave = nbox = REGION_NUM_RECTS(prgn);
+
+ (*pXAAInfo->SetupForSolidFill)(pScreenInfo, 0, GXcopy, (CARD32)(-1));
+ for (; nbox; nbox--, pbox++) {
+ (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
+ pbox->x1 + pATIDRIServer->fbX,
+ pbox->y1 + pATIDRIServer->fbY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
+ pbox->x1 + pATIDRIServer->backX,
+ pbox->y1 + pATIDRIServer->backY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+ }
+
+ pbox = pboxSave;
+ nbox = nboxSave;
+
+ (*pXAAInfo->SetupForSolidFill)(pScreenInfo, depth, GXcopy, (CARD32)(-1));
+ for (; nbox; nbox--, pbox++)
+ (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo,
+ pbox->x1 + pATIDRIServer->depthX,
+ pbox->y1 + pATIDRIServer->depthY,
+ pbox->x2 - pbox->x1,
+ pbox->y2 - pbox->y1);
+
+ pXAAInfo->NeedToSync = TRUE;
+}
+
+/* Copy the back and depth buffers when the X server moves a window.
+ *
+ * Note: this function was copied from the Radeon driver...
+ *
+ * This routine is a modified form of XAADoBitBlt with the calls to
+ * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source
+ * instead of destination. My origin is upside down so the ydir cases
+ * are reversed.
+ */
+static void ATIDRIMoveBuffers( WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc, CARD32 indx )
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
+
+ int backOffsetPitch = (((pATI->pDRIServerInfo->backPitch/8) << 22) |
+ (pATI->pDRIServerInfo->backOffset >> 3));
+#if 0
+ int depthOffsetPitch = (((pATI->pDRIServerInfo->depthPitch/8) << 22) |
+ (pATI->pDRIServerInfo->depthOffset >> 3));
+#endif
+ BoxPtr pboxTmp, pboxNext, pboxBase;
+ DDXPointPtr pptTmp;
+ int xdir, ydir;
+
+ int screenwidth = pScreenInfo->virtualX;
+ int screenheight = pScreenInfo->virtualY;
+
+ BoxPtr pbox = REGION_RECTS(prgnSrc);
+ int nbox = REGION_NUM_RECTS(prgnSrc);
+
+ BoxPtr pboxNew1 = NULL;
+ BoxPtr pboxNew2 = NULL;
+ DDXPointPtr pptNew1 = NULL;
+ DDXPointPtr pptNew2 = NULL;
+ DDXPointPtr pptSrc = &ptOldOrg;
+
+ int dx = pWin->drawable.x - ptOldOrg.x;
+ int dy = pWin->drawable.y - ptOldOrg.y;
+
+ if (!pXAAInfo)
+ return;
+
+ if (!pXAAInfo->SetupForScreenToScreenCopy)
+ return;
+
+ /* FIXME: Only move the back and depth buffers for contexts
+ * that request them.
+ */
+
+ /* If the copy will overlap in Y, reverse the order */
+ if (dy > 0) {
+ ydir = -1;
+
+ if (nbox > 1) {
+ /* Keep ordering in each band, reverse order of bands */
+ pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
+ if (!pboxNew1) return;
+ pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
+ if (!pptNew1) {
+ DEALLOCATE_LOCAL(pboxNew1);
+ return;
+ }
+ pboxBase = pboxNext = pbox+nbox-1;
+ while (pboxBase >= pbox) {
+ while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
+ pboxNext--;
+ pboxTmp = pboxNext+1;
+ pptTmp = pptSrc + (pboxTmp - pbox);
+ while (pboxTmp <= pboxBase) {
+ *pboxNew1++ = *pboxTmp++;
+ *pptNew1++ = *pptTmp++;
+ }
+ pboxBase = pboxNext;
+ }
+ pboxNew1 -= nbox;
+ pbox = pboxNew1;
+ pptNew1 -= nbox;
+ pptSrc = pptNew1;
+ }
+ } else {
+ /* No changes required */
+ ydir = 1;
+ }
+
+ /* If the regions will overlap in X, reverse the order */
+ if (dx > 0) {
+ xdir = -1;
+
+ if (nbox > 1) {
+ /* reverse order of rects in each band */
+ pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec)*nbox);
+ pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec)*nbox);
+ if (!pboxNew2 || !pptNew2) {
+ DEALLOCATE_LOCAL(pptNew2);
+ DEALLOCATE_LOCAL(pboxNew2);
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(pboxNew1);
+ return;
+ }
+ pboxBase = pboxNext = pbox;
+ while (pboxBase < pbox+nbox) {
+ while ((pboxNext < pbox+nbox)
+ && (pboxNext->y1 == pboxBase->y1))
+ pboxNext++;
+ pboxTmp = pboxNext;
+ pptTmp = pptSrc + (pboxTmp - pbox);
+ while (pboxTmp != pboxBase) {
+ *pboxNew2++ = *--pboxTmp;
+ *pptNew2++ = *--pptTmp;
+ }
+ pboxBase = pboxNext;
+ }
+ pboxNew2 -= nbox;
+ pbox = pboxNew2;
+ pptNew2 -= nbox;
+ pptSrc = pptNew2;
+ }
+ } else {
+ /* No changes are needed */
+ xdir = 1;
+ }
+
+ (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo, xdir, ydir, GXcopy,
+ (CARD32)(-1), -1);
+
+ for (; nbox-- ; pbox++) {
+ int xa = pbox->x1;
+ int ya = pbox->y1;
+ int destx = xa + dx;
+ int desty = ya + dy;
+ int w = pbox->x2 - xa + 1;
+ int h = pbox->y2 - ya + 1;
+
+ if (destx < 0) xa -= destx, w += destx, destx = 0;
+ if (desty < 0) ya -= desty, h += desty, desty = 0;
+ if (destx + w > screenwidth) w = screenwidth - destx;
+ if (desty + h > screenheight) h = screenheight - desty;
+
+ if (w <= 0) continue;
+ if (h <= 0) continue;
+
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(SRC_OFF_PITCH, backOffsetPitch);
+ outf(DST_OFF_PITCH, backOffsetPitch);
+
+ (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
+ xa, ya,
+ destx, desty,
+ w, h);
+#if 0
+ /* FIXME: Move depth buffers? */
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(SRC_OFF_PITCH, depthOffsetPitch);
+ outf(DST_OFF_PITCH, depthOffsetPitch);
+
+ if (pATI->depthMoves)
+ ATIScreenToScreenCopyDepth(pScreenInfo,
+ xa, ya,
+ destx, desty,
+ w, h);
+#endif
+ }
+
+ ATIMach64WaitForFIFO(pATI, 2);
+ outf(SRC_OFF_PITCH, pATI->NewHW.dst_off_pitch);
+ outf(DST_OFF_PITCH, pATI->NewHW.src_off_pitch);
+
+ DEALLOCATE_LOCAL(pptNew2);
+ DEALLOCATE_LOCAL(pboxNew2);
+ DEALLOCATE_LOCAL(pptNew1);
+ DEALLOCATE_LOCAL(pboxNew1);
+
+ pXAAInfo->NeedToSync = TRUE;
+}
+
+/* Compute log base 2 of val. */
+static int Mach64MinBits(int val)
+{
+ int bits;
+
+ if (!val) return 1;
+ for (bits = 0; val; val >>= 1, ++bits);
+ return bits;
+}
+
+/* Initialize the AGP state. Request memory for use in AGP space, and
+ * initialize the Rage Pro registers to point to that memory.
+ */
+static Bool ATIDRIAgpInit( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+
+ unsigned long mode;
+ unsigned int vendor, device;
+ int ret;
+ unsigned long cntl;
+ int s, l;
+
+ pATIDRIServer->agpSize = ATI_DEFAULT_AGP_SIZE;
+ pATIDRIServer->agpMode = ATI_DEFAULT_AGP_MODE;
+ pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
+ pATIDRIServer->ringSize = 16; /* 16 kB ring */
+
+ if ( drmAgpAcquire( pATI->drmFD ) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP not available\n" );
+ return FALSE;
+ }
+
+ mode = drmAgpGetMode( pATI->drmFD ); /* Default mode */
+ vendor = drmAgpVendorId( pATI->drmFD );
+ device = drmAgpDeviceId( pATI->drmFD );
+
+ if (pATI->OptionAGPMode > 0 && pATI->OptionAGPMode <= ATI_AGP_MAX_MODE) {
+ pATIDRIServer->agpMode = pATI->OptionAGPMode;
+ xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using AGP %dx Mode\n",
+ pATIDRIServer->agpMode );
+ } else if (pATI->OptionAGPMode > 0) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal AGP Mode: %d\n",
+ pATI->OptionAGPMode );
+ return FALSE;
+ } else {
+ /* If no mode configured, use the default mode obtained from agpgart */
+ if ( mode & AGP_MODE_2X ) {
+ pATIDRIServer->agpMode = 2;
+ } else if ( mode & AGP_MODE_1X ) {
+ pATIDRIServer->agpMode = 1;
+ }
+ xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using AGP %dx Mode\n",
+ pATIDRIServer->agpMode );
+ }
+
+ mode &= ~AGP_MODE_MASK;
+ switch ( pATIDRIServer->agpMode ) {
+ case 2: mode |= AGP_MODE_2X;
+ case 1: default: mode |= AGP_MODE_1X;
+ }
+
+ if (pATI->OptionAGPSize) {
+ switch (pATI->OptionAGPSize) {
+ case 256:
+ case 128:
+ case 64:
+ case 32:
+ case 16:
+ case 8:
+ case 4:
+ pATIDRIServer->agpSize = pATI->OptionAGPSize;
+ xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB AGP aperture\n",
+ pATIDRIServer->agpSize );
+ break;
+ default:
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[agp] Illegal aperture size %d MB\n", pATI->OptionAGPSize );
+ return FALSE;
+ }
+ } else {
+ xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB AGP aperture\n",
+ pATIDRIServer->agpSize );
+ }
+
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
+ mode, vendor, device,
+ pATI->PCIInfo->vendor,
+ pATI->PCIInfo->chipType );
+
+ if ( drmAgpEnable( pATI->drmFD, mode ) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] AGP not enabled\n" );
+ drmAgpRelease( pATI->drmFD );
+ return FALSE;
+ }
+
+ pATIDRIServer->agpOffset = 0;
+
+ ret = drmAgpAlloc( pATI->drmFD, pATIDRIServer->agpSize*1024*1024,
+ 0, NULL, &pATIDRIServer->agpHandle );
+ if ( ret < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Out of memory (%d)\n", ret );
+ drmAgpRelease( pATI->drmFD );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[agp] %d kB allocated with handle 0x%08x\n",
+ pATIDRIServer->agpSize*1024, pATIDRIServer->agpHandle );
+
+ if ( drmAgpBind( pATI->drmFD, pATIDRIServer->agpHandle, pATIDRIServer->agpOffset) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Could not bind\n" );
+ drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
+ drmAgpRelease( pATI->drmFD );
+ return FALSE;
+ }
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Using %d kB for DMA descriptor ring\n", pATIDRIServer->ringSize);
+
+ if (pATI->OptionBufferSize) {
+ if (pATI->OptionBufferSize < 1 || pATI->OptionBufferSize > pATIDRIServer->agpSize ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR, "[agp] Illegal DMA buffers size: %d MB\n",
+ pATI->OptionBufferSize );
+ return FALSE;
+ }
+ if (pATI->OptionBufferSize > 2) {
+ xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Illegal DMA buffers size: %d MB\n",
+ pATI->OptionBufferSize );
+ xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Clamping DMA buffers size to 2 MB\n",
+ pATI->OptionBufferSize );
+ pATIDRIServer->bufferSize = 2;
+ } else {
+ pATIDRIServer->bufferSize = pATI->OptionBufferSize;
+ xf86DrvMsg( pScreen->myNum, X_CONFIG, "[agp] Using %d MB for DMA buffers\n",
+ pATIDRIServer->bufferSize );
+ }
+ } else {
+ xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[agp] Using %d MB for DMA buffers\n",
+ pATIDRIServer->bufferSize );
+ }
+
+ pATIDRIServer->agpTexSize = pATIDRIServer->agpSize - pATIDRIServer->bufferSize;
+
+ /* Reserve space for the DMA descriptor ring */
+ pATIDRIServer->ringStart = pATIDRIServer->agpOffset;
+ pATIDRIServer->ringMapSize = pATIDRIServer->ringSize*1024; /* ringSize is in kB */
+
+ /* Reserve space for the vertex buffer */
+ pATIDRIServer->bufferStart = pATIDRIServer->ringStart + pATIDRIServer->ringMapSize;
+ pATIDRIServer->bufferMapSize = pATIDRIServer->bufferSize*1024*1024;
+
+ /* Reserve the rest for AGP textures */
+ pATIDRIServer->agpTexStart = pATIDRIServer->bufferStart + pATIDRIServer->bufferMapSize;
+ s = (pATIDRIServer->agpSize*1024*1024 - pATIDRIServer->agpTexStart);
+ l = Mach64MinBits((s-1) / MACH64_NR_TEX_REGIONS);
+ if (l < MACH64_LOG_TEX_GRANULARITY) l = MACH64_LOG_TEX_GRANULARITY;
+ pATIDRIServer->agpTexMapSize = (s >> l) << l;
+ pATIDRIServer->log2AGPTexGran = l;
+
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] Using %d kB for AGP textures\n", pATIDRIServer->agpTexMapSize/1024);
+
+ /* Map DMA descriptor ring */
+ if ( drmAddMap( pATI->drmFD, pATIDRIServer->ringStart, pATIDRIServer->ringMapSize,
+ DRM_AGP, DRM_RESTRICTED, &pATIDRIServer->ringHandle ) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[agp] Could not add ring mapping\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[agp] ring handle = 0x%08lx\n",
+ pATIDRIServer->ringHandle );
+
+ if ( drmMap( pATI->drmFD, pATIDRIServer->ringHandle,
+ pATIDRIServer->ringMapSize, &pATIDRIServer->ringMap ) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[agp] Could not map ring\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[agp] Ring mapped at 0x%08lx\n",
+ (unsigned long)pATIDRIServer->ringMap );
+
+ /* Map vertex buffers */
+ if ( drmAddMap( pATI->drmFD, pATIDRIServer->bufferStart, pATIDRIServer->bufferMapSize,
+ DRM_AGP, 0, &pATIDRIServer->bufferHandle ) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[agp] Could not add vertex buffers mapping\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[agp] vertex buffers handle = 0x%08lx\n",
+ pATIDRIServer->bufferHandle );
+
+ if ( drmMap( pATI->drmFD, pATIDRIServer->bufferHandle,
+ pATIDRIServer->bufferMapSize, &pATIDRIServer->bufferMap ) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[agp] Could not map vertex buffers\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[agp] Vertex buffers mapped at 0x%08lx\n",
+ (unsigned long)pATIDRIServer->bufferMap );
+
+ /* Map AGP Textures */
+ if (drmAddMap(pATI->drmFD, pATIDRIServer->agpTexStart, pATIDRIServer->agpTexMapSize,
+ DRM_AGP, 0, &pATIDRIServer->agpTexHandle) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not add AGP texture region mapping\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP texture region handle = 0x%08lx\n",
+ pATIDRIServer->agpTexHandle);
+
+ if (drmMap(pATI->drmFD, pATIDRIServer->agpTexHandle, pATIDRIServer->agpTexMapSize,
+ &pATIDRIServer->agpTexMap) < 0) {
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[agp] Could not map AGP texture region\n");
+ return FALSE;
+ }
+ xf86DrvMsg(pScreen->myNum, X_INFO,
+ "[agp] AGP Texture region mapped at 0x%08lx\n",
+ (unsigned long)pATIDRIServer->agpTexMap);
+
+ /* Initialize Mach64's AGP registers */
+ cntl = inm( AGP_CNTL );
+ cntl &= ~AGP_APER_SIZE_MASK;
+ switch ( pATIDRIServer->agpSize ) {
+ case 256: cntl |= AGP_APER_SIZE_256MB; break;
+ case 128: cntl |= AGP_APER_SIZE_128MB; break;
+ case 64: cntl |= AGP_APER_SIZE_64MB; break;
+ case 32: cntl |= AGP_APER_SIZE_32MB; break;
+ case 16: cntl |= AGP_APER_SIZE_16MB; break;
+ case 8: cntl |= AGP_APER_SIZE_8MB; break;
+ case 4: cntl |= AGP_APER_SIZE_4MB; break;
+ default:
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[agp] Illegal aperture size %d kB\n",
+ pATIDRIServer->agpSize*1024 );
+ return FALSE;
+ }
+
+ /* 1 = DATA comes in clock in which TRDY sampled (default) */
+ /* 0 = DATA comes in clock after TRDY sampled */
+ cntl |= AGP_TRDY_MODE;
+
+ /* 1 = generate all reads as high priority */
+ /* 0 = generate all reads as their default priority (default) */
+ /* Setting this only works for me at AGP 1x mode (LLD) */
+ if (pATIDRIServer->agpMode == 1) {
+ cntl |= HIGH_PRIORITY_READ_EN;
+ } else {
+ cntl &= ~HIGH_PRIORITY_READ_EN;
+ }
+
+ outm( AGP_BASE, drmAgpBase(pATI->drmFD) );
+ outm( AGP_CNTL, cntl );
+
+ return TRUE;
+}
+
+/* Add a map for the MMIO registers that will be accessed by any
+ * DRI-based clients.
+ */
+static Bool ATIDRIMapInit( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+
+ pATIDRIServer->regsSize = getpagesize();
+ if ( drmAddMap( pATI->drmFD, pATI->Block1Base,
+ pATIDRIServer->regsSize,
+ DRM_REGISTERS, DRM_READ_ONLY,
+ &pATIDRIServer->regsHandle ) < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[drm] failed to map registers\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[drm] register handle = 0x%08lx\n",
+ pATIDRIServer->regsHandle );
+
+ return TRUE;
+}
+
+/* Initialize the kernel data structures. */
+static Bool ATIDRIKernelInit( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+ drmMach64Init info;
+
+ memset( &info, 0, sizeof(drmMach64Init) );
+
+ info.func = DRM_MACH64_INIT_DMA;
+ info.sarea_priv_offset = sizeof(XF86DRISAREARec);
+ info.is_pci = pATIDRIServer->IsPCI;
+ info.dma_mode = pATI->OptionDMAMode;
+
+ info.fb_bpp = pATI->bitsPerPixel;
+ info.front_offset = pATIDRIServer->frontOffset;
+ info.front_pitch = pATIDRIServer->frontPitch;
+ info.back_offset = pATIDRIServer->backOffset;
+ info.back_pitch = pATIDRIServer->backPitch;
+
+ info.depth_bpp = 16;
+ info.depth_offset = pATIDRIServer->depthOffset;
+ info.depth_pitch = pATIDRIServer->depthPitch;
+
+ info.fb_offset = pATI->LinearBase;
+ info.mmio_offset = pATIDRIServer->regsHandle;
+ info.ring_offset = pATIDRIServer->ringHandle;
+ info.buffers_offset = pATIDRIServer->bufferHandle;
+ info.agp_textures_offset = pATIDRIServer->agpTexHandle;
+
+ if ( drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
+ &info, sizeof(drmMach64Init) ) < 0 ) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/* Add a map for the DMA buffers that will be accessed by any
+ * DRI-based clients.
+ */
+static Bool ATIDRIAddBuffers( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+
+ /* Initialize vertex buffers */
+ if ( pATIDRIServer->IsPCI ) {
+ pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
+ (pATIDRIServer->bufferSize*1024*1024)/MACH64_BUFFER_SIZE,
+ MACH64_BUFFER_SIZE,
+ 0,
+ 0 );
+ } else {
+ pATIDRIServer->numBuffers = drmAddBufs( pATI->drmFD,
+ pATIDRIServer->bufferMapSize/MACH64_BUFFER_SIZE,
+ MACH64_BUFFER_SIZE,
+ DRM_AGP_BUFFER,
+ pATIDRIServer->bufferStart );
+ }
+ if ( pATIDRIServer->numBuffers <= 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[drm] Could not create DMA buffers list\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[drm] Added %d %d byte DMA buffers\n",
+ pATIDRIServer->numBuffers, MACH64_BUFFER_SIZE );
+
+ return TRUE;
+}
+
+static Bool ATIDRIMapBuffers( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+
+ pATIDRIServer->drmBuffers = drmMapBufs( pATI->drmFD );
+ if ( !pATIDRIServer->drmBuffers ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[drm] Failed to map DMA buffers list\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreen->myNum, X_INFO,
+ "[drm] Mapped %d DMA buffers at 0x%08lx\n",
+ pATIDRIServer->drmBuffers->count,
+ pATIDRIServer->drmBuffers->list->address );
+
+ return TRUE;
+}
+
+static Bool ATIDRIIrqInit( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+
+ if ( pATI->irq <= 0 ) {
+ pATI->irq = drmGetInterruptFromBusID(pATI->drmFD,
+ ((pciConfigPtr)pATI->PCIInfo
+ ->thisCard)->busnum,
+ ((pciConfigPtr)pATI->PCIInfo
+ ->thisCard)->devnum,
+ ((pciConfigPtr)pATI->PCIInfo
+ ->thisCard)->funcnum);
+ if ( pATI->irq <= 0 ) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "[drm] Couldn't find IRQ for bus id %d:%d:%d\n",
+ ((pciConfigPtr)pATI->PCIInfo->thisCard)->busnum,
+ ((pciConfigPtr)pATI->PCIInfo->thisCard)->devnum,
+ ((pciConfigPtr)pATI->PCIInfo->thisCard)->funcnum);
+ pATI->irq = 0;
+ } else if ((drmCtlInstHandler(pATI->drmFD, pATI->irq)) != 0) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "[drm] Failed to initialize interrupt handler with IRQ %d\n",
+ pATI->irq);
+ pATI->irq = 0;
+ }
+
+ if (pATI->irq)
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "[drm] Installed interrupt handler, using IRQ %d\n",
+ pATI->irq);
+ else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "[drm] Falling back to irq-free operation\n",
+ pATI->irq);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+
+}
+
+/* Initialize the screen-specific data structures for the DRI and the
+ * Rage Pro. This is the main entry point to the device-specific
+ * initialization code. It calls device-independent DRI functions to
+ * create the DRI data structures and initialize the DRI state.
+ */
+Bool ATIDRIScreenInit( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ DRIInfoPtr pDRIInfo;
+ ATIDRIPtr pATIDRI;
+ ATIDRIServerInfoPtr pATIDRIServer;
+ drmVersionPtr version;
+ int major, minor, patch;
+
+ /* Check that the GLX, DRI, and DRM modules have been loaded by testing
+ * for known symbols in each module.
+ */
+ if ( !xf86LoaderCheckSymbol("GlxSetVisualConfigs") ) return FALSE;
+ if ( !xf86LoaderCheckSymbol("DRIScreenInit") ) return FALSE;
+ if ( !xf86LoaderCheckSymbol("drmAvailable") ) return FALSE;
+ if ( !xf86LoaderCheckSymbol("DRIQueryVersion") ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[dri] ATIDRIScreenInit failed (libdri.a too old)\n" );
+ return FALSE;
+ }
+
+ /* Check the DRI version */
+ DRIQueryVersion( &major, &minor, &patch );
+ if ( major != 4 || minor < 0 ) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libDRI version is %d.%d.%d but version 4.0.x is needed.\n"
+ "[dri] Disabling the DRI.\n",
+ major, minor, patch );
+ return FALSE;
+ }
+
+ switch ( pATI->bitsPerPixel ) {
+ case 8:
+ /* These modes are not supported (yet). */
+ case 15:
+ case 24:
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[dri] Direct rendering only supported in 16 and 32 bpp modes\n");
+ return FALSE;
+
+ /* Only 16 and 32 color depths are supported currently. */
+ case 16:
+ if ( pATI->depth != 16) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[dri] Direct rendering not supported for depth %d at fbbpp 16.\n", pATI->depth );
+ return FALSE;
+ }
+ break;
+ case 32:
+ break;
+ }
+
+ /* Create the DRI data structure, and fill it in before calling the
+ * DRIScreenInit().
+ */
+ pDRIInfo = DRICreateInfoRec();
+ if ( !pDRIInfo ) return FALSE;
+
+ pATI->pDRIInfo = pDRIInfo;
+ pDRIInfo->drmDriverName = ATIKernelDriverName;
+ pDRIInfo->clientDriverName = ATIClientDriverName;
+ if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) {
+ pDRIInfo->busIdString = DRICreatePCIBusID(pATI->PCIInfo);
+ } else {
+ pDRIInfo->busIdString = xalloc( 64 );
+ sprintf( pDRIInfo->busIdString,
+ "PCI:%d:%d:%d",
+ pATI->PCIInfo->bus,
+ pATI->PCIInfo->device,
+ pATI->PCIInfo->func );
+ }
+ pDRIInfo->ddxDriverMajorVersion = ATI_VERSION_MAJOR;
+ pDRIInfo->ddxDriverMinorVersion = ATI_VERSION_MINOR;
+ pDRIInfo->ddxDriverPatchVersion = ATI_VERSION_PATCH;
+ pDRIInfo->frameBufferPhysicalAddress = pATI->LinearBase;
+ pDRIInfo->frameBufferSize = pATI->LinearSize;
+ pDRIInfo->frameBufferStride = (pScreenInfo->displayWidth *
+ pATI->FBBytesPerPixel);
+ pDRIInfo->ddxDrawableTableEntry = ATI_MAX_DRAWABLES;
+
+ if ( SAREA_MAX_DRAWABLES < ATI_MAX_DRAWABLES ) {
+ pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
+ } else {
+ pDRIInfo->maxDrawableTableEntry = ATI_MAX_DRAWABLES;
+ }
+
+ /* For now the mapping works by using a fixed size defined
+ * in the SAREA header
+ */
+ if ( sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) > SAREA_MAX ) {
+ ErrorF( "[dri] Data does not fit in SAREA\n" );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %d+%d: %d\n",
+ sizeof(XF86DRISAREARec), sizeof(ATISAREAPrivRec),
+ sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec) );
+ pDRIInfo->SAREASize = SAREA_MAX;
+
+ pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 );
+ if ( !pATIDRI ) {
+ DRIDestroyInfoRec( pATI->pDRIInfo );
+ pATI->pDRIInfo = NULL;
+ xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
+ "[dri] Failed to allocate memory for private record\n" );
+ return FALSE;
+ }
+ pATIDRIServer = (ATIDRIServerInfoPtr)
+ xnfcalloc( sizeof(ATIDRIServerInfoRec), 1 );
+ if ( !pATIDRIServer ) {
+ xfree( pATIDRI );
+ DRIDestroyInfoRec( pATI->pDRIInfo );
+ pATI->pDRIInfo = NULL;
+ xf86DrvMsg( pScreenInfo->scrnIndex, X_ERROR,
+ "[dri] Failed to allocate memory for private record\n" );
+ return FALSE;
+ }
+
+ pATI->pDRIServerInfo = pATIDRIServer;
+
+ pDRIInfo->devPrivate = pATIDRI;
+ pDRIInfo->devPrivateSize = sizeof(ATIDRIRec);
+ pDRIInfo->contextSize = sizeof(ATIDRIContextRec);
+
+ pDRIInfo->CreateContext = ATICreateContext;
+ pDRIInfo->DestroyContext = ATIDestroyContext;
+ pDRIInfo->SwapContext = ATIDRISwapContext;
+ pDRIInfo->InitBuffers = ATIDRIInitBuffers;
+ pDRIInfo->MoveBuffers = ATIDRIMoveBuffers;
+ pDRIInfo->TransitionTo2d = ATIDRITransitionTo2d;
+ pDRIInfo->TransitionTo3d = ATIDRITransitionTo3d;
+ pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
+
+ pDRIInfo->createDummyCtx = TRUE;
+ pDRIInfo->createDummyCtxPriv = FALSE;
+
+ pATI->have3DWindows = FALSE;
+
+ if ( !DRIScreenInit( pScreen, pDRIInfo, &pATI->drmFD ) ) {
+ xfree( pATIDRIServer );
+ pATI->pDRIServerInfo = NULL;
+ xfree( pDRIInfo->devPrivate );
+ pDRIInfo->devPrivate = NULL;
+ DRIDestroyInfoRec( pDRIInfo );
+ pDRIInfo = NULL;
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[dri] DRIScreenInit Failed\n" );
+ return FALSE;
+ }
+
+ /* Check the DRM lib version.
+ drmGetLibVersion was not supported in version 1.0, so check for
+ symbol first to avoid possible crash or hang.
+ */
+ if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
+ version = drmGetLibVersion(pATI->drmFD);
+ } else {
+ /* drmlib version 1.0.0 didn't have the drmGetLibVersion
+ entry point. Fake it by allocating a version record
+ via drmGetVersion and changing it to version 1.0.0
+ */
+ version = drmGetVersion(pATI->drmFD);
+ version->version_major = 1;
+ version->version_minor = 0;
+ version->version_patchlevel = 0;
+ }
+
+ if (version) {
+ if (version->version_major != 1 ||
+ version->version_minor < 1) {
+ /* incompatible drm library version */
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
+ "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
+ "[dri] libdrm.a module version is %d.%d.%d but version 1.1.x is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel);
+ drmFreeVersion(version);
+ ATIDRICloseScreen(pScreen);
+ return FALSE;
+ }
+ drmFreeVersion(version);
+ }
+
+ /* Check the mach64 DRM version */
+ version = drmGetVersion( pATI->drmFD );
+ if ( version ) {
+ if ( version->version_major != 1 ||
+ version->version_minor < 0 ) {
+ /* Incompatible DRM version */
+ xf86DrvMsg( pScreen->myNum, X_ERROR,
+ "[dri] ATIDRIScreenInit failed because of a version mismatch.\n"
+ "[dri] mach64.o kernel module version is %d.%d.%d, but version 1.0 or greater is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel );
+ drmFreeVersion( version );
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+ drmFreeVersion( version );
+ }
+
+ switch ( pATI->OptionDMAMode ) {
+ case MACH64_MODE_DMA_ASYNC:
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request asynchronous DMA mode\n");
+ break;
+ case MACH64_MODE_DMA_SYNC:
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request synchronous DMA mode\n");
+ break;
+ case MACH64_MODE_MMIO:
+ xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Will request pseudo-DMA (MMIO) mode\n");
+ break;
+ default:
+ xf86DrvMsg(pScreen->myNum, X_WARNING, "[drm] Unknown DMA mode\n");
+ }
+
+ pATIDRIServer->IsPCI = (pATI->BusType == ATI_BUS_PCI || pATI->OptionIsPCI) ? TRUE : FALSE;
+
+ if ( pATI->BusType != ATI_BUS_PCI && pATI->OptionIsPCI ) {
+ outm( AGP_BASE, 0 );
+ outm( AGP_CNTL, 0 );
+ xf86DrvMsg(pScreen->myNum, X_CONFIG, "[dri] Forcing PCI mode\n");
+ }
+
+ /* Check buffer size option for PCI, since it won't be done in ATIDRIAgpInit */
+ if ( pATIDRIServer->IsPCI) {
+ pATIDRIServer->bufferSize = ATI_DEFAULT_BUFFER_SIZE;
+ if (pATI->OptionBufferSize) {
+ if (pATI->OptionBufferSize < 1) {
+ xf86DrvMsg( pScreen->myNum, X_ERROR, "[pci] Illegal DMA buffers size: %d MB\n",
+ pATI->OptionBufferSize );
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+ if (pATI->OptionBufferSize > 2) {
+ xf86DrvMsg( pScreen->myNum, X_WARNING, "[pci] Illegal DMA buffers size: %d MB\n",
+ pATI->OptionBufferSize );
+ xf86DrvMsg( pScreen->myNum, X_WARNING, "[pci] Clamping DMA buffers size to 2 MB\n",
+ pATI->OptionBufferSize );
+ pATIDRIServer->bufferSize = 2;
+ } else {
+ pATIDRIServer->bufferSize = pATI->OptionBufferSize;
+ xf86DrvMsg( pScreen->myNum, X_CONFIG, "[pci] Using %d MB DMA buffer size\n",
+ pATIDRIServer->bufferSize );
+ }
+ } else {
+ xf86DrvMsg( pScreen->myNum, X_DEFAULT, "[pci] Using %d MB DMA buffer size\n",
+ pATIDRIServer->bufferSize );
+ }
+ }
+
+ /* Initialize AGP */
+ if ( !pATIDRIServer->IsPCI && !ATIDRIAgpInit( pScreen ) ) {
+ pATIDRIServer->IsPCI = TRUE;
+ if ( pATI->BusType != ATI_BUS_PCI ) {
+ outm( AGP_BASE, 0 );
+ outm( AGP_CNTL, 0 );
+ }
+ xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] AGP failed to initialize -- falling back to PCI mode.\n" );
+ xf86DrvMsg( pScreen->myNum, X_WARNING, "[agp] Make sure you have the agpgart kernel module loaded.\n" );
+ }
+
+ if ( !ATIDRIMapInit( pScreen ) ) {
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+
+ if ( !ATIInitVisualConfigs( pScreen ) ) {
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+ xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
+ "[dri] Visual configs initialized\n" );
+
+ xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO,
+ "[dri] Block 0 base at 0x%08lx\n", pATI->Block0Base );
+
+ return TRUE;
+}
+
+/* Finish initializing the device-dependent DRI state, and call
+ * DRIFinishScreenInit() to complete the device-independent DRI
+ * initialization.
+ */
+Bool ATIDRIFinishScreenInit( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATISAREAPrivPtr pSAREAPriv;
+ ATIDRIPtr pATIDRI;
+ ATIDRIServerInfoPtr pATIDRIServer;
+
+ pATI->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
+
+ /* NOTE: DRIFinishScreenInit must be called before *DRIKernelInit
+ * because *DRIKernelInit requires that the hardware lock is held by
+ * the X server, and the first time the hardware lock is grabbed is
+ * in DRIFinishScreenInit.
+ */
+ if ( !DRIFinishScreenInit( pScreen ) ) {
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+
+ /* Initialize the DMA buffer list */
+ /* Need to do this before ATIDRIKernelInit so we can init the freelist */
+ if ( !ATIDRIAddBuffers( pScreen ) ) {
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+
+ /* Initialize the kernel data structures */
+ if ( !ATIDRIKernelInit( pScreen ) ) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "[drm] Failed to initialize the mach64.o kernel module\n");
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "[drm] Check the system log for more information.\n");
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+
+ if ( !ATIDRIMapBuffers( pScreen ) ) {
+ ATIDRICloseScreen( pScreen );
+ return FALSE;
+ }
+
+ /* Initialize IRQ */
+ ATIDRIIrqInit( pScreen );
+
+ pSAREAPriv = (ATISAREAPrivPtr) DRIGetSAREAPrivate( pScreen );
+ memset( pSAREAPriv, 0, sizeof(*pSAREAPriv) );
+
+ pATIDRI = (ATIDRIPtr)pATI->pDRIInfo->devPrivate;
+ pATIDRIServer = pATI->pDRIServerInfo;
+
+ pATIDRI->width = pScreenInfo->virtualX;
+ pATIDRI->height = pScreenInfo->virtualY;
+ pATIDRI->mem = pScreenInfo->videoRam * 1024;
+ pATIDRI->cpp = pScreenInfo->bitsPerPixel / 8;
+
+ pATIDRI->IsPCI = pATIDRIServer->IsPCI;
+ pATIDRI->AGPMode = pATIDRIServer->agpMode;
+
+ pATIDRI->frontOffset = pATIDRIServer->frontOffset;
+ pATIDRI->frontPitch = pATIDRIServer->frontPitch;
+
+ pATIDRI->backOffset = pATIDRIServer->backOffset;
+ pATIDRI->backPitch = pATIDRIServer->backPitch;
+
+ pATIDRI->depthOffset = pATIDRIServer->depthOffset;
+ pATIDRI->depthPitch = pATIDRIServer->depthPitch;
+
+ pATIDRI->textureOffset = pATIDRIServer->textureOffset;
+ pATIDRI->textureSize = pATIDRIServer->textureSize;
+ pATIDRI->logTextureGranularity = pATIDRIServer->logTextureGranularity;
+
+ pATIDRI->regs = pATIDRIServer->regsHandle;
+ pATIDRI->regsSize = pATIDRIServer->regsSize;
+
+ pATIDRI->agp = pATIDRIServer->agpTexHandle;
+ pATIDRI->agpSize = pATIDRIServer->agpTexMapSize;
+ pATIDRI->logAgpTextureGranularity = pATIDRIServer->log2AGPTexGran;
+ pATIDRI->agpTextureOffset = pATIDRIServer->agpTexStart;
+
+ return TRUE;
+}
+
+/* The screen is being closed, so clean up any state and free any
+ * resources used by the DRI.
+ */
+void ATIDRICloseScreen( ScreenPtr pScreen )
+{
+ ScrnInfoPtr pScreenInfo = xf86Screens[pScreen->myNum];
+ ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRIServerInfoPtr pATIDRIServer = pATI->pDRIServerInfo;
+ drmMach64Init info;
+
+ /* Stop interrupt generation and handling if used */
+ if ( pATI->irq > 0 ) {
+ if ( drmCtlUninstHandler(pATI->drmFD) != 0 ) {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
+ "[drm] Error uninstalling interrupt handler for IRQ %d\n", pATI->irq);
+ } else {
+ xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
+ "[drm] Uninstalled interrupt handler for IRQ %d\n", pATI->irq);
+ }
+ pATI->irq = 0;
+ }
+
+ /* De-allocate DMA buffers */
+ if ( pATIDRIServer->drmBuffers ) {
+ drmUnmapBufs( pATIDRIServer->drmBuffers );
+ pATIDRIServer->drmBuffers = NULL;
+ }
+
+ /* De-allocate all kernel resources */
+ memset(&info, 0, sizeof(drmMach64Init));
+ info.func = DRM_MACH64_CLEANUP_DMA;
+ drmCommandWrite( pATI->drmFD, DRM_MACH64_INIT,
+ &info, sizeof(drmMach64Init) );
+
+ /* De-allocate all AGP resources */
+ if ( pATIDRIServer->agpTexMap ) {
+ drmUnmap( pATIDRIServer->agpTexMap, pATIDRIServer->agpTexMapSize );
+ pATIDRIServer->agpTexMap = NULL;
+ }
+ if ( pATIDRIServer->bufferMap ) {
+ drmUnmap( pATIDRIServer->bufferMap, pATIDRIServer->bufferMapSize );
+ pATIDRIServer->bufferMap = NULL;
+ }
+ if ( pATIDRIServer->agpHandle ) {
+ drmAgpUnbind( pATI->drmFD, pATIDRIServer->agpHandle );
+ drmAgpFree( pATI->drmFD, pATIDRIServer->agpHandle );
+ pATIDRIServer->agpHandle = 0;
+ drmAgpRelease( pATI->drmFD );
+ }
+
+ /* De-allocate all DRI resources */
+ DRICloseScreen( pScreen );
+
+ /* De-allocate all DRI data structures */
+ if ( pATI->pDRIInfo ) {
+ if ( pATI->pDRIInfo->devPrivate ) {
+ xfree( pATI->pDRIInfo->devPrivate );
+ pATI->pDRIInfo->devPrivate = NULL;
+ }
+ DRIDestroyInfoRec( pATI->pDRIInfo );
+ pATI->pDRIInfo = NULL;
+ }
+ if ( pATI->pDRIServerInfo ) {
+ xfree( pATI->pDRIServerInfo );
+ pATI->pDRIServerInfo = NULL;
+ }
+ if ( pATI->pVisualConfigs ) {
+ xfree( pATI->pVisualConfigs );
+ pATI->pVisualConfigs = NULL;
+ }
+ if ( pATI->pVisualConfigsPriv ) {
+ xfree( pATI->pVisualConfigsPriv );
+ pATI->pVisualConfigsPriv = NULL;
+ }
+}
diff --git a/src/atidri.h b/src/atidri.h
new file mode 100644
index 00000000..a0319a66
--- /dev/null
+++ b/src/atidri.h
@@ -0,0 +1,47 @@
+/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * Copyright 2000 Gareth Hughes
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * GARETH HUGHES 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.
+ */
+
+/*
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ * Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+#ifndef __ATIDRI_H__
+#define __ATIDRI_H__ 1
+
+#include "atiproto.h"
+
+/* DRI driver defaults */
+#define ATI_DEFAULT_AGP_SIZE 8 /* MB (must be a power of 2 and > 4MB) */
+#define ATI_DEFAULT_AGP_MODE 1
+#define ATI_DEFAULT_BUFFER_SIZE 2 /* MB (must be page aligned) */
+
+#define ATI_AGP_MAX_MODE 2
+
+extern Bool ATIDRIScreenInit FunctionPrototype((ScreenPtr));
+extern Bool ATIDRIFinishScreenInit FunctionPrototype((ScreenPtr));
+extern void ATIDRICloseScreen FunctionPrototype((ScreenPtr));
+
+#endif /* __ATIDRI_H__ */
diff --git a/src/atidripriv.h b/src/atidripriv.h
new file mode 100644
index 00000000..b16b14e4
--- /dev/null
+++ b/src/atidripriv.h
@@ -0,0 +1,59 @@
+/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ * Precision Insight, Inc., Cedar Park, Texas, and
+ * VA Linux Systems Inc., Fremont, California.
+ *
+ * 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 on 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 ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR 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.
+ */
+
+/*
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ * Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+#ifndef __ATIDRIPRIV_H__
+#define __ATIDRIPRIV_H__ 1
+
+#include "GL/glxint.h"
+#include "GL/glxtokens.h"
+
+#include "atiproto.h"
+
+#define ATI_MAX_DRAWABLES 256
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} ATIConfigPrivRec, *ATIConfigPrivPtr;
+
+typedef struct {
+ /* Nothing here yet */
+ int dummy;
+} ATIDRIContextRec, *ATIDRIContextPtr;
+
+extern void GlxSetVisualConfigs FunctionPrototype((int, __GLXvisualConfig *, void **));
+
+#endif /* __ATIDRIPRIV_H__ */
diff --git a/src/atifillin.c b/src/atifillin.c
new file mode 100644
index 00000000..76df7550
--- /dev/null
+++ b/src/atifillin.c
@@ -0,0 +1,24 @@
+/*
+ * atifillin.c: fill in a ScrnInfoPtr with the relevant information for
+ * atimisc.
+ *
+ * (c) 2004 Adam Jackson. Standard MIT license applies.
+ */
+
+#include "atifillin.h"
+
+void ATIFillInScreenInfo(ScrnInfoPtr pScreenInfo)
+{
+ pScreenInfo->driverVersion = ATI_VERSION_CURRENT;
+ pScreenInfo->driverName = ATI_DRIVER_NAME;
+ pScreenInfo->name = ATI_NAME;
+ pScreenInfo->Probe = ATIProbe;
+ pScreenInfo->PreInit = ATIPreInit;
+ pScreenInfo->ScreenInit = ATIScreenInit;
+ pScreenInfo->SwitchMode = ATISwitchMode;
+ pScreenInfo->AdjustFrame = ATIAdjustFrame;
+ pScreenInfo->EnterVT = ATIEnterVT;
+ pScreenInfo->LeaveVT = ATILeaveVT;
+ pScreenInfo->FreeScreen = ATIFreeScreen;
+ pScreenInfo->ValidMode = ATIValidMode;
+}
diff --git a/src/atifillin.h b/src/atifillin.h
new file mode 100644
index 00000000..824b7916
--- /dev/null
+++ b/src/atifillin.h
@@ -0,0 +1,22 @@
+/*
+ * atifillin.h: header for atifillin.c.
+ *
+ * (c) 2004 Adam Jackson. Standard MIT license applies.
+ */
+
+#ifndef ATI_FILLIN_H
+#define ATI_FILLIN_H
+
+/* include headers corresponding to fields touched by ATIFillInScreenInfo() */
+
+#include "ativersion.h"
+#include "atiprobe.h"
+#include "atipreinit.h"
+#include "atiscreen.h"
+#include "aticonsole.h"
+#include "atiadjust.h"
+#include "ativalid.h"
+
+extern void ATIFillInScreenInfo FunctionPrototype((ScrnInfoPtr));
+
+#endif
diff --git a/src/atiload.c b/src/atiload.c
index e00f216b..8ed14f17 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_DEVEL
+
+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_DEVEL */
+
const char *ATIfbSymbols[] =
{
"fbPictureInit",
diff --git a/src/atiload.h b/src/atiload.h
index a506f340..38272238 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_DEVEL
+
+ *ATIdrmSymbols[], *ATIdriSymbols[],
+
+#endif /* XF86DRI_DEVEL */
+
*ATIfbSymbols[], *ATIshadowfbSymbols[], *ATIxaaSymbols[],
*ATIramdacSymbols[], *ATIi2cSymbols[];
diff --git a/src/atilock.c b/src/atilock.c
index a6d5cda5..8dafcf76 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_DEVEL
+
+ 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_DEVEL */
+
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 f90f6f91..dfbe8d76 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_DEVEL
+
+ /* 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_DEVEL */
+
pATIHW->gui_cntl = inm(GUI_CNTL) & ~CMDFIFO_SIZE_MODE;
+#endif /* XF86DRI_DEVEL */
+
/* Initialise destination registers */
pATIHW->dst_off_pitch =
SetBits((pATI->displayWidth * pATI->XModifier) >> 3, DST_PITCH);
@@ -1083,6 +1123,13 @@ ATIMach64SetDPMSMode
return;
}
+#ifdef XF86DRI_DEVEL
+
+ /* XAA Sync requires the DRM lock if DRI enabled */
+ ATIDRILock(pScreenInfo);
+
+#endif /* XF86DRI_DEVEL */
+
ATIMach64Sync(pScreenInfo);
outr(CRTC_GEN_CNTL, crtc_gen_cntl);
@@ -1178,4 +1225,11 @@ ATIMach64SetDPMSMode
}
}
}
+
+#ifdef XF86DRI_DEVEL
+
+ ATIDRIUnlock(pScreenInfo);
+
+#endif /* XF86DRI_DEVEL */
+
}
diff --git a/src/atimach64accel.c b/src/atimach64accel.c
index 6f2dba73..9a38cf09 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,10 @@
#include "atipriv.h"
#include "atiregs.h"
+#ifdef XF86DRI_DEVEL
+#include "mach64_common.h"
+#endif
+
#include "miline.h"
/* Used to test MMIO cache integrity in ATIMach64Sync() */
@@ -130,12 +139,146 @@ ATIMach64Sync
{
ATIPtr pATI = ATIPTR(pScreenInfo);
- ATIMach64WaitForIdle(pATI);
- if (pATI->pXAAInfo)
- pATI->pXAAInfo->NeedToSync = FALSE;
+#ifdef XF86DRI_DEVEL
- 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_DEVEL */
+ {
+ ATIMach64WaitForIdle(pATI);
+
+ if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache)
+ {
/*
* For debugging purposes, attempt to verify that each cached register
* should actually be cached.
@@ -227,6 +370,7 @@ ATIMach64Sync
}
}
}
+ }
}
/*
@@ -235,6 +379,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 +404,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 +468,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 +511,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 +543,8 @@ ATIMach64SubsequentSolidFillRect
{
ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRISync(pScreenInfo);
+
if (pATI->XModifier != 1)
{
x *= pATI->XModifier;
@@ -424,6 +579,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 +612,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 +654,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 +685,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 +736,8 @@ ATIMach64SubsequentMono8x8PatternFillRect
{
ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRISync(pScreenInfo);
+
if (pATI->XModifier != 1)
{
x *= pATI->XModifier;
@@ -607,6 +772,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 +817,8 @@ ATIMach64SubsequentScanlineCPUToScreenColorExpandFill
{
ATIPtr pATI = ATIPTR(pScreenInfo);
+ ATIDRISync(pScreenInfo);
+
if (pATI->XModifier != 1)
{
x *= pATI->XModifier;
@@ -691,6 +860,8 @@ ATIMach64SubsequentColorExpandScanline
int w = pATI->ExpansionBitmapWidth;
int nDWord;
+ ATIDRISync(pScreenInfo);
+
while (w > 0)
{
/*
diff --git a/src/atimach64cursor.c b/src/atimach64cursor.c
index 9d8816be..07d85cb3 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_DEVEL
+
+ /* XAA Sync requires the DRM lock if DRI enabled */
+ ATIDRILock(pScreenInfo);
+
+#endif /* XF86DRI_DEVEL */
+
/* Synchronise video memory accesses */
ATIMach64Sync(pScreenInfo);
@@ -277,6 +284,12 @@ ATIMach64LoadCursorImage
#endif
+#ifdef XF86DRI_DEVEL
+
+ ATIDRIUnlock(pScreenInfo);
+
+#endif /* XF86DRI_DEVEL */
+
}
/*
diff --git a/src/atimach64io.h b/src/atimach64io.h
index a1c07b8f..01cb32d1 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_DEVEL
+
+#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_DEVEL */
+
+
+#define ATIDRIWaitForIdle(_pATI)
+#define ATIDRILock(_pScrInfo)
+#define ATIDRIUnlock(_pScrInfo)
+#define ATIDRISync(_pScrInfo)
+
+#endif /* XF86DRI_DEVEL */
+
+
/*
* 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 53c97b5e..cfbf40fc 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
@@ -35,7 +38,7 @@ static XF86ModuleVersionInfo ATIVersionRec =
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
- XF86_VERSION_CURRENT,
+ XORG_VERSION_CURRENT,
ATI_VERSION_MAJOR, ATI_VERSION_MINOR, ATI_VERSION_PATCH,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
@@ -111,6 +114,13 @@ ATISetup
#endif /* AVOID_CPIO */
+#ifdef XF86DRI_DEVEL
+
+ ATIdrmSymbols,
+ ATIdriSymbols,
+
+#endif /* XF86DRI_DEVEL */
+
ATIfbSymbols,
ATIshadowfbSymbols,
ATIxaaSymbols,
diff --git a/src/atimodule.c b/src/atimodule.c
index 206e2811..2d10516e 100644
--- a/src/atimodule.c
+++ b/src/atimodule.c
@@ -39,6 +39,7 @@ const char *ATISymbols[] =
"ATILeaveVT",
"ATIFreeScreen",
"ATIValidMode",
+ "ATIFillInScreenInfo",
NULL
};
@@ -52,7 +53,8 @@ const char *R128Symbols[] =
"R128LeaveVT",
"R128FreeScreen",
"R128ValidMode",
- "R128Options",
+ "R128OptionsWeak",
+ "R128FillInScreenInfo",
NULL
};
@@ -66,8 +68,9 @@ const char *RADEONSymbols[] =
"RADEONLeaveVT",
"RADEONFreeScreen",
"RADEONValidMode",
- "RADEONOptions",
+ "RADEONOptionsWeak",
"RADEONHandleMessage",
+ "RADEONFillInScreenInfo",
NULL
};
@@ -77,7 +80,7 @@ static XF86ModuleVersionInfo ATIVersionRec =
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
- XF86_VERSION_CURRENT,
+ XORG_VERSION_CURRENT,
ATI_VERSION_MAJOR, ATI_VERSION_MINOR, ATI_VERSION_PATCH,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
diff --git a/src/atioption.c b/src/atioption.c
index 81b6d3b8..24536fcc 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_DEVEL
+
+ {
+ 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_DEVEL */
+
{
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 53e2be43..de406f99 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_DEVEL
+
+ 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_DEVEL */
+
ATI_OPTION_MMIO_CACHE,
ATI_OPTION_TEST_MMIO_CACHE,
ATI_OPTION_PANEL_DISPLAY,
diff --git a/src/atipreinit.c b/src/atipreinit.c
index a3523daa..ebe54ad1 100644
--- a/src/atipreinit.c
+++ b/src/atipreinit.c
@@ -1479,7 +1479,7 @@ ATIPreInit
if (pATI->Chip >= ATI_CHIP_264GT)
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
- "For information on using the multimedia capabilities\n of this"
+ "For information on using the multimedia capabilities\n\tof this"
" adapter, please see http://gatos.sf.net.\n");
if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
diff --git a/src/atiprobe.c b/src/atiprobe.c
index ec861797..08cc56f3 100644
--- a/src/atiprobe.c
+++ b/src/atiprobe.c
@@ -27,6 +27,7 @@
#include "atibus.h"
#include "atichip.h"
#include "aticonsole.h"
+#include "atifillin.h"
#include "atiident.h"
#include "atimach64io.h"
#include "atimodule.h"
@@ -57,32 +58,6 @@
* largely ignored.
*/
-#ifdef XFree86LOADER
-
-/*
- * The following exists to prevent the compiler from considering entry points
- * defined in a separate module from being constants.
- */
-static xf86PreInitProc * const volatile PreInitProc = ATIPreInit;
-static xf86ScreenInitProc * const volatile ScreenInitProc = ATIScreenInit;
-static xf86SwitchModeProc * const volatile SwitchModeProc = ATISwitchMode;
-static xf86AdjustFrameProc * const volatile AdjustFrameProc = ATIAdjustFrame;
-static xf86EnterVTProc * const volatile EnterVTProc = ATIEnterVT;
-static xf86LeaveVTProc * const volatile LeaveVTProc = ATILeaveVT;
-static xf86FreeScreenProc * const volatile FreeScreenProc = ATIFreeScreen;
-static xf86ValidModeProc * const volatile ValidModeProc = ATIValidMode;
-
-#define ATIPreInit PreInitProc
-#define ATIScreenInit ScreenInitProc
-#define ATISwitchMode SwitchModeProc
-#define ATIAdjustFrame AdjustFrameProc
-#define ATIEnterVT EnterVTProc
-#define ATILeaveVT LeaveVTProc
-#define ATIFreeScreen FreeScreenProc
-#define ATIValidMode ValidModeProc
-
-#endif
-
/* Used as a temporary buffer */
#define Identifier ((char *)(pATI->MMIOCache))
@@ -2299,18 +2274,7 @@ NoVGAWonder:;
ATIPtrs[j - 1] = NULL;
/* Fill in probe data */
- pScreenInfo->driverVersion = ATI_VERSION_CURRENT;
- pScreenInfo->driverName = ATI_DRIVER_NAME;
- pScreenInfo->name = ATI_NAME;
- pScreenInfo->Probe = ATIProbe;
- pScreenInfo->PreInit = ATIPreInit;
- pScreenInfo->ScreenInit = ATIScreenInit;
- pScreenInfo->SwitchMode = ATISwitchMode;
- pScreenInfo->AdjustFrame = ATIAdjustFrame;
- pScreenInfo->EnterVT = ATIEnterVT;
- pScreenInfo->LeaveVT = ATILeaveVT;
- pScreenInfo->FreeScreen = ATIFreeScreen;
- pScreenInfo->ValidMode = ATIValidMode;
+ ATIFillInScreenInfo(pScreenInfo);
pScreenInfo->driverPrivate = pATI;
diff --git a/src/atiregs.h b/src/atiregs.h
index fd80e745..4c35c2b6 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 822600d7..33e8a322 100644
--- a/src/atiscreen.c
+++ b/src/atiscreen.c
@@ -19,17 +19,33 @@
* 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"
+
+#ifdef XF86DRI_DEVEL
+#include "mach64_dri.h"
+#include "mach64_sarea.h"
+#endif
#include "shadowfb.h"
#include "xf86cmap.h"
@@ -81,6 +97,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 +132,9 @@ ATIScreenInit
ATIPtr pATI = ATIPTR(pScreenInfo);
pointer pFB;
int VisualMask;
+#ifdef XF86DRI_DEVEL
+ BoxRec ScreenArea;
+#endif
/* Set video hardware state */
if (!ATIEnterGraphics(pScreen, pScreenInfo, pATI))
@@ -122,6 +159,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 +173,50 @@ ATIScreenInit
}
}
+#ifdef XF86DRI_DEVEL
+
+ /* 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_DEVEL */
+
/* Initialise framebuffer layer */
switch (pATI->bitsPerPixel)
{
@@ -234,7 +317,183 @@ ATIScreenInit
#endif /* AVOID_CPIO */
+ /* Memory manager setup */
+
+#ifdef XF86DRI_DEVEL
+
+ 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_DEVEL */
+
/* 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 +553,26 @@ ATIScreenInit
if (serverGeneration == 1)
xf86ShowUnusedOptions(pScreenInfo->scrnIndex, pScreenInfo->options);
+#ifdef XF86DRI_DEVEL
+
+ /* 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_DEVEL */
+
return TRUE;
}
@@ -313,6 +592,17 @@ ATICloseScreen
ATIPtr pATI = ATIPTR(pScreenInfo);
Bool Closed = TRUE;
+#ifdef XF86DRI_DEVEL
+
+ /* Disable direct rendering */
+ if (pATI->directRenderingEnabled)
+ {
+ ATIDRICloseScreen(pScreen);
+ pATI->directRenderingEnabled = FALSE;
+ }
+
+#endif /* XF86DRI_DEVEL */
+
ATICloseXVideo(pScreen, pScreenInfo, pATI);
if (pATI->pXAAInfo)
diff --git a/src/atistruct.h b/src/atistruct.h
index a80c8b43..87ff0a1c 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_DEVEL
+
+/*
+ * DRI support
+ */
+#define _XF86DRI_SERVER_
+#include "atidripriv.h"
+#include "mach64_dri.h"
+#include "sarea.h"
+#include "xf86dri.h"
+#include "dri.h"
+
+#endif /* XF86DRI_DEVEL */
+
#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
@@ -436,6 +454,37 @@ typedef struct _ATIRec
* Wrapped functions.
*/
CloseScreenProcPtr CloseScreen;
+
+#ifdef XF86DRI_DEVEL
+
+ /*
+ * 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_DEVEL */
+
} ATIRec;
#define ATIPTR(_p) ((ATIPtr)((_p)->driverPrivate))
diff --git a/src/mach64_common.h b/src/mach64_common.h
new file mode 100644
index 00000000..00609e31
--- /dev/null
+++ b/src/mach64_common.h
@@ -0,0 +1,131 @@
+/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
+/* mach64_common.h -- common header definitions for Rage Pro 2D/3D/DRM suite
+ * Created: Sun Dec 03 11:34:16 2000 by gareth@valinux.com
+ *
+ * Copyright 2000 Gareth Hughes
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * GARETH HUGHES 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.
+ *
+ * Author:
+ * Gareth Hughes <gareth@valinux.com>
+ * Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+#ifndef __MACH64_COMMON_H__
+#define __MACH64_COMMON_H__ 1
+
+/* WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (mach64_drm.h)
+ */
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_MACH64_INIT 0x00
+#define DRM_MACH64_IDLE 0x01
+#define DRM_MACH64_RESET 0x02
+#define DRM_MACH64_SWAP 0x03
+#define DRM_MACH64_CLEAR 0x04
+#define DRM_MACH64_VERTEX 0x05
+#define DRM_MACH64_BLIT 0x06
+#define DRM_MACH64_FLUSH 0x07
+#define DRM_MACH64_GETPARAM 0x08
+
+/* Buffer flags for clears
+ */
+#define MACH64_FRONT 0x1
+#define MACH64_BACK 0x2
+#define MACH64_DEPTH 0x4
+
+/* Primitive types for vertex buffers
+ */
+#define MACH64_PRIM_POINTS 0x00000000
+#define MACH64_PRIM_LINES 0x00000001
+#define MACH64_PRIM_LINE_LOOP 0x00000002
+#define MACH64_PRIM_LINE_STRIP 0x00000003
+#define MACH64_PRIM_TRIANGLES 0x00000004
+#define MACH64_PRIM_TRIANGLE_STRIP 0x00000005
+#define MACH64_PRIM_TRIANGLE_FAN 0x00000006
+#define MACH64_PRIM_QUADS 0x00000007
+#define MACH64_PRIM_QUAD_STRIP 0x00000008
+#define MACH64_PRIM_POLYGON 0x00000009
+
+
+typedef enum _drmMach64DMAMode {
+ MACH64_MODE_DMA_ASYNC,
+ MACH64_MODE_DMA_SYNC,
+ MACH64_MODE_MMIO
+} drmMach64DMAMode;
+
+typedef struct {
+ enum {
+ DRM_MACH64_INIT_DMA = 0x01,
+ DRM_MACH64_CLEANUP_DMA = 0x02
+ } func;
+ unsigned long sarea_priv_offset;
+ int is_pci;
+ drmMach64DMAMode dma_mode;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ unsigned long fb_offset;
+ unsigned long mmio_offset;
+ unsigned long ring_offset;
+ unsigned long buffers_offset;
+ unsigned long agp_textures_offset;
+} drmMach64Init;
+
+typedef struct {
+ unsigned int flags;
+ int x, y, w, h;
+ unsigned int clear_color;
+ unsigned int clear_depth;
+} drmMach64Clear;
+
+typedef struct {
+ int prim;
+ void *buf; /* Address of vertex buffer */
+ unsigned long used; /* Number of bytes in buffer */
+ int discard; /* Client finished with buffer? */
+} drmMach64Vertex;
+
+typedef struct {
+ int idx;
+ int pitch;
+ int offset;
+ int format;
+ unsigned short x, y;
+ unsigned short width, height;
+} drmMach64Blit;
+
+typedef struct {
+ int param;
+ int *value;
+} drmMach64GetParam;
+
+#define MACH64_PARAM_FRAMES_QUEUED 1
+#define MACH64_PARAM_IRQ_NR 2
+
+#endif /* __MACH64_COMMON_H__ */
diff --git a/src/mach64_dri.h b/src/mach64_dri.h
new file mode 100644
index 00000000..139668e3
--- /dev/null
+++ b/src/mach64_dri.h
@@ -0,0 +1,126 @@
+/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * Copyright 2000 Gareth Hughes
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * GARETH HUGHES 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.
+ */
+
+/*
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ * Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+#ifndef __MACH64_DRI_H__
+#define __MACH64_DRI_H__ 1
+
+#include "xf86drm.h"
+
+typedef struct {
+ drm_handle_t fbHandle;
+
+ drm_handle_t regsHandle;
+ drmSize regsSize;
+
+ int IsPCI;
+
+ drm_handle_t agpHandle; /* Handle from drmAgpAlloc */
+ unsigned long agpOffset;
+ drmSize agpSize;
+ int agpMode;
+
+ /* DMA descriptor ring */
+ unsigned long ringStart; /* Offset into AGP space */
+ drm_handle_t ringHandle; /* Handle from drmAddMap */
+ drmSize ringMapSize; /* Size of map */
+ int ringSize; /* Size of ring (in kB) */
+ drmAddress ringMap; /* Map */
+
+ /* vertex buffer data */
+ unsigned long bufferStart; /* Offset into AGP space */
+ drm_handle_t bufferHandle; /* Handle from drmAddMap */
+ drmSize bufferMapSize; /* Size of map */
+ int bufferSize; /* Size of buffers (in MB) */
+ drmAddress bufferMap; /* Map */
+
+ drmBufMapPtr drmBuffers; /* Buffer map */
+ int numBuffers; /* Number of buffers */
+
+ /* AGP Texture data */
+ unsigned long agpTexStart; /* Offset into AGP space */
+ drm_handle_t agpTexHandle; /* Handle from drmAddMap */
+ drmSize agpTexMapSize; /* Size of map */
+ int agpTexSize; /* Size of AGP tex space (in MB) */
+ drmAddress agpTexMap; /* Map */
+ int log2AGPTexGran;
+
+ int fbX;
+ int fbY;
+ int backX;
+ int backY;
+ int depthX;
+ int depthY;
+
+ int frontOffset;
+ int frontPitch;
+ int backOffset;
+ int backPitch;
+ int depthOffset;
+ int depthPitch;
+
+ int textureOffset;
+ int textureSize;
+ int logTextureGranularity;
+} ATIDRIServerInfoRec, *ATIDRIServerInfoPtr;
+
+typedef struct {
+ int chipset;
+ int width;
+ int height;
+ int mem;
+ int cpp;
+
+ int IsPCI;
+ int AGPMode;
+
+ unsigned int frontOffset;
+ unsigned int frontPitch;
+
+ unsigned int backOffset;
+ unsigned int backPitch;
+
+ unsigned int depthOffset;
+ unsigned int depthPitch;
+
+ unsigned int textureOffset;
+ unsigned int textureSize;
+ int logTextureGranularity;
+
+ drm_handle_t regs;
+ drmSize regsSize;
+
+ drm_handle_t agp;
+ drmSize agpSize;
+ unsigned int agpTextureOffset;
+ unsigned int agpTextureSize;
+ int logAgpTextureGranularity;
+} ATIDRIRec, *ATIDRIPtr;
+
+#endif /* __MACH64_DRI_H__ */
diff --git a/src/mach64_sarea.h b/src/mach64_sarea.h
new file mode 100644
index 00000000..47a4bf9a
--- /dev/null
+++ b/src/mach64_sarea.h
@@ -0,0 +1,163 @@
+/* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
+/*
+ * Copyright 2000 Gareth Hughes
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * GARETH HUGHES 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.
+ */
+
+/*
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ * Leif Delgass <ldelgass@retinalburn.net>
+ */
+
+#ifndef __MACH64_SAREA_H__
+#define __MACH64_SAREA_H__ 1
+
+#include "Xmd.h"
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the kernel file (mach64_drm.h)
+ */
+#ifndef __MACH64_SAREA_DEFINES__
+#define __MACH64_SAREA_DEFINES__ 1
+
+/* What needs to be changed for the current vertex buffer?
+ * GH: We're going to be pedantic about this. We want the card to do as
+ * little as possible, so let's avoid having it fetch a whole bunch of
+ * register values that don't change all that often, if at all.
+ */
+#define MACH64_UPLOAD_DST_OFF_PITCH 0x0001
+#define MACH64_UPLOAD_Z_OFF_PITCH 0x0002
+#define MACH64_UPLOAD_Z_ALPHA_CNTL 0x0004
+#define MACH64_UPLOAD_SCALE_3D_CNTL 0x0008
+#define MACH64_UPLOAD_DP_FOG_CLR 0x0010
+#define MACH64_UPLOAD_DP_WRITE_MASK 0x0020
+#define MACH64_UPLOAD_DP_PIX_WIDTH 0x0040
+#define MACH64_UPLOAD_SETUP_CNTL 0x0080
+#define MACH64_UPLOAD_MISC 0x0100
+#define MACH64_UPLOAD_TEXTURE 0x0200
+#define MACH64_UPLOAD_TEX0IMAGE 0x0400
+#define MACH64_UPLOAD_TEX1IMAGE 0x0800
+#define MACH64_UPLOAD_CLIPRECTS 0x1000 /* handled client-side */
+#define MACH64_UPLOAD_CONTEXT 0x00ff
+#define MACH64_UPLOAD_ALL 0x1fff
+
+/* DMA buffer size
+ */
+#define MACH64_BUFFER_SIZE 16384
+
+/* Max number of swaps allowed on the ring
+ * before the client must wait
+ */
+#define MACH64_MAX_QUEUED_FRAMES 3
+
+/* Byte offsets for host blit buffer data
+ */
+#define MACH64_HOSTDATA_BLIT_OFFSET 104
+
+/* Keep these small for testing.
+ */
+#define MACH64_NR_SAREA_CLIPRECTS 8
+
+
+#define MACH64_CARD_HEAP 0
+#define MACH64_AGP_HEAP 1
+#define MACH64_NR_TEX_HEAPS 2
+#define MACH64_NR_TEX_REGIONS 64
+#define MACH64_LOG_TEX_GRANULARITY 16
+
+#define MACH64_TEX_MAXLEVELS 1
+
+#define MACH64_NR_CONTEXT_REGS 15
+#define MACH64_NR_TEXTURE_REGS 4
+
+#endif /* __MACH64_SAREA_DEFINES__ */
+
+typedef struct {
+ /* Context state */
+ unsigned int dst_off_pitch; /* 0x500 */
+
+ unsigned int z_off_pitch; /* 0x548 */ /* ****** */
+ unsigned int z_cntl; /* 0x54c */
+ unsigned int alpha_tst_cntl; /* 0x550 */
+
+ unsigned int scale_3d_cntl; /* 0x5fc */
+
+ unsigned int sc_left_right; /* 0x6a8 */
+ unsigned int sc_top_bottom; /* 0x6b4 */
+
+ unsigned int dp_fog_clr; /* 0x6c4 */
+ unsigned int dp_write_mask; /* 0x6c8 */
+ unsigned int dp_pix_width; /* 0x6d0 */
+ unsigned int dp_mix; /* 0x6d4 */ /* ****** */
+ unsigned int dp_src; /* 0x6d8 */ /* ****** */
+
+ unsigned int clr_cmp_cntl; /* 0x708 */ /* ****** */
+ unsigned int gui_traj_cntl; /* 0x730 */ /* ****** */
+
+ unsigned int setup_cntl; /* 0x304 */
+
+ /* Texture state */
+ unsigned int tex_size_pitch; /* 0x770 */
+ unsigned int tex_cntl; /* 0x774 */
+ unsigned int secondary_tex_off; /* 0x778 */
+ unsigned int tex_offset; /* 0x5c0 */
+} mach64_context_regs_t;
+
+typedef struct {
+ /* The channel for communication of state information to the kernel
+ * on firing a vertex buffer.
+ */
+ mach64_context_regs_t ContextState;
+ unsigned int dirty;
+ unsigned int vertsize;
+
+#ifdef XF86DRI
+ /* The current cliprects, or a subset thereof.
+ */
+ drm_clip_rect_t boxes[MACH64_NR_SAREA_CLIPRECTS];
+ unsigned int nbox;
+#endif
+ /* Counter for throttling of rendering clients.
+ */
+ unsigned int frames_queued;
+
+ /* Maintain an LRU of contiguous regions of texture space. If you
+ * think you own a region of texture memory, and it has an age
+ * different to the one you set, then you are mistaken and it has
+ * been stolen by another client. If global texAge hasn't changed,
+ * there is no need to walk the list.
+ *
+ * These regions can be used as a proxy for the fine-grained texture
+ * information of other clients - by maintaining them in the same
+ * lru which is used to age their own textures, clients have an
+ * approximate lru for the whole of global texture space, and can
+ * make informed decisions as to which areas to kick out. There is
+ * no need to choose whether to kick out your own texture or someone
+ * else's - simply eject them all in LRU order.
+ */
+ drmTextureRegion texList[MACH64_NR_TEX_HEAPS][MACH64_NR_TEX_REGIONS+1];
+ unsigned int texAge[MACH64_NR_TEX_HEAPS];
+
+ int ctxOwner; /* last context to upload state */
+} ATISAREAPrivRec, *ATISAREAPrivPtr;
+
+#endif /* __MACH64_SAREA_H__ */
diff --git a/src/r128.h b/src/r128.h
index 3b477551..b5c203aa 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 44bc2d45..90c5cb5f 100644
--- a/src/r128_accel.c
+++ b/src/r128_accel.c
@@ -86,6 +86,7 @@
#include "r128_sarea.h"
#define _XF86DRI_SERVER_
#include "r128_dri.h"
+#include "r128_common.h"
#endif
/* Line support */
diff --git a/src/r128_chipset.h b/src/r128_chipset.h
new file mode 100644
index 00000000..e896f76e
--- /dev/null
+++ b/src/r128_chipset.h
@@ -0,0 +1,54 @@
+static SymTabRec R128Chipsets[] = {
+ /* FIXME: The chipsets with (PCI/AGP) are not known wether they are AGP or
+ * PCI, so I've labeled them as such in hopes users will submit
+ * data if we're unable to gather it from official documentation
+ */
+ { PCI_CHIP_RAGE128LE, "ATI Rage 128 Mobility M3 LE (PCI)" },
+ { PCI_CHIP_RAGE128LF, "ATI Rage 128 Mobility M3 LF (AGP)" },
+ { PCI_CHIP_RAGE128MF, "ATI Rage 128 Mobility M4 MF (AGP)" },
+ { PCI_CHIP_RAGE128ML, "ATI Rage 128 Mobility M4 ML (AGP)" },
+ { PCI_CHIP_RAGE128PA, "ATI Rage 128 Pro GL PA (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PB, "ATI Rage 128 Pro GL PB (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PC, "ATI Rage 128 Pro GL PC (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PD, "ATI Rage 128 Pro GL PD (PCI)" },
+ { PCI_CHIP_RAGE128PE, "ATI Rage 128 Pro GL PE (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PF, "ATI Rage 128 Pro GL PF (AGP)" },
+ { PCI_CHIP_RAGE128PG, "ATI Rage 128 Pro VR PG (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PH, "ATI Rage 128 Pro VR PH (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PI, "ATI Rage 128 Pro VR PI (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PJ, "ATI Rage 128 Pro VR PJ (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PK, "ATI Rage 128 Pro VR PK (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PL, "ATI Rage 128 Pro VR PL (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PM, "ATI Rage 128 Pro VR PM (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PN, "ATI Rage 128 Pro VR PN (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PO, "ATI Rage 128 Pro VR PO (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PP, "ATI Rage 128 Pro VR PP (PCI)" },
+ { PCI_CHIP_RAGE128PQ, "ATI Rage 128 Pro VR PQ (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PR, "ATI Rage 128 Pro VR PR (PCI)" },
+ { PCI_CHIP_RAGE128PS, "ATI Rage 128 Pro VR PS (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PT, "ATI Rage 128 Pro VR PT (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PU, "ATI Rage 128 Pro VR PU (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PV, "ATI Rage 128 Pro VR PV (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PW, "ATI Rage 128 Pro VR PW (PCI/AGP)" },
+ { PCI_CHIP_RAGE128PX, "ATI Rage 128 Pro VR PX (PCI/AGP)" },
+ { PCI_CHIP_RAGE128RE, "ATI Rage 128 GL RE (PCI)" },
+ { PCI_CHIP_RAGE128RF, "ATI Rage 128 GL RF (AGP)" },
+ { PCI_CHIP_RAGE128RG, "ATI Rage 128 RG (AGP)" },
+ { PCI_CHIP_RAGE128RK, "ATI Rage 128 VR RK (PCI)" },
+ { PCI_CHIP_RAGE128RL, "ATI Rage 128 VR RL (AGP)" },
+ { PCI_CHIP_RAGE128SE, "ATI Rage 128 4X SE (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SF, "ATI Rage 128 4X SF (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SG, "ATI Rage 128 4X SG (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SH, "ATI Rage 128 4X SH (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SK, "ATI Rage 128 4X SK (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SL, "ATI Rage 128 4X SL (PCI/AGP)" },
+ { PCI_CHIP_RAGE128SM, "ATI Rage 128 4X SM (AGP)" },
+ { PCI_CHIP_RAGE128SN, "ATI Rage 128 4X SN (PCI/AGP)" },
+ { PCI_CHIP_RAGE128TF, "ATI Rage 128 Pro ULTRA TF (AGP)" },
+ { PCI_CHIP_RAGE128TL, "ATI Rage 128 Pro ULTRA TL (AGP)" },
+ { PCI_CHIP_RAGE128TR, "ATI Rage 128 Pro ULTRA TR (AGP)" },
+ { PCI_CHIP_RAGE128TS, "ATI Rage 128 Pro ULTRA TS (AGP?)" },
+ { PCI_CHIP_RAGE128TT, "ATI Rage 128 Pro ULTRA TT (AGP?)" },
+ { PCI_CHIP_RAGE128TU, "ATI Rage 128 Pro ULTRA TU (AGP?)" },
+ { -1, NULL }
+};
diff --git a/src/r128_dri.c b/src/r128_dri.c
index e185a279..2b35c334 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"
@@ -55,15 +56,7 @@
#include "GL/glxtokens.h"
#include "sarea.h"
-/* ?? HACK - for now, put this here... */
-/* ?? Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
-#if defined(__alpha__)
-# define DRM_PAGE_SIZE 8192
-#elif defined(__ia64__)
-# define DRM_PAGE_SIZE getpagesize()
-#else
-# define DRM_PAGE_SIZE 4096
-#endif
+static size_t r128_drm_page_size;
static void R128DRITransitionTo2d(ScreenPtr pScreen);
static void R128DRITransitionTo3d(ScreenPtr pScreen);
@@ -277,7 +270,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 +281,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 */
@@ -501,11 +494,11 @@ static Bool R128DRIAgpInit(R128InfoPtr info, ScreenPtr pScreen)
/* Initialize the CCE ring buffer data */
info->ringStart = info->agpOffset;
- info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size;
info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
info->ringReadOffset = info->ringStart + info->ringMapSize;
- info->ringReadMapSize = DRM_PAGE_SIZE;
+ info->ringReadMapSize = r128_drm_page_size;
/* Reserve space for vertex/indirect buffers */
info->bufStart = info->ringReadOffset + info->ringReadMapSize;
@@ -654,11 +647,11 @@ static Bool R128DRIPciInit(R128InfoPtr info, ScreenPtr pScreen)
/* Initialize the CCE ring buffer data */
info->ringStart = info->agpOffset;
- info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringMapSize = info->ringSize*1024*1024 + r128_drm_page_size;
info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
info->ringReadOffset = info->ringStart + info->ringMapSize;
- info->ringReadMapSize = DRM_PAGE_SIZE;
+ info->ringReadMapSize = r128_drm_page_size;
/* Reserve space for vertex/indirect buffers */
info->bufStart = info->ringReadOffset + info->ringReadMapSize;
@@ -1015,6 +1008,8 @@ Bool R128DRIScreenInit(ScreenPtr pScreen)
break;
}
+ r128_drm_page_size = getpagesize();
+
/* Create the DRI data structure, and fill it in before calling the
DRIScreenInit(). */
if (!(pDRIInfo = DRICreateInfoRec())) return FALSE;
@@ -1022,12 +1017,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;
@@ -1473,6 +1472,10 @@ 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);
diff --git a/src/r128_dri.h b/src/r128_dri.h
index 64345d3c..a20ec59a 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 cd8b9954..8167d00c 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
@@ -90,6 +91,8 @@
#include "vgaHW.h"
#include "dixstruct.h"
+#include "r128_chipset.h"
+
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
@@ -137,7 +140,7 @@ typedef enum {
OPTION_SHOW_CACHE
} R128Opts;
-const OptionInfoRec R128Options[] = {
+static const OptionInfoRec R128Options[] = {
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE },
@@ -164,6 +167,8 @@ const OptionInfoRec R128Options[] = {
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
+const OptionInfoRec *R128OptionsWeak(void) { return R128Options; }
+
R128RAMRec R128RAM[] = { /* Memory Specifications
From RAGE 128 Software Development
Manual (Technical Reference Manual P/N
@@ -192,19 +197,23 @@ static const char *fbdevHWSymbols[] = {
"fbdevHWGetVidmem",
"fbdevHWDPMSSet",
+ "fbdevHWDPMSSetWeak",
/* colormap */
"fbdevHWLoadPalette",
+ "fbdevHWLoadPaletteWeak",
/* ScrnInfo hooks */
"fbdevHWAdjustFrame",
+ "fbdevHWAdjustFrameWeak",
"fbdevHWEnterVT",
"fbdevHWLeaveVT",
"fbdevHWModeInit",
"fbdevHWRestore",
"fbdevHWSave",
"fbdevHWSwitchMode",
- "fbdevHWValidMode",
+ "fbdevHWSwitchModeWeak",
+ "fbdevHWValidModeWeak",
"fbdevHWMapMMIO",
"fbdevHWMapVidmem",
@@ -296,6 +305,7 @@ static const char *driSymbols[] = {
"DRIScreenInit",
"DRIUnlock",
"GlxSetVisualConfigs",
+ "DRICreatePCIBusID",
NULL
};
@@ -1917,9 +1927,9 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
if (!xf86LoadSubModule(pScrn, "fbdevhw")) return FALSE;
xf86LoaderReqSymLists(fbdevHWSymbols, NULL);
if (!fbdevHWInit(pScrn, info->PciInfo, NULL)) return FALSE;
- pScrn->SwitchMode = fbdevHWSwitchMode;
- pScrn->AdjustFrame = fbdevHWAdjustFrame;
- pScrn->ValidMode = fbdevHWValidMode;
+ pScrn->SwitchMode = fbdevHWSwitchModeWeak();
+ pScrn->AdjustFrame = fbdevHWAdjustFrameWeak();
+ pScrn->ValidMode = fbdevHWValidModeWeak();
}
if (!info->FBDev)
@@ -1957,7 +1967,7 @@ Bool R128PreInit(ScrnInfoPtr pScrn, int flags)
xf86FreeInt10(pInt10);
xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
- "For information on using the multimedia capabilities\n of this"
+ "For information on using the multimedia capabilities\n\tof this"
" adapter, please see http://gatos.sf.net.\n");
return TRUE;
@@ -2423,7 +2433,7 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
/* Colormap setup */
if (!miCreateDefColormap(pScreen)) return FALSE;
if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8,
- (info->FBDev ? fbdevHWLoadPalette :
+ (info->FBDev ? fbdevHWLoadPaletteWeak() :
R128LoadPalette), NULL,
CMAP_PALETTED_TRUECOLOR
| CMAP_RELOAD_ON_MODE_SWITCH
@@ -2434,7 +2444,7 @@ Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
/* DPMS setup - FIXME: also for mirror mode in non-fbdev case? - Michel */
if (info->FBDev)
- xf86DPMSInit(pScreen, fbdevHWDPMSSet, 0);
+ xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
else {
if (!info->HasPanelRegs || info->BIOSDisplay == R128_BIOS_DISPLAY_CRT)
xf86DPMSInit(pScreen, R128DisplayPowerManagementSet, 0);
@@ -3672,4 +3682,19 @@ static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on)
OUTREG(R128_LVDS_GEN_CNTL, lvds_gen_cntl);
return 0;
- }
+}
+
+void R128FillInScreenInfo(ScrnInfoPtr pScrn)
+{
+ pScrn->driverVersion = R128_VERSION_CURRENT;
+ pScrn->driverName = R128_DRIVER_NAME;
+ pScrn->name = R128_NAME;
+ pScrn->PreInit = R128PreInit;
+ pScrn->ScreenInit = R128ScreenInit;
+ pScrn->SwitchMode = R128SwitchMode;
+ pScrn->AdjustFrame = R128AdjustFrame;
+ pScrn->EnterVT = R128EnterVT;
+ pScrn->LeaveVT = R128LeaveVT;
+ pScrn->FreeScreen = R128FreeScreen;
+ pScrn->ValidMode = R128ValidMode;
+}
diff --git a/src/r128_misc.c b/src/r128_misc.c
index 30202b3f..dd77061a 100644
--- a/src/r128_misc.c
+++ b/src/r128_misc.c
@@ -38,7 +38,7 @@ static XF86ModuleVersionInfo R128VersionRec =
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
- XF86_VERSION_CURRENT,
+ XORG_VERSION_CURRENT,
R128_VERSION_MAJOR, R128_VERSION_MINOR, R128_VERSION_PATCH,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
diff --git a/src/r128_probe.c b/src/r128_probe.c
index d017b358..08b3595a 100644
--- a/src/r128_probe.c
+++ b/src/r128_probe.c
@@ -48,86 +48,7 @@
#include "xf86_ansic.h"
#include "xf86Resources.h"
-#ifdef XFree86LOADER
-
-/*
- * The following exists to prevent the compiler from considering entry points
- * defined in a separate module from being constants.
- */
-static xf86PreInitProc * const volatile PreInitProc = R128PreInit;
-static xf86ScreenInitProc * const volatile ScreenInitProc = R128ScreenInit;
-static xf86SwitchModeProc * const volatile SwitchModeProc = R128SwitchMode;
-static xf86AdjustFrameProc * const volatile AdjustFrameProc = R128AdjustFrame;
-static xf86EnterVTProc * const volatile EnterVTProc = R128EnterVT;
-static xf86LeaveVTProc * const volatile LeaveVTProc = R128LeaveVT;
-static xf86FreeScreenProc * const volatile FreeScreenProc = R128FreeScreen;
-static xf86ValidModeProc * const volatile ValidModeProc = R128ValidMode;
-
-#define R128PreInit PreInitProc
-#define R128ScreenInit ScreenInitProc
-#define R128SwitchMode SwitchModeProc
-#define R128AdjustFrame AdjustFrameProc
-#define R128EnterVT EnterVTProc
-#define R128LeaveVT LeaveVTProc
-#define R128FreeScreen FreeScreenProc
-#define R128ValidMode ValidModeProc
-
-#endif
-
-SymTabRec R128Chipsets[] = {
- /* FIXME: The chipsets with (PCI/AGP) are not known wether they are AGP or
- * PCI, so I've labeled them as such in hopes users will submit
- * data if we're unable to gather it from official documentation
- */
- { PCI_CHIP_RAGE128LE, "ATI Rage 128 Mobility M3 LE (PCI)" },
- { PCI_CHIP_RAGE128LF, "ATI Rage 128 Mobility M3 LF (AGP)" },
- { PCI_CHIP_RAGE128MF, "ATI Rage 128 Mobility M4 MF (AGP)" },
- { PCI_CHIP_RAGE128ML, "ATI Rage 128 Mobility M4 ML (AGP)" },
- { PCI_CHIP_RAGE128PA, "ATI Rage 128 Pro GL PA (PCI/AGP)" },
- { PCI_CHIP_RAGE128PB, "ATI Rage 128 Pro GL PB (PCI/AGP)" },
- { PCI_CHIP_RAGE128PC, "ATI Rage 128 Pro GL PC (PCI/AGP)" },
- { PCI_CHIP_RAGE128PD, "ATI Rage 128 Pro GL PD (PCI)" },
- { PCI_CHIP_RAGE128PE, "ATI Rage 128 Pro GL PE (PCI/AGP)" },
- { PCI_CHIP_RAGE128PF, "ATI Rage 128 Pro GL PF (AGP)" },
- { PCI_CHIP_RAGE128PG, "ATI Rage 128 Pro VR PG (PCI/AGP)" },
- { PCI_CHIP_RAGE128PH, "ATI Rage 128 Pro VR PH (PCI/AGP)" },
- { PCI_CHIP_RAGE128PI, "ATI Rage 128 Pro VR PI (PCI/AGP)" },
- { PCI_CHIP_RAGE128PJ, "ATI Rage 128 Pro VR PJ (PCI/AGP)" },
- { PCI_CHIP_RAGE128PK, "ATI Rage 128 Pro VR PK (PCI/AGP)" },
- { PCI_CHIP_RAGE128PL, "ATI Rage 128 Pro VR PL (PCI/AGP)" },
- { PCI_CHIP_RAGE128PM, "ATI Rage 128 Pro VR PM (PCI/AGP)" },
- { PCI_CHIP_RAGE128PN, "ATI Rage 128 Pro VR PN (PCI/AGP)" },
- { PCI_CHIP_RAGE128PO, "ATI Rage 128 Pro VR PO (PCI/AGP)" },
- { PCI_CHIP_RAGE128PP, "ATI Rage 128 Pro VR PP (PCI)" },
- { PCI_CHIP_RAGE128PQ, "ATI Rage 128 Pro VR PQ (PCI/AGP)" },
- { PCI_CHIP_RAGE128PR, "ATI Rage 128 Pro VR PR (PCI)" },
- { PCI_CHIP_RAGE128PS, "ATI Rage 128 Pro VR PS (PCI/AGP)" },
- { PCI_CHIP_RAGE128PT, "ATI Rage 128 Pro VR PT (PCI/AGP)" },
- { PCI_CHIP_RAGE128PU, "ATI Rage 128 Pro VR PU (PCI/AGP)" },
- { PCI_CHIP_RAGE128PV, "ATI Rage 128 Pro VR PV (PCI/AGP)" },
- { PCI_CHIP_RAGE128PW, "ATI Rage 128 Pro VR PW (PCI/AGP)" },
- { PCI_CHIP_RAGE128PX, "ATI Rage 128 Pro VR PX (PCI/AGP)" },
- { PCI_CHIP_RAGE128RE, "ATI Rage 128 GL RE (PCI)" },
- { PCI_CHIP_RAGE128RF, "ATI Rage 128 GL RF (AGP)" },
- { PCI_CHIP_RAGE128RG, "ATI Rage 128 RG (AGP)" },
- { PCI_CHIP_RAGE128RK, "ATI Rage 128 VR RK (PCI)" },
- { PCI_CHIP_RAGE128RL, "ATI Rage 128 VR RL (AGP)" },
- { PCI_CHIP_RAGE128SE, "ATI Rage 128 4X SE (PCI/AGP)" },
- { PCI_CHIP_RAGE128SF, "ATI Rage 128 4X SF (PCI/AGP)" },
- { PCI_CHIP_RAGE128SG, "ATI Rage 128 4X SG (PCI/AGP)" },
- { PCI_CHIP_RAGE128SH, "ATI Rage 128 4X SH (PCI/AGP)" },
- { PCI_CHIP_RAGE128SK, "ATI Rage 128 4X SK (PCI/AGP)" },
- { PCI_CHIP_RAGE128SL, "ATI Rage 128 4X SL (PCI/AGP)" },
- { PCI_CHIP_RAGE128SM, "ATI Rage 128 4X SM (AGP)" },
- { PCI_CHIP_RAGE128SN, "ATI Rage 128 4X SN (PCI/AGP)" },
- { PCI_CHIP_RAGE128TF, "ATI Rage 128 Pro ULTRA TF (AGP)" },
- { PCI_CHIP_RAGE128TL, "ATI Rage 128 Pro ULTRA TL (AGP)" },
- { PCI_CHIP_RAGE128TR, "ATI Rage 128 Pro ULTRA TR (AGP)" },
- { PCI_CHIP_RAGE128TS, "ATI Rage 128 Pro ULTRA TS (AGP?)" },
- { PCI_CHIP_RAGE128TT, "ATI Rage 128 Pro ULTRA TT (AGP?)" },
- { PCI_CHIP_RAGE128TU, "ATI Rage 128 Pro ULTRA TU (AGP?)" },
- { -1, NULL }
-};
+#include "r128_chipset.h"
PciChipsets R128PciChipsets[] = {
{ PCI_CHIP_RAGE128LE, PCI_CHIP_RAGE128LE, RES_SHARED_VGA },
@@ -194,7 +115,7 @@ R128AvailableOptions(int chipid, int busid)
chipid -= PCI_VENDOR_ATI << 16;
for (i = 0; R128PciChipsets[i].PCIid > 0; i++) {
if (chipid == R128PciChipsets[i].PCIid)
- return R128Options;
+ return R128OptionsWeak();
}
return NULL;
}
@@ -280,18 +201,8 @@ R128Probe(DriverPtr drv, int flags)
#endif
- pScrn->driverVersion = R128_VERSION_CURRENT;
- pScrn->driverName = R128_DRIVER_NAME;
- pScrn->name = R128_NAME;
pScrn->Probe = R128Probe;
- pScrn->PreInit = R128PreInit;
- pScrn->ScreenInit = R128ScreenInit;
- pScrn->SwitchMode = R128SwitchMode;
- pScrn->AdjustFrame = R128AdjustFrame;
- pScrn->EnterVT = R128EnterVT;
- pScrn->LeaveVT = R128LeaveVT;
- pScrn->FreeScreen = R128FreeScreen;
- pScrn->ValidMode = R128ValidMode;
+ R128FillInScreenInfo(pScrn);
foundScreen = TRUE;
diff --git a/src/r128_probe.h b/src/r128_probe.h
index 247a8f57..34810dd9 100644
--- a/src/r128_probe.h
+++ b/src/r128_probe.h
@@ -49,7 +49,6 @@ extern void R128Identify
extern Bool R128Probe
FunctionPrototype((DriverPtr, int));
-extern SymTabRec R128Chipsets[];
extern PciChipsets R128PciChipsets[];
/* r128_driver.c */
@@ -73,6 +72,10 @@ extern ModeStatus R128ValidMode
FunctionPrototype((int, DisplayModePtr, Bool,
int));
-extern const OptionInfoRec R128Options[];
+extern const OptionInfoRec * R128OptionsWeak
+ FunctionPrototype((void));
+
+extern void R128FillInScreenInfo
+ FunctionPrototype((ScrnInfoPtr));
#endif /* _R128_PROBE_H_ */
diff --git a/src/r128_reg.h b/src/r128_reg.h
index a0f21cf5..98b89bfa 100644
--- a/src/r128_reg.h
+++ b/src/r128_reg.h
@@ -1050,33 +1050,31 @@
# define R128_TEX_CACHE_PALLETE_MODE (1 << 11)
# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
# define R128_ALPHA_COMB_ADD_NCLAMP (1 << 12)
-# define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP (2 << 12)
-# define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12)
+# define R128_ALPHA_COMB_SUB_SRC_DST_NCLAMP (3 << 12)
+# define R128_ALPHA_COMB_FCN_MASK (3 << 12)
+# define R128_FOG_VERTEX (0 << 14)
# define R128_FOG_TABLE (1 << 14)
# define R128_SIGNED_DST_CLAMP (1 << 15)
-# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
-# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
-# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
-# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
-# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
-# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
-# define R128_ALPHA_BLEND_SRC_DSTALPHA (6 << 16)
-# define R128_ALPHA_BLEND_SRC_INVDSTALPHA (7 << 16)
-# define R128_ALPHA_BLEND_SRC_DSTCOLOR (8 << 16)
-# define R128_ALPHA_BLEND_SRC_INVDSTCOLOR (9 << 16)
-# define R128_ALPHA_BLEND_SRC_SAT (10 << 16)
-# define R128_ALPHA_BLEND_SRC_BLEND (11 << 16)
-# define R128_ALPHA_BLEND_SRC_INVBLEND (12 << 16)
-# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
-# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
-# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
-# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
-# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
-# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
-# define R128_ALPHA_BLEND_DST_DSTALPHA (6 << 20)
-# define R128_ALPHA_BLEND_DST_INVDSTALPHA (7 << 20)
-# define R128_ALPHA_BLEND_DST_DSTCOLOR (8 << 20)
-# define R128_ALPHA_BLEND_DST_INVDSTCOLOR (9 << 20)
+
+# define R128_ALPHA_BLEND_ZERO (0 )
+# define R128_ALPHA_BLEND_ONE (1 )
+# define R128_ALPHA_BLEND_SRCCOLOR (2 )
+# define R128_ALPHA_BLEND_INVSRCCOLOR (3 )
+# define R128_ALPHA_BLEND_SRCALPHA (4 )
+# define R128_ALPHA_BLEND_INVSRCALPHA (5 )
+# define R128_ALPHA_BLEND_DSTALPHA (6 )
+# define R128_ALPHA_BLEND_INVDSTALPHA (7 )
+# define R128_ALPHA_BLEND_DSTCOLOR (8 )
+# define R128_ALPHA_BLEND_INVDSTCOLOR (9 )
+# define R128_ALPHA_BLEND_SAT (10) /* aka SRCALPHASAT */
+# define R128_ALPHA_BLEND_BLEND (11) /* aka BOTHSRCALPHA */
+# define R128_ALPHA_BLEND_INVBLEND (12) /* aka BOTHINVSRCALPHA */
+# define R128_ALPHA_BLEND_MASK (15)
+
+# define R128_ALPHA_BLEND_SRC_SHIFT (16)
+# define R128_ALPHA_BLEND_DST_SHIFT (20)
+
# define R128_ALPHA_TEST_NEVER (0 << 24)
# define R128_ALPHA_TEST_LESS (1 << 24)
# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
@@ -1085,6 +1083,7 @@
# define R128_ALPHA_TEST_GREATER (5 << 24)
# define R128_ALPHA_TEST_NEQUAL (6 << 24)
# define R128_ALPHA_TEST_ALWAYS (7 << 24)
+# define R128_ALPHA_TEST_MASK (7 << 24)
# define R128_COMPOSITE_SHADOW_CMP_EQUAL (0 << 28)
# define R128_COMPOSITE_SHADOW_CMP_NEQUAL (1 << 28)
# define R128_COMPOSITE_SHADOW (1 << 29)
@@ -1205,47 +1204,11 @@
# define R128_MISC_SCALE_3D_TEXMAP_SHADE (2 << 8)
# define R128_MISC_SCALE_PIX_BLEND (0 << 10)
# define R128_MISC_SCALE_PIX_REPLICATE (1 << 10)
-# define R128_ALPHA_COMB_ADD_CLAMP (0 << 12)
-# define R128_ALPHA_COMB_ADD_NO_CLAMP (1 << 12)
-# define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP (2 << 12)
-# define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3 << 12)
-# define R128_FOG_VERTEX (0 << 14)
-# define R128_FOG_TABLE (1 << 14)
-# define R128_ALPHA_BLEND_SRC_ZERO (0 << 16)
-# define R128_ALPHA_BLEND_SRC_ONE (1 << 16)
-# define R128_ALPHA_BLEND_SRC_SRCCOLOR (2 << 16)
-# define R128_ALPHA_BLEND_SRC_INVSRCCOLOR (3 << 16)
-# define R128_ALPHA_BLEND_SRC_SRCALPHA (4 << 16)
-# define R128_ALPHA_BLEND_SRC_INVSRCALPHA (5 << 16)
-# define R128_ALPHA_BLEND_SRC_DESTALPHA (6 << 16)
-# define R128_ALPHA_BLEND_SRC_INVDESTALPHA (7 << 16)
-# define R128_ALPHA_BLEND_SRC_DESTCOLOR (8 << 16)
-# define R128_ALPHA_BLEND_SRC_INVDESTCOLOR (9 << 16)
-# define R128_ALPHA_BLEND_SRC_SRCALPHASAT (10 << 16)
-# define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA (11 << 16)
-# define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16)
-# define R128_ALPHA_BLEND_SRC_MASK (15 << 16)
-# define R128_ALPHA_BLEND_DST_ZERO (0 << 20)
-# define R128_ALPHA_BLEND_DST_ONE (1 << 20)
-# define R128_ALPHA_BLEND_DST_SRCCOLOR (2 << 20)
-# define R128_ALPHA_BLEND_DST_INVSRCCOLOR (3 << 20)
-# define R128_ALPHA_BLEND_DST_SRCALPHA (4 << 20)
-# define R128_ALPHA_BLEND_DST_INVSRCALPHA (5 << 20)
-# define R128_ALPHA_BLEND_DST_DESTALPHA (6 << 20)
-# define R128_ALPHA_BLEND_DST_INVDESTALPHA (7 << 20)
-# define R128_ALPHA_BLEND_DST_DESTCOLOR (8 << 20)
-# define R128_ALPHA_BLEND_DST_INVDESTCOLOR (9 << 20)
-# define R128_ALPHA_BLEND_DST_SRCALPHASAT (10 << 20)
-# define R128_ALPHA_BLEND_DST_MASK (15 << 20)
-# define R128_ALPHA_TEST_NEVER (0 << 24)
-# define R128_ALPHA_TEST_LESS (1 << 24)
-# define R128_ALPHA_TEST_LESSEQUAL (2 << 24)
-# define R128_ALPHA_TEST_EQUAL (3 << 24)
-# define R128_ALPHA_TEST_GREATEREQUAL (4 << 24)
-# define R128_ALPHA_TEST_GREATER (5 << 24)
-# define R128_ALPHA_TEST_NEQUAL (6 << 24)
-# define R128_ALPHA_TEST_ALWAYS (7 << 24)
-# define R128_ALPHA_TEST_MASK (7 << 24)
+/* Bits [14:12] are the same as R128_SCALE_3D_CNTL */
+/* Bit [15] is unknown */
+/* Bits [26:16] are the same as R128_SCALE_3D_CNTL */
+/* Bits [31:27] are unknown */
+
#define R128_TEXTURE_CLR_CMP_CLR_C 0x1ca4
#define R128_TEXTURE_CLR_CMP_MSK_C 0x1ca8
#define R128_FOG_COLOR_C 0x1cac
diff --git a/src/r128_sarea.h b/src/r128_sarea.h
index beb8cfe8..b9ad29d2 100644
--- a/src/r128_sarea.h
+++ b/src/r128_sarea.h
@@ -160,7 +160,7 @@ typedef struct {
/* 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;
/* Counters for throttling of rendering clients.
diff --git a/src/radeon.h b/src/radeon.h
index fd91e3d5..523d2b72 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -45,6 +45,7 @@
/* XAA and Cursor Support */
#include "xaa.h"
+#include "vbe.h"
#include "xf86Cursor.h"
/* DDC support */
@@ -53,6 +54,7 @@
/* Xv support */
#include "xf86xv.h"
+#include "radeon_probe.h"
/* DRI support */
#ifdef XF86DRI
#define _XF86DRI_SERVER_
@@ -66,6 +68,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 */
@@ -109,7 +132,10 @@ typedef struct {
CARD32 cap1_trig_cntl;
CARD32 bus_cntl;
CARD32 surface_cntl;
+ CARD32 bios_4_scratch;
CARD32 bios_5_scratch;
+ CARD32 bios_6_scratch;
+
/* Other registers to save for VT switches */
CARD32 dp_datatype;
CARD32 rbbm_soft_reset;
@@ -190,6 +216,9 @@ typedef struct {
Bool palette_valid;
CARD32 palette[256];
CARD32 palette2[256];
+
+ CARD32 tv_dac_cntl;
+
} RADEONSaveRec, *RADEONSavePtr;
typedef struct {
@@ -210,31 +239,6 @@ typedef struct {
} RADEONFBLayout;
typedef enum {
- MT_NONE,
- MT_CRT,
- MT_LCD,
- MT_DFP,
- MT_CTV,
- MT_STV
-} RADEONMonitorType;
-
-typedef enum {
- DDC_NONE_DETECTED,
- DDC_MONID,
- DDC_DVI,
- DDC_VGA,
- DDC_CRT2
-} RADEONDDCType;
-
-typedef enum {
- CONNECTOR_NONE,
- CONNECTOR_PROPRIETARY,
- CONNECTOR_CRT,
- CONNECTOR_DVI_I,
- CONNECTOR_DVI_D
-} RADEONConnectorType;
-
-typedef enum {
CHIP_FAMILY_UNKNOW,
CHIP_FAMILY_LEGACY,
CHIP_FAMILY_RADEON,
@@ -244,14 +248,32 @@ typedef enum {
CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350), RS250 (IGP 7000) */
CHIP_FAMILY_R200,
CHIP_FAMILY_RV250,
- CHIP_FAMILY_RS300, /* Radeon 9000 IGP */
+ CHIP_FAMILY_RS300, /* RS300/RS350 */
CHIP_FAMILY_RV280,
CHIP_FAMILY_R300,
CHIP_FAMILY_R350,
CHIP_FAMILY_RV350,
+ CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
+ CHIP_FAMILY_R420, /* R420/R423/M18 */
CHIP_FAMILY_LAST
} RADEONChipFamily;
+#define IS_RV100_VARIANT ((info->ChipFamily == CHIP_FAMILY_RV100) || \
+ (info->ChipFamily == CHIP_FAMILY_RV200) || \
+ (info->ChipFamily == CHIP_FAMILY_RS100) || \
+ (info->ChipFamily == CHIP_FAMILY_RS200) || \
+ (info->ChipFamily == CHIP_FAMILY_RV250) || \
+ (info->ChipFamily == CHIP_FAMILY_RV280) || \
+ (info->ChipFamily == CHIP_FAMILY_RS300))
+
+
+#define IS_R300_VARIANT ((info->ChipFamily == CHIP_FAMILY_R300) || \
+ (info->ChipFamily == CHIP_FAMILY_RV350) || \
+ (info->ChipFamily == CHIP_FAMILY_R350) || \
+ (info->ChipFamily == CHIP_FAMILY_RV380) || \
+ (info->ChipFamily == CHIP_FAMILY_R420))
+
+
typedef struct {
CARD32 freq;
CARD32 value;
@@ -269,11 +291,16 @@ typedef struct {
unsigned long LinearAddr; /* Frame buffer physical address */
unsigned long MMIOAddr; /* MMIO region physical address */
unsigned long BIOSAddr; /* BIOS physical address */
+ unsigned int fbLocation;
unsigned char *MMIO; /* Map of MMIO region */
unsigned char *FB; /* Map of frame buffer */
CARD8 *VBIOS; /* Video BIOS pointer */
+ Bool IsAtomBios; /* New BIOS used in R420 etc. */
+ int ROMHeaderStart; /* Start of the ROM Info Table */
+ int MasterDataStart; /* Offset for Master Data Table for ATOM BIOS */
+
CARD32 MemCntl;
CARD32 BusCntl;
unsigned long FbMapSize; /* Size of frame buffer, in bytes */
@@ -286,18 +313,11 @@ typedef struct {
Bool HasCRTC2; /* All cards except original Radeon */
Bool IsMobility; /* Mobile chips for laptops */
Bool IsIGP; /* IGP chips */
+ Bool HasSingleDAC; /* only TVDAC on chip */
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 */
Bool ddc_mode; /* Validate mode by matching exactly
* the modes supported in DDC data
*/
@@ -412,14 +432,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! */
@@ -428,7 +448,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;
@@ -445,20 +465,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 */
@@ -467,7 +487,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 */
@@ -531,14 +551,53 @@ typedef struct {
FBLinearPtr videoLinear;
int videoKey;
+ /* Render */
+ Bool RenderAccel;
+ Bool RenderInited3D;
+ FBLinearPtr RenderTex;
+ void (*RenderCallback)(ScrnInfoPtr);
+ Time RenderTimeout;
+
/* general */
Bool showCache;
OptionInfoPtr Options;
#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;
+
+ /* special handlings for DELL triple-head server */
+ Bool IsDellServer;
} RADEONInfoRec, *RADEONInfoPtr;
+
#define RADEONWaitForFifo(pScrn, entries) \
do { \
if (info->fifo_slots < entries) \
@@ -546,6 +605,7 @@ do { \
info->fifo_slots -= entries; \
} while (0)
+extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn);
extern void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries);
extern void RADEONWaitForIdleMMIO(ScrnInfoPtr pScrn);
#ifdef XF86DRI
@@ -566,6 +626,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);
@@ -577,6 +638,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);
@@ -587,6 +649,12 @@ extern void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard);
extern void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn);
extern int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info);
+extern Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10);
+extern Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn);
+extern Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn);
+extern Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn);
+extern Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn);
+extern Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn);
#define RADEONCP_START(pScrn, info) \
do { \
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 52955d4a..62ce8794 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
@@ -110,8 +111,6 @@ static struct {
{ RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */
};
-extern int gRADEONEntityIndex;
-
/* The FIFO has 64 slots. This routines waits until at least `entries'
* of these slots are empty.
*/
@@ -174,6 +173,7 @@ void RADEONEngineReset(ScrnInfoPtr pScrn)
clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+#if 0 /* taken care of by new PM code */
/* Some ASICs have bugs with dynamic-on feature, which are
* ASIC-version dependent, so we force all blocks on for now
*/
@@ -190,8 +190,11 @@ void RADEONEngineReset(ScrnInfoPtr pScrn)
OUTPLL(RADEON_SCLK_MORE_CNTL, tmp | RADEON_SCLK_MORE_FORCEON);
}
}
+#endif /* new PM code */
mclk_cntl = INPLL(pScrn, RADEON_MCLK_CNTL);
+
+#if 0 /* handled by new PM code */
OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl |
RADEON_FORCEON_MCLKA |
RADEON_FORCEON_MCLKB |
@@ -199,6 +202,7 @@ void RADEONEngineReset(ScrnInfoPtr pScrn)
RADEON_FORCEON_YCLKB |
RADEON_FORCEON_MC |
RADEON_FORCEON_AIC));
+#endif /* new PM code */
/* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some
* unexpected behaviour on some machines. Here we use
@@ -207,9 +211,7 @@ void RADEONEngineReset(ScrnInfoPtr pScrn)
host_path_cntl = INREG(RADEON_HOST_PATH_CNTL);
rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);
- if ((info->ChipFamily == CHIP_FAMILY_R300) ||
- (info->ChipFamily == CHIP_FAMILY_R350) ||
- (info->ChipFamily == CHIP_FAMILY_RV350)) {
+ if (IS_R300_VARIANT) {
CARD32 tmp;
OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
@@ -223,7 +225,6 @@ void RADEONEngineReset(ScrnInfoPtr pScrn)
} else {
OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
RADEON_SOFT_RESET_CP |
- RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_SE |
RADEON_SOFT_RESET_RE |
RADEON_SOFT_RESET_PP |
@@ -232,7 +233,6 @@ void RADEONEngineReset(ScrnInfoPtr pScrn)
INREG(RADEON_RBBM_SOFT_RESET);
OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (CARD32)
~(RADEON_SOFT_RESET_CP |
- RADEON_SOFT_RESET_HI |
RADEON_SOFT_RESET_SE |
RADEON_SOFT_RESET_RE |
RADEON_SOFT_RESET_PP |
@@ -245,9 +245,7 @@ void RADEONEngineReset(ScrnInfoPtr pScrn)
INREG(RADEON_HOST_PATH_CNTL);
OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl);
- if ((info->ChipFamily != CHIP_FAMILY_R300) &&
- (info->ChipFamily != CHIP_FAMILY_R350) &&
- (info->ChipFamily != CHIP_FAMILY_RV350))
+ if (IS_R300_VARIANT)
OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
@@ -275,16 +273,14 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn)
*/
/* Turn of all automatic flushing - we'll do it all */
- if ((info->ChipFamily != CHIP_FAMILY_R300) &&
- (info->ChipFamily != CHIP_FAMILY_R350) &&
- (info->ChipFamily != CHIP_FAMILY_RV350))
+ if (!IS_R300_VARIANT)
OUTREG(RADEON_RB2D_DSTCACHE_MODE, 0);
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
@@ -318,6 +314,10 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn)
OUTREG(RADEON_DP_WRITE_MASK, 0xffffffff);
RADEONWaitForIdleMMIO(pScrn);
+
+#ifdef RENDER
+ info->RenderInited3D = FALSE;
+#endif
}
/* Initialize the acceleration hardware */
@@ -331,15 +331,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);
@@ -386,6 +377,9 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val)
#define FINISH_ACCEL()
+#ifdef RENDER
+#include "radeon_render.c"
+#endif
#include "radeon_accelfuncs.c"
#undef ACCEL_MMIO
@@ -404,6 +398,9 @@ void RADEONEngineInit(ScrnInfoPtr pScrn)
#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val)
#define FINISH_ACCEL() ADVANCE_RING()
+#ifdef RENDER
+#include "radeon_render.c"
+#endif
#include "radeon_accelfuncs.c"
#undef ACCEL_CP
diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c
index 0e30de69..848b4c0f 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... */
@@ -271,6 +271,7 @@ FUNC_NAME(RADEONSetupForSolidLine)(ScrnInfoPtr pScrn,
BEGIN_ACCEL(1);
OUT_ACCEL_REG(RADEON_DST_LINE_PATCOUNT,
0x55 << RADEON_BRES_CNTL_SHIFT);
+ FINISH_ACCEL();
}
BEGIN_ACCEL(3);
@@ -1169,7 +1170,7 @@ RADEONSelectBuffer(ScrnInfoPtr pScrn, int buffer)
}
#endif
-static void
+void
FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@@ -1224,9 +1225,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);
@@ -1346,6 +1348,59 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a)
| HARDWARE_PATTERN_SCREEN_ORIGIN
| BIT_ORDER_IN_BYTE_LSBFIRST);
#endif
+
+#ifdef RENDER
+ if (info->RenderAccel
+#ifdef XFree86LOADER
+ && info->xaaReq.minorversion >= 2
+#endif
+ ) {
+
+ a->CPUToScreenAlphaTextureFlags = XAA_RENDER_POWER_OF_2_TILE_ONLY;
+ a->CPUToScreenAlphaTextureFormats = RADEONTextureFormats;
+ a->CPUToScreenAlphaTextureDstFormats = RADEONDstFormats;
+ a->CPUToScreenTextureFlags = XAA_RENDER_POWER_OF_2_TILE_ONLY;
+ a->CPUToScreenTextureFormats = RADEONTextureFormats;
+ a->CPUToScreenTextureDstFormats = RADEONDstFormats;
+
+ if (IS_R300_VARIANT) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration "
+ "unsupported on Radeon 9500/9700 and newer.\n");
+ } else if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
+ (info->ChipFamily == CHIP_FAMILY_RV280) ||
+ (info->ChipFamily == CHIP_FAMILY_RS300) ||
+ (info->ChipFamily == CHIP_FAMILY_R200)) {
+ a->SetupForCPUToScreenAlphaTexture2 =
+ FUNC_NAME(R200SetupForCPUToScreenAlphaTexture);
+ a->SubsequentCPUToScreenAlphaTexture =
+ FUNC_NAME(R200SubsequentCPUToScreenTexture);
+
+ a->SetupForCPUToScreenTexture2 =
+ FUNC_NAME(R200SetupForCPUToScreenTexture);
+ a->SubsequentCPUToScreenTexture =
+ FUNC_NAME(R200SubsequentCPUToScreenTexture);
+ } else {
+ a->SetupForCPUToScreenAlphaTexture2 =
+ FUNC_NAME(R100SetupForCPUToScreenAlphaTexture);
+ a->SubsequentCPUToScreenAlphaTexture =
+ FUNC_NAME(R100SubsequentCPUToScreenTexture);
+
+ a->SetupForCPUToScreenTexture2 =
+ FUNC_NAME(R100SetupForCPUToScreenTexture);
+ a->SubsequentCPUToScreenTexture =
+ FUNC_NAME(R100SubsequentCPUToScreenTexture);
+ }
+ } else if (info->RenderAccel) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration currently "
+ "requires XAA v1.2 or newer.\n");
+ }
+
+ if (!a->SetupForCPUToScreenAlphaTexture2 && !a->SetupForCPUToScreenTexture2)
+ info->RenderAccel = FALSE;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration %s\n",
+ info->RenderAccel ? "enabled" : "disabled");
+#endif /* RENDER */
}
#undef FUNC_NAME
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
new file mode 100644
index 00000000..d54c9b93
--- /dev/null
+++ b/src/radeon_bios.c
@@ -0,0 +1,514 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c,v 1.0 Exp $ */
+/*
+ * Copyright 2004 ATI Technologies Inc., Markham, Ontario
+ *
+ * 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 on 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 ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR 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.
+ */
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_probe.h"
+#include "radeon_reg.h"
+#include "vbe.h"
+
+/* Read the Video BIOS block and the FP registers (if applicable). */
+Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int tmp;
+
+ if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Cannot allocate space for hold Video BIOS!\n");
+ return FALSE;
+ } else {
+ if (pInt10) {
+ info->BIOSAddr = pInt10->BIOSseg << 4;
+ (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
+ RADEON_VBIOS_SIZE);
+ } else {
+ xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE);
+ if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not detected in PCI space!\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Attempting to read Video BIOS from "
+ "legacy ISA space!\n");
+ info->BIOSAddr = 0x000c0000;
+ xf86ReadDomainMemory(info->PciTag, info->BIOSAddr,
+ RADEON_VBIOS_SIZE, info->VBIOS);
+ }
+ }
+ }
+
+ if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Unrecognized BIOS signature, BIOS data will not be used\n");
+ xfree (info->VBIOS);
+ info->VBIOS = NULL;
+ return FALSE;
+ }
+
+ if (info->VBIOS) info->ROMHeaderStart = RADEON_BIOS16(0x48);
+
+ if(!info->ROMHeaderStart) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Invalid ROM pointer, BIOS data will not be used\n");
+ xfree (info->VBIOS);
+ info->VBIOS = NULL;
+ return FALSE;
+ }
+
+ tmp = info->ROMHeaderStart + 4;
+ if ((RADEON_BIOS8(tmp) == 'A' &&
+ RADEON_BIOS8(tmp+1) == 'T' &&
+ RADEON_BIOS8(tmp+2) == 'O' &&
+ RADEON_BIOS8(tmp+3) == 'M') ||
+ (RADEON_BIOS8(tmp) == 'M' &&
+ RADEON_BIOS8(tmp+1) == 'O' &&
+ RADEON_BIOS8(tmp+2) == 'T' &&
+ RADEON_BIOS8(tmp+3) == 'A'))
+ info->IsAtomBios = TRUE;
+ else
+ info->IsAtomBios = FALSE;
+
+ if (info->IsAtomBios)
+ info->MasterDataStart = RADEON_BIOS16 (info->ROMHeaderStart + 32);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s BIOS detected\n",
+ info->IsAtomBios ? "ATOM":"Legacy");
+
+ return TRUE;
+}
+
+Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ int i = 0, j, tmp, tmp0=0, tmp1=0;
+
+ if(!info->VBIOS) return FALSE;
+
+ if (info->IsAtomBios) {
+ if((tmp = RADEON_BIOS16 (info->MasterDataStart + 22))) {
+ int crtc = 0, id[2];
+ tmp1 = RADEON_BIOS16 (tmp + 4);
+ for (i=0; i<8; i++) {
+ if(tmp1 & (1<<i)) {
+ CARD16 portinfo = RADEON_BIOS16(tmp+6+i*2);
+ if (crtc < 2) {
+ if ((i==2) || (i==6)) continue; /* ignore TV here */
+
+ if (crtc == 1) {
+ /* sharing same port with id[0] */
+ if (((portinfo>>8) & 0xf) == id[0]) {
+ if (i == 3)
+ pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT;
+ else if (i == 7)
+ pRADEONEnt->PortInfo[0].TMDSType = TMDS_EXT;
+
+ if (pRADEONEnt->PortInfo[0].DACType == DAC_UNKNOWN)
+ pRADEONEnt->PortInfo[0].DACType = (portinfo & 0xf) - 1;
+ continue;
+ }
+ }
+
+ id[crtc] = (portinfo>>8) & 0xf;
+ pRADEONEnt->PortInfo[crtc].DACType = (portinfo & 0xf) - 1;
+ pRADEONEnt->PortInfo[crtc].ConnectorType = (portinfo>>4) & 0xf;
+ if (i == 3)
+ pRADEONEnt->PortInfo[crtc].TMDSType = TMDS_INT;
+ else if (i == 7)
+ pRADEONEnt->PortInfo[crtc].TMDSType = TMDS_EXT;
+
+ if((tmp0 = RADEON_BIOS16 (info->MasterDataStart + 24)) && id[crtc]) {
+ switch (RADEON_BIOS16 (tmp0 + 4 + 27 * id[crtc]) * 4)
+ {
+ case RADEON_GPIO_MONID:
+ pRADEONEnt->PortInfo[crtc].DDCType = DDC_MONID;
+ break;
+ case RADEON_GPIO_DVI_DDC:
+ pRADEONEnt->PortInfo[crtc].DDCType = DDC_DVI;
+ break;
+ case RADEON_GPIO_VGA_DDC:
+ pRADEONEnt->PortInfo[crtc].DDCType = DDC_VGA;
+ break;
+ case RADEON_GPIO_CRT2_DDC:
+ pRADEONEnt->PortInfo[crtc].DDCType = DDC_CRT2;
+ break;
+ default:
+ pRADEONEnt->PortInfo[crtc].DDCType = DDC_NONE;
+ break;
+ }
+
+ } else {
+ pRADEONEnt->PortInfo[crtc].DDCType = DDC_NONE;
+ }
+ crtc++;
+ } else {
+ /* we have already had two CRTCs assigned. the rest may share the same
+ * port with the existing connector, fill in them accordingly.
+ */
+ for (j=0; j<2; j++) {
+ if (((portinfo>>8) & 0xf) == id[j]) {
+ if (i == 3)
+ pRADEONEnt->PortInfo[j].TMDSType = TMDS_INT;
+ else if (i == 7)
+ pRADEONEnt->PortInfo[j].TMDSType = TMDS_EXT;
+
+ if (pRADEONEnt->PortInfo[j].DACType == DAC_UNKNOWN)
+ pRADEONEnt->PortInfo[j].DACType = (portinfo & 0xf) - 1;
+ }
+ }
+ }
+ }
+ }
+
+ for (i=0; i<2; i++) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
+ i, pRADEONEnt->PortInfo[i].DDCType, pRADEONEnt->PortInfo[i].DACType,
+ pRADEONEnt->PortInfo[i].TMDSType, pRADEONEnt->PortInfo[i].ConnectorType);
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n");
+ return FALSE;
+ }
+ } else {
+ if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x50))) {
+ for (i = 1; i < 4; i++) {
+
+ if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; /* end of table */
+
+ tmp0 = RADEON_BIOS16(tmp + i*2);
+ if (((tmp0 >> 12) & 0x1f) == 0) continue; /* no connector */
+
+ /* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */
+ tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */
+
+ pRADEONEnt->PortInfo[tmp1].DDCType = (tmp0 >> 8) & 0x0f;
+ if (pRADEONEnt->PortInfo[tmp1].DDCType > DDC_CRT2) pRADEONEnt->PortInfo[tmp1].DDCType = DDC_NONE_DETECTED;
+ pRADEONEnt->PortInfo[tmp1].DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY;
+ pRADEONEnt->PortInfo[tmp1].ConnectorType = (tmp0 >> 12) & 0x0f;
+ if (pRADEONEnt->PortInfo[tmp1].ConnectorType > CONNECTOR_UNSUPPORTED) pRADEONEnt->PortInfo[tmp1].ConnectorType = CONNECTOR_UNSUPPORTED;
+ pRADEONEnt->PortInfo[tmp1].TMDSType = ((tmp0 >> 4) & 0x01) ? TMDS_EXT : TMDS_INT;
+
+ /* some sanity checks */
+ if (((pRADEONEnt->PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_D) &&
+ (pRADEONEnt->PortInfo[tmp1].ConnectorType != CONNECTOR_DVI_I)) &&
+ pRADEONEnt->PortInfo[tmp1].TMDSType == TMDS_INT)
+ pRADEONEnt->PortInfo[tmp1].TMDSType = TMDS_UNKNOWN;
+
+ xf86DrvMsg(0, X_INFO, "Connector%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
+ tmp1, pRADEONEnt->PortInfo[tmp1].DDCType, pRADEONEnt->PortInfo[tmp1].DACType,
+ pRADEONEnt->PortInfo[tmp1].TMDSType, pRADEONEnt->PortInfo[tmp1].ConnectorType);
+ }
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n");
+ return FALSE;
+ }
+
+ if (info->IsMobility) {
+ if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) {
+ if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) {
+ if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) {
+ pRADEONEnt->PortInfo[0].DDCType = tmp1;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n");
+ }
+ }
+ }
+ }
+
+#if 0
+/* External TMDS Table, not used now */
+ if ((tmp0 = RADEON_BIOS16(info->ROMHeaderStart + 0x58))) {
+
+ //pRADEONEnt->PortInfo[1].DDCType = (RADEON_BIOS8(tmp0 + 7) & 0x07);
+ //pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_DVI_I;
+ //pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "External TMDS found.\n");
+
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NO External TMDS Info found\n");
+
+ }
+#endif
+
+ }
+ return TRUE;
+}
+
+/* Read PLL parameters from BIOS block. Default to typical values if there
+ is no BIOS. */
+Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ RADEONPLLPtr pll = &info->pll;
+ CARD16 pll_info_block;
+
+ if (!info->VBIOS) {
+ return FALSE;
+ } else {
+ if (info->IsAtomBios) {
+ pll_info_block = RADEON_BIOS16 (info->MasterDataStart + 12);
+
+ pll->reference_freq = RADEON_BIOS16 (pll_info_block + 82);
+ pll->reference_div = 0; /* Need to derive from existing setting
+ or use a new algorithm to calculate
+ from min_input and max_input
+ */
+ pll->min_pll_freq = RADEON_BIOS16 (pll_info_block + 78);
+ pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 32);
+ pll->xclk = RADEON_BIOS16 (pll_info_block + 72);
+
+ info->sclk = RADEON_BIOS32(pll_info_block + 8) / 100.0;
+ info->mclk = RADEON_BIOS32(pll_info_block + 12) / 100.0;
+ if (info->sclk == 0) info->sclk = 200;
+ if (info->mclk == 0) info->mclk = 200;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %ld, max_pll: %ld, xclk: %d, sclk: %f, mclk: %f\n",
+ pll->reference_freq, pll->min_pll_freq, pll->max_pll_freq, pll->xclk, info->sclk, info->mclk);
+
+ } else {
+ pll_info_block = RADEON_BIOS16 (info->ROMHeaderStart + 0x30);
+
+ pll->reference_freq = RADEON_BIOS16 (pll_info_block + 0x0e);
+ pll->reference_div = RADEON_BIOS16 (pll_info_block + 0x10);
+ pll->min_pll_freq = RADEON_BIOS32 (pll_info_block + 0x12);
+ pll->max_pll_freq = RADEON_BIOS32 (pll_info_block + 0x16);
+ pll->xclk = RADEON_BIOS16 (pll_info_block + 0x08);
+
+ info->sclk = RADEON_BIOS16(pll_info_block + 8) / 100.0;
+ info->mclk = RADEON_BIOS16(pll_info_block + 10) / 100.0;
+ }
+ }
+
+ return TRUE;
+}
+
+Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned long tmp, i;
+
+ if (!info->VBIOS) return FALSE;
+
+ if (info->IsAtomBios) {
+ if((tmp = RADEON_BIOS16 (info->MasterDataStart + 16))) {
+
+ info->PanelXRes = RADEON_BIOS16(tmp+6);
+ info->PanelYRes = RADEON_BIOS16(tmp+10);
+ info->DotClock = RADEON_BIOS16(tmp+4)*10;
+ info->HBlank = RADEON_BIOS16(tmp+8);
+ info->HOverPlus = RADEON_BIOS16(tmp+14);
+ info->HSyncWidth = RADEON_BIOS16(tmp+16);
+ info->VBlank = RADEON_BIOS16(tmp+12);
+ info->VOverPlus = RADEON_BIOS16(tmp+18);
+ info->VSyncWidth = RADEON_BIOS16(tmp+20);
+ info->PanelPwrDly = RADEON_BIOS16(tmp+40);
+
+ info->Flags = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "LVDS Info:\n"
+ "XRes: %d, YRes: %d, DotClock: %d\n"
+ "HBlank: %d, HOverPlus: %d, HSyncWidth: %d\n"
+ "VBlank: %d, VOverPlus: %d, VSyncWidth: %d\n",
+ info->PanelXRes, info->PanelYRes, info->DotClock,
+ info->HBlank,info->HOverPlus, info->HSyncWidth,
+ info->VBlank, info->VOverPlus, info->VSyncWidth);
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "No LVDS Info Table found in BIOS!\n");
+ return FALSE;
+ }
+ } else {
+
+ tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x40);
+
+ if (!tmp) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "No Panel Info Table found in BIOS!\n");
+ return FALSE;
+ } else {
+ char stmp[30];
+ int tmp0;
+
+ for (i = 0; i < 24; i++)
+ stmp[i] = RADEON_BIOS8(tmp+i+1);
+ stmp[24] = 0;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Panel ID string: %s\n", stmp);
+
+ info->PanelXRes = RADEON_BIOS16(tmp+25);
+ info->PanelYRes = RADEON_BIOS16(tmp+27);
+ xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n",
+ info->PanelXRes, info->PanelYRes);
+
+ info->PanelPwrDly = RADEON_BIOS16(tmp+44);
+ if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0)
+ info->PanelPwrDly = 2000;
+
+ /* some panels only work well with certain divider combinations.
+ */
+ info->RefDivider = RADEON_BIOS16(tmp+46);
+ info->PostDivider = RADEON_BIOS8(tmp+48);
+ info->FeedbackDivider = RADEON_BIOS16(tmp+49);
+ if ((info->RefDivider != 0) &&
+ (info->FeedbackDivider > 3)) {
+ info->UseBiosDividers = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "BIOS provided dividers will be used.\n");
+ }
+
+ /* 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) &&
+ (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) {
+ info->HBlank = (RADEON_BIOS16(tmp0+17) -
+ RADEON_BIOS16(tmp0+19)) * 8;
+ info->HOverPlus = (RADEON_BIOS16(tmp0+21) -
+ RADEON_BIOS16(tmp0+19) - 1) * 8;
+ info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8;
+ info->VBlank = (RADEON_BIOS16(tmp0+24) -
+ RADEON_BIOS16(tmp0+26));
+ info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) -
+ RADEON_BIOS16(tmp0+26));
+ info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11);
+ info->DotClock = RADEON_BIOS16(tmp0+9) * 10;
+ info->Flags = 0;
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned long tmp;
+ char EDID[256];
+
+ if (!info->VBIOS) return FALSE;
+
+ if (info->IsAtomBios) {
+ /* Not yet */
+ return FALSE;
+ } else {
+ if (!(tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x4c))) {
+ return FALSE;
+ }
+
+ memcpy(EDID, (char*)(info->VBIOS + tmp), 256);
+
+ info->DotClock = (*(CARD16*)(EDID+54)) * 10;
+ info->PanelXRes = (*(CARD8*)(EDID+56)) + ((*(CARD8*)(EDID+58))>>4)*256;
+ info->HBlank = (*(CARD8*)(EDID+57)) + ((*(CARD8*)(EDID+58)) & 0xf)*256;
+ info->HOverPlus = (*(CARD8*)(EDID+62)) + ((*(CARD8*)(EDID+65)>>6)*256);
+ info->HSyncWidth = (*(CARD8*)(EDID+63)) + (((*(CARD8*)(EDID+65)>>4) & 3)*256);
+ info->PanelYRes = (*(CARD8*)(EDID+59)) + ((*(CARD8*)(EDID+61))>>4)*256;
+ info->VBlank = ((*(CARD8*)(EDID+60)) + ((*(CARD8*)(EDID+61)) & 0xf)*256);
+ info->VOverPlus = (((*(CARD8*)(EDID+64))>>4) + (((*(CARD8*)(EDID+65)>>2) & 3)*16));
+ info->VSyncWidth = (((*(CARD8*)(EDID+64)) & 0xf) + ((*(CARD8*)(EDID+65)) & 3)*256);
+ info->Flags = V_NHSYNC | V_NVSYNC; /**(CARD8*)(EDID+71);*/
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Hardcoded EDID data will be used for TMDS panel\n");
+ }
+ return TRUE;
+}
+
+Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 tmp, maxfreq;
+ int i, n;
+
+ if (!info->VBIOS) return FALSE;
+
+ if (info->IsAtomBios) {
+ if((tmp = RADEON_BIOS16 (info->MasterDataStart + 18))) {
+
+ maxfreq = RADEON_BIOS16(tmp+4);
+
+ for (i=0; i<4; i++) {
+ info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6);
+ /* This assumes each field in TMDS_PLL has 6 bit as in R300/R420 */
+ info->tmds_pll[i].value = ((RADEON_BIOS8(tmp+i*6+8) & 0x3f) |
+ ((RADEON_BIOS8(tmp+i*6+10) & 0x3f)<<6) |
+ ((RADEON_BIOS8(tmp+i*6+9) & 0xf)<<12) |
+ ((RADEON_BIOS8(tmp+i*6+11) & 0xf)<<16));
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "TMDS PLL from BIOS: %ld %lx\n",
+ info->tmds_pll[i].freq, info->tmds_pll[i].value);
+
+ if (maxfreq == info->tmds_pll[i].freq) {
+ info->tmds_pll[i].freq = 0xffffffff;
+ break;
+ }
+ }
+ return TRUE;
+ }
+ } else {
+
+ tmp = RADEON_BIOS16(info->ROMHeaderStart + 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 TRUE;
+ }
+
+ /* revision 4 has some problem as it appears in RV280,
+ comment it off for now, 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 TRUE;
+ }
+ */
+ }
+ }
+ return FALSE;
+}
diff --git a/src/radeon_chipset.h b/src/radeon_chipset.h
new file mode 100644
index 00000000..468a6392
--- /dev/null
+++ b/src/radeon_chipset.h
@@ -0,0 +1,96 @@
+static SymTabRec RADEONChipsets[] = {
+ { PCI_CHIP_RADEON_QD, "ATI Radeon QD (AGP)" },
+ { 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)" },
+ { 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)" },
+ { PCI_CHIP_RADEON_LZ, "ATI Radeon Mobility M6 LZ (AGP)" },
+ { PCI_CHIP_RS100_4136, "ATI Radeon IGP320 (A3) 4136" },
+ { PCI_CHIP_RS100_4336, "ATI Radeon IGP320M (U1) 4336" },
+ { PCI_CHIP_RS200_4137, "ATI Radeon IGP330/340/350 (A4) 4137" },
+ { PCI_CHIP_RS200_4337, "ATI Radeon IGP330M/340M/350M (U2) 4337" },
+ { 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_QL, "ATI Radeon 8500 QL (AGP)" },
+ { PCI_CHIP_R200_QM, "ATI Radeon 9100 QM (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_RS350_7834, "ATI Radeon 9100 PRO IGP 7834" },
+ { PCI_CHIP_RS350_7835, "ATI Radeon Mobility 9200 IGP 7835" },
+ { 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_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 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_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/9700 (M10/M11) 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 T2e (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)" },
+ { PCI_CHIP_RV380_3E50, "ATI Radeon X600 (RV380) 3E50 (PCIE)" },
+ { PCI_CHIP_RV380_3E54, "ATI FireGL V3200 (RV380) 3E54 (PCIE)" },
+ { PCI_CHIP_RV380_3150, "ATI Radeon Mobility X600 (M24) 3150 (PCIE)" },
+ { PCI_CHIP_RV380_3154, "ATI FireGL M24 GL 3154 (PCIE)" },
+ { PCI_CHIP_RV370_5B60, "ATI Radeon X300 (RV370) 5B60 (PCIE)" },
+ { PCI_CHIP_RV370_5B62, "ATI Radeon X600 (RV370) 5B62 (PCIE)" },
+ { PCI_CHIP_RV370_5B64, "ATI FireGL V3100 (RV370) 5B64 (PCIE)" },
+ { PCI_CHIP_RV370_5B65, "ATI FireGL D1100 (RV370) 5B65 (PCIE)" },
+ { PCI_CHIP_RV370_5460, "ATI Radeon Mobility M300 (M22) 5460 (PCIE)" },
+ { PCI_CHIP_RV370_5464, "ATI FireGL M22 GL 5464 (PCIE)" },
+ { PCI_CHIP_R420_JH, "ATI Radeon X800 (R420) JH (AGP)" },
+ { PCI_CHIP_R420_JI, "ATI Radeon X800PRO (R420) JI (AGP)" },
+ { PCI_CHIP_R420_JJ, "ATI Radeon X800SE (R420) JJ (AGP)" },
+ { PCI_CHIP_R420_JK, "ATI Radeon X800 (R420) JK (AGP)" },
+ { PCI_CHIP_R420_JL, "ATI Radeon X800 (R420) JL (AGP)" },
+ { PCI_CHIP_R420_JM, "ATI FireGL X3 (R420) JM (AGP)" },
+ { PCI_CHIP_R420_JN, "ATI Radeon Mobility 9800 (M18) JN (AGP)" },
+ { PCI_CHIP_R420_JP, "ATI Radeon X800XT (R420) JP (AGP)" },
+ { PCI_CHIP_R423_UH, "ATI Radeon X800 (R423) UH (PCIE)" },
+ { PCI_CHIP_R423_UI, "ATI Radeon X800PRO (R423) UI (PCIE)" },
+ { PCI_CHIP_R423_UJ, "ATI Radeon X800LE (R423) UJ (PCIE)" },
+ { PCI_CHIP_R423_UK, "ATI Radeon X800SE (R423) UK (PCIE)" },
+ { PCI_CHIP_R423_UQ, "ATI FireGL V7200 (R423) UQ (PCIE)" },
+ { PCI_CHIP_R423_UR, "ATI FireGL V5100 (R423) UR (PCIE)" },
+ { PCI_CHIP_R423_UT, "ATI FireGL V7100 (R423) UT (PCIE)" },
+ { PCI_CHIP_R423_5D57, "ATI Radeon X800XT (R423) 5D57 (PCIE)" },
+
+ { -1, NULL }
+};
diff --git a/src/radeon_common.h b/src/radeon_common.h
index 1a5f9d58..90a068bc 100644
--- a/src/radeon_common.h
+++ b/src/radeon_common.h
@@ -31,7 +31,7 @@
* Converted to common header format:
* Jens Owen <jens@tungstengraphics.com>
*
- * $XdotOrg: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.1.4.3.4.1 2004/03/04 17:47:39 eich Exp $
+ * $XdotOrg: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.3 2004/06/16 09:43:58 anholt Exp $
* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_common.h,v 1.8tsi Exp $
*
*/
@@ -39,6 +39,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
@@ -277,7 +278,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
@@ -360,7 +361,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
@@ -402,18 +404,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
@@ -453,7 +465,7 @@ typedef struct drm_radeon_irq_wait {
typedef struct drm_radeon_set_param {
unsigned int param;
- long long value;
+ int64_t value;
} drmRadeonSetParam;
#define RADEON_SETPARAM_FB_LOCATION 1
diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c
index fe54cd98..fba00f3a 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"
@@ -72,23 +73,23 @@ static CARD32 mono_cursor_color[] = {
#if X_BYTE_ORDER == X_BIG_ENDIAN
#define CURSOR_SWAPPING_DECL_MMIO unsigned char *RADEONMMIO = info->MMIO;
-#define CURSOR_SWAPPING_DECL CARD32 __surface_cntl;
#define CURSOR_SWAPPING_START() \
OUTREG(RADEON_SURFACE_CNTL, \
- ((__surface_cntl = INREG(RADEON_SURFACE_CNTL)) | \
+ (info->ModeReg.surface_cntl | \
RADEON_NONSURF_AP0_SWP_32BPP) & \
~RADEON_NONSURF_AP0_SWP_16BPP)
-#define CURSOR_SWAPPING_END() (OUTREG(RADEON_SURFACE_CNTL, __surface_cntl))
+#define CURSOR_SWAPPING_END() (OUTREG(RADEON_SURFACE_CNTL, \
+ info->ModeReg.surface_cntl))
#else
#define CURSOR_SWAPPING_DECL_MMIO
-#define CURSOR_SWAPPING_DECL
#define CURSOR_SWAPPING_START()
#define CURSOR_SWAPPING_END()
#endif
+
/* Set cursor foreground and background colors */
static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
@@ -96,7 +97,6 @@ static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_start);
int pixel, i;
CURSOR_SWAPPING_DECL_MMIO
- CURSOR_SWAPPING_DECL
#ifdef ARGB_CURSOR
/* Don't recolour cursors set with SetCursorARGB. */
@@ -138,10 +138,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 +152,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 +171,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
@@ -251,7 +186,6 @@ static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
CARD32 save2 = 0;
CARD8 chunk;
CARD32 i, j;
- CURSOR_SWAPPING_DECL
if (!info->IsSecondary) {
save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20);
@@ -259,7 +193,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 +226,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 +237,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 +250,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);
@@ -358,7 +292,6 @@ static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
CARD32 save2 = 0;
CARD32 *image = pCurs->bits->argb;
CARD32 *i;
- CURSOR_SWAPPING_DECL
if (!image)
return; /* XXX can't happen */
@@ -369,7 +302,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 +340,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 0c6d5556..c32ab18c 100644
--- a/src/radeon_dri.c
+++ b/src/radeon_dri.c
@@ -56,15 +56,7 @@
#include "sarea.h"
#include "radeon_sarea.h"
-/* HACK - for now, put this here... */
-/* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
-#if defined(__alpha__)
-# define DRM_PAGE_SIZE 8192
-#elif defined(__ia64__)
-# define DRM_PAGE_SIZE getpagesize()
-#else
-# define DRM_PAGE_SIZE 4096
-#endif
+static size_t radeon_drm_page_size;
static Bool RADEONDRICloseFullScreen(ScreenPtr pScreen);
@@ -172,7 +164,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 +276,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 +313,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
@@ -351,8 +343,17 @@ static void RADEONEnterServer(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
RADEONInfoPtr info = RADEONPTR(pScrn);
+#ifdef RENDER
+ RADEONSAREAPrivPtr pSAREAPriv;
+#endif
if (info->accel) info->accel->NeedToSync = TRUE;
+
+#ifdef RENDER
+ pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+ if (pSAREAPriv->ctxOwner != DRIGetContext(pScrn->pScreen))
+ info->RenderInited3D = FALSE;
+#endif
}
/* Called when the X server goes to sleep to allow the X server's
@@ -692,11 +693,11 @@ static void RADEONDRIInitGARTValues(RADEONInfoPtr info)
/* Initialize the CP ring buffer data */
info->ringStart = info->gartOffset;
- info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+ info->ringMapSize = info->ringSize*1024*1024 + radeon_drm_page_size;
info->ringSizeLog2QW = RADEONMinBits(info->ringSize*1024*1024/8)-1;
info->ringReadOffset = info->ringStart + info->ringMapSize;
- info->ringReadMapSize = DRM_PAGE_SIZE;
+ info->ringReadMapSize = radeon_drm_page_size;
/* Reserve space for vertex/indirect buffers */
info->bufStart = info->ringReadOffset + info->ringReadMapSize;
@@ -1024,12 +1025,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;
@@ -1227,6 +1226,8 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen)
break;
}
+ radeon_drm_page_size = getpagesize();
+
/* Create the DRI data structure, and fill it in before calling the
* DRIScreenInit().
*/
@@ -1235,19 +1236,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;
+ if ( info->ChipFamily >= CHIP_FAMILY_R200 )
+ 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);
+ 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 +1365,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 +1418,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 +1890,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);
diff --git a/src/radeon_dri.h b/src/radeon_dri.h
index 3f467190..4453fe6f 100644
--- a/src/radeon_dri.h
+++ b/src/radeon_dri.h
@@ -38,12 +38,14 @@
#define _RADEON_DRI_
#include "xf86drm.h"
-#include "radeon_common.h"
/* DRI Driver defaults */
#define RADEON_DEFAULT_CP_PIO_MODE RADEON_CSQ_PRIPIO_INDPIO
#define RADEON_DEFAULT_CP_BM_MODE RADEON_CSQ_PRIBM_INDBM
-#define RADEON_DEFAULT_AGP_MODE 1
+/* Default to AGP 4x mode for IGP chips, there are some problems with 1x and 2x
+ * modes on AGP master side
+ */
+#define RADEON_DEFAULT_AGP_MODE (info->IsIGP ? 4 : 1)
#define RADEON_DEFAULT_AGP_FAST_WRITE 0
#define RADEON_DEFAULT_GART_SIZE 8 /* MB (must be 2^n and > 4MB) */
#define RADEON_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */
@@ -85,15 +87,15 @@ typedef struct {
int log2TexGran;
/* MMIO register data */
- drmHandle registerHandle;
+ drm_handle_t registerHandle;
drmSize registerSize;
/* CP in-memory status information */
- drmHandle statusHandle;
+ drm_handle_t statusHandle;
drmSize statusSize;
/* CP GART Texture data */
- drmHandle gartTexHandle;
+ drm_handle_t gartTexHandle;
drmSize gartTexMapSize;
int log2GARTTexGran;
int gartTexOffset;
diff --git a/src/radeon_dripriv.h b/src/radeon_dripriv.h
index 88593162..34e5dbc9 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 1efa07ac..cc906278 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -56,6 +56,10 @@
* 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 */
@@ -64,6 +68,7 @@
#include "radeon_probe.h"
#include "radeon_reg.h"
#include "radeon_version.h"
+#include "radeon_mergedfb.h"
#ifdef XF86DRI
#define _XF86DRI_SERVER_
@@ -90,6 +95,8 @@
#include "fbdevhw.h"
#include "vgaHW.h"
+#include "radeon_chipset.h"
+
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
@@ -108,19 +115,27 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
int flags);
static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn);
+static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn);
+static int RADEONValidateMergeModes(ScrnInfoPtr pScrn);
+static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode);
+
+/* psuedo xinerama support */
+
+extern Bool RADEONnoPanoramiXExtension;
+
typedef enum {
OPTION_NOACCEL,
OPTION_SW_CURSOR,
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,
@@ -131,30 +146,39 @@ 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_MERGEDFB,
+ OPTION_CRT2HSYNC,
+ OPTION_CRT2VREFRESH,
+ OPTION_CRT2POS,
+ OPTION_METAMODES,
+ OPTION_MERGEDDPI,
+ OPTION_NORADEONXINERAMA,
+ OPTION_CRT2ISSCRN0,
OPTION_DISP_PRIORITY,
OPTION_PANEL_SIZE,
- OPTION_MIN_DOTCLOCK
+ OPTION_MIN_DOTCLOCK,
+#ifdef RENDER
+ OPTION_RENDER_ACCEL,
+ OPTION_SUBPIXEL_ORDER,
+#endif
+ OPTION_SHOWCACHE,
+ OPTION_DYNAMIC_CLOCKS
} RADEONOpts;
-const OptionInfoRec RADEONOptions[] = {
+static const OptionInfoRec RADEONOptions[] = {
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ 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, "AGPSize", OPTV_INTEGER, {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 },
@@ -166,18 +190,30 @@ 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 },
{ OPTION_MIN_DOTCLOCK, "ForceMinDotClock", OPTV_FREQ, {0}, FALSE },
+#ifdef RENDER
+ { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE },
+#endif
+ { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DYNAMIC_CLOCKS, "DynamicClocks", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
+const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions; }
+
static const char *vgahwSymbols[] = {
"vgaHWFreeHWRec",
"vgaHWGetHWRec",
@@ -208,7 +244,7 @@ static const char *fbdevHWSymbols[] = {
"fbdevHWRestore",
"fbdevHWSave",
"fbdevHWSwitchMode",
- "fbdevHWValidMode",
+ "fbdevHWValidModeWeak",
"fbdevHWMapMMIO",
"fbdevHWMapVidmem",
@@ -309,6 +345,7 @@ static const char *driSymbols[] = {
"DRIScreenInit",
"DRIUnlock",
"GlxSetVisualConfigs",
+ "DRICreatePCIBusID",
NULL
};
@@ -404,9 +441,11 @@ static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] =
{{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*/
+ {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/
+ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/
};
-extern int gRADEONEntityIndex;
+extern int getRADEONEntityIndex(void);
struct RADEONInt10Save {
CARD32 MEM_CNTL;
@@ -417,12 +456,12 @@ struct RADEONInt10Save {
static Bool RADEONMapMMIO(ScrnInfoPtr pScrn);
static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn);
-static RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn)
+RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn)
{
DevUnion *pPriv;
RADEONInfoPtr info = RADEONPTR(pScrn);
pPriv = xf86GetEntityPrivate(info->pEnt->index,
- gRADEONEntityIndex);
+ getRADEONEntityIndex());
return pPriv->ptr;
}
@@ -489,8 +528,8 @@ 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> (%02lx), setting to %02lx\n",
- (unsigned long)CardTmp >> 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);
@@ -510,6 +549,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;
@@ -699,7 +780,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));
@@ -730,7 +811,7 @@ static void RADEONUnblank(ScrnInfoPtr pScrn)
default:
break;
}
- if (info->Clone)
+ if (info->MergedFB)
OUTREGP(RADEON_CRTC2_GEN_CNTL,
0,
~(RADEON_CRTC2_DISP_DIS));
@@ -767,12 +848,13 @@ static int RADEONDiv(int n, int d)
return (n + (d / 2)) / d;
}
-static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, xf86MonPtr* MonInfo)
+static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, RADEONConnector* port)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
unsigned long DDCReg;
RADEONMonitorType MonType = MT_NONE;
+ xf86MonPtr* MonInfo = &port->MonInfo;
int i, j;
DDCReg = info->DDCReg;
@@ -857,8 +939,20 @@ static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCT
if (*MonInfo) {
if ((*MonInfo)->rawData[0x14] & 0x80) {
- if (INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON) MonType = MT_LCD;
- else MonType = MT_DFP;
+ /* Note some laptops have a DVI output that uses internal TMDS,
+ * when its DVI is enabled by hotkey, LVDS panel is not used.
+ * In this case, the laptop is configured as DVI+VGA as a normal
+ * desktop card.
+ * Also for laptop, when X starts with lid closed (no DVI connection)
+ * both LDVS and TMDS are disable, we still need to treat it as a LVDS panel.
+ */
+ if (port->TMDSType == TMDS_EXT) MonType = MT_DFP;
+ else {
+ if ((INREG(RADEON_FP_GEN_CNTL) & (1<<7)) || !info->IsMobility)
+ MonType = MT_DFP;
+ else
+ MonType = MT_LCD;
+ }
} else MonType = MT_CRT;
} else MonType = MT_NONE;
@@ -924,7 +1018,7 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
ulData |= 0x2;
OUTREG(RADEON_DAC_CNTL, ulData);
- usleep(1000);
+ usleep(10000);
ulData = INREG(RADEON_DAC_CNTL);
bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0;
@@ -948,7 +1042,6 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
#if 0
if (info->ChipFamily == CHIP_FAMILY_R200) {
-
unsigned long ulOrigGPIO_MONID;
unsigned long ulOrigFP2_GEN_CNTL;
unsigned long ulOrigDISP_OUTPUT_CNTL;
@@ -1064,15 +1157,13 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
| RADEON_RED_MX_FORCE_DAC_DATA
| RADEON_GRN_MX_FORCE_DAC_DATA
| RADEON_BLU_MX_FORCE_DAC_DATA);
- if ((info->ChipFamily == CHIP_FAMILY_R300) ||
- (info->ChipFamily == CHIP_FAMILY_R350) ||
- (info->ChipFamily == CHIP_FAMILY_RV350))
+ if (IS_R300_VARIANT)
ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
else
ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT;
OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData);
- usleep(1000);
+ usleep(10000);
ulData = INREG(RADEON_TV_DAC_CNTL);
bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0;
@@ -1092,516 +1183,7 @@ RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac)
return(bConnected ? MT_CRT : MT_NONE);
}
-static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
-{
- RADEONInfoPtr info = RADEONPTR(pScrn);
- RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
- unsigned char *RADEONMMIO = info->MMIO;
- const char *s;
- Bool ignore_edid = FALSE, ddc_crt2_used = FALSE;
-
-#define RADEON_BIOS8(v) (info->VBIOS[v])
-#define RADEON_BIOS16(v) (info->VBIOS[v] | \
- (info->VBIOS[(v) + 1] << 8))
-#define RADEON_BIOS32(v) (info->VBIOS[v] | \
- (info->VBIOS[(v) + 1] << 8) | \
- (info->VBIOS[(v) + 2] << 16) | \
- (info->VBIOS[(v) + 3] << 24))
-
- pRADEONEnt->MonType1 = MT_NONE;
- pRADEONEnt->MonType2 = MT_NONE;
- pRADEONEnt->MonInfo1 = NULL;
- pRADEONEnt->MonInfo2 = NULL;
- pRADEONEnt->ReversedDAC = FALSE;
- pRADEONEnt->ReversedTMDS = FALSE;
-
- /* IgnoreEDID option is different from NoDDC options used by DDC module
- * When IgnoreEDID is used, monitor detection will still use DDC
- * detection, but all EDID data will not be used in mode validation.
- */
- if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) {
- if (ignore_edid)
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
- "IgnoreEDID is specified, EDID data will be ignored\n");
- }
-
- /*
- * MonitorLayout option takes a string for two monitors connected in following format:
- * Option "MonitorLayout" "primary-port-display, secondary-port-display"
- * primary and secondary port displays can have one of following:
- * NONE, CRT, LVDS, TMDS
- * With this option, driver will bring up monitors as specified,
- * not using auto-detection routines to probe monitors.
- */
-
- /* current monitor mapping scheme:
- * Two displays connected:
- * Primary Port:
- * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or
- * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or
- * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary
- *
- * Secondary Port
- * CRTC2 -> CRT DAC -> VGA port -> CRT monitor --> Secondary or
- * CRTC2 -> FP2/Ext. -> DVI port -> TMDS panel --> Secondary
- *
- * Only DVI (or Int. LDC) conneced:
- * CRTC1 -> FP/TMDS -> DVI port -> TMDS panel --> Primary or
- * CRTC1 -> FP/LVDS -> Int. LCD -> LVDS panel --> Primary or
- * CRTC1 -> TV DAC -> DVI port -> CRT monitor --> Primary
- *
- * Only VGA (can be DVI on some dual-DVI boards) connected:
- * CRTC1 -> CRT DAC -> VGA port -> CRT monitor --> Primary or
- * CRTC1 -> FP2/Ext. -> DVI port -> TMDS panel --> Primary (not supported)
- *
- * Note, this is different from Windows scheme where
- * if a digital panel is connected to DVI port, DVI will be the 1st port
- * otherwise, VGA port will be treated as 1st port
- *
- * Here we always treat DVI port as primary if both ports are connected.
- * When only one port is connected, it will be treated as
- * primary regardless which port or what type of display is involved.
- */
-
- if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) {
- char s1[5], s2[5];
- int i = 0, second = 0;
-
- /* When using user specified monitor types, we will not do DDC detection
- *
- */
- do {
- switch(*s)
- {
- case ',':
- s1[i] = '\0';
- i = 0;
- second = 1;
- break;
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- if (second)
- s2[i] = *s;
- else
- s1[i] = *s;
- i++;
- if (i == 4) break;
- }
- } while(*s++);
- s2[i] = '\0';
-
- if (strcmp(s1, "NONE") == 0)
- pRADEONEnt->MonType1 = MT_NONE;
- else if (strcmp(s1, "CRT") == 0)
- pRADEONEnt->MonType1 = MT_CRT;
- else if (strcmp(s1, "TMDS") == 0)
- pRADEONEnt->MonType1 = MT_DFP;
- else if (strcmp(s1, "LVDS") == 0)
- pRADEONEnt->MonType1 = MT_LCD;
- else
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Invalid Monitor type specified for 1st port \n");
- if (strcmp(s2, "NONE") == 0)
- pRADEONEnt->MonType2 = MT_NONE;
- else if (strcmp(s2, "CRT") == 0)
- pRADEONEnt->MonType2 = MT_CRT;
- else if (strcmp(s2, "TMDS") == 0)
- pRADEONEnt->MonType2 = MT_DFP;
- else if (strcmp(s2, "LVDS") == 0)
- pRADEONEnt->MonType2 = MT_LCD;
- else
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Invalid Monitor type specified for 2nd port \n");
-
- if (!ignore_edid) {
- if (pRADEONEnt->MonType1) /* assuming the first port using DDC_DVI */
- if(!RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1)) {
- RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1);
- ddc_crt2_used = TRUE;
- }
- if (pRADEONEnt->MonType2) { /* assuming the second port using DDC_VGA/DDC_CRT2 */
- if(!RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2))
- if (!ddc_crt2_used)
- RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2);
- }
- }
-
- if (!pRADEONEnt->MonType1) {
- if (pRADEONEnt->MonType2) {
- pRADEONEnt->MonType1 = pRADEONEnt->MonType2;
- pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2;
- } else {
- pRADEONEnt->MonType1 = MT_CRT;
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "No valid monitor specified, force to CRT on 1st port\n");
- }
- pRADEONEnt->MonType2 = MT_NONE;
- pRADEONEnt->MonInfo2 = NULL;
- }
- } else {
- /* Auto detection */
- int i;
- CARD32 tmp;
-
- /* Old single head radeon cards */
- if(!info->HasCRTC2) {
- if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1)));
- else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo1)));
- else if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1)));
- else if (pInt10) {
- if (xf86LoadSubModule(pScrn, "vbe")) {
- vbeInfoPtr pVbe;
- pVbe = VBEInit(pInt10, info->pEnt->index);
- if (pVbe) {
- for (i = 0; i < 5; i++) {
- pRADEONEnt->MonInfo1 = vbeDoEDID(pVbe, NULL);
- }
- if (pRADEONEnt->MonInfo1->rawData[0x14] & 0x80)
- pRADEONEnt->MonType1 = MT_DFP;
- else pRADEONEnt->MonType1 = MT_CRT;
- }
- }
- } else
- pRADEONEnt->MonType1 = MT_CRT;
-
- pRADEONEnt->HasSecondary = FALSE;
- if (!ignore_edid) {
- if (pRADEONEnt->MonInfo1) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n");
- xf86PrintEDID( pRADEONEnt->MonInfo1 );
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n");
- }
- }
- return;
- }
-
- /* Normally the port uses DDC_DVI connected with TVDAC,
- * But this is not true for OEM cards which have TVDAC and CRT DAC reversed.
- * If that's the case, we need also reverse the port arrangement.
- * BIOS settings are supposed report this correctly, work fine for all cards tested.
- * But there may be some exceptions, in that case, user can reverse their monitor
- * definition in config file to correct the problem.
- */
- if (info->VBIOS && (tmp = RADEON_BIOS16(info->FPBIOSstart + 0x50))) {
- for (i = 1; i < 4; i++) {
- unsigned int tmp0;
- if (!RADEON_BIOS8(tmp + i*2) && i > 1) break;
- tmp0 = RADEON_BIOS16(tmp + i*2);
- if ((!(tmp0 & 0x01)) && (((tmp0 >> 8) & 0xf) == DDC_DVI)) {
- pRADEONEnt->ReversedDAC = TRUE;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DACs detected\n");
- }
- if ((((tmp0 >> 8) & 0x0f) == DDC_DVI ) && ((tmp0 >> 4) & 0x1)) {
- pRADEONEnt->ReversedTMDS = TRUE;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed TMDS detected\n");
- }
- }
- }
-
- /* Primary Head (DVI or Laptop Int. panel)*/
- /* A ddc capable display connected on DVI port */
- if((pRADEONEnt->MonType1 = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->MonInfo1)));
- else if((pRADEONEnt->MonType1 =
- RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo1))) {
- ddc_crt2_used = TRUE;
- } else if ((info->IsMobility) &&
- (info->VBIOS && (INREG(RADEON_BIOS_4_SCRATCH) & 4))) {
- /* non-DDC laptop panel connected on primary */
- pRADEONEnt->MonType1 = MT_LCD;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Non-DDC laptop panel detected\n");
- } else {
- /* CRT on DVI, TODO: not reliable, make it always return false for now*/
- pRADEONEnt->MonType1 = RADEONCrtIsPhysicallyConnected(pScrn, pRADEONEnt->ReversedDAC);
- }
-
- /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/
- if((pRADEONEnt->MonType2 =
- RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->MonInfo2)));
- else if(!ddc_crt2_used)
- pRADEONEnt->MonType2 =
- RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->MonInfo2);
- if (!pRADEONEnt->MonType2)
- pRADEONEnt->MonType2 = RADEONCrtIsPhysicallyConnected(pScrn, !pRADEONEnt->ReversedDAC);
-
- if(pRADEONEnt->ReversedTMDS) {
- /* always keep internal TMDS as primary head */
- if (pRADEONEnt->MonType1 == MT_DFP ||
- pRADEONEnt->MonType2 == MT_DFP) {
- int tmp1 = pRADEONEnt->MonType1;
- xf86MonPtr MonInfo = pRADEONEnt->MonInfo1;
- pRADEONEnt->MonInfo1 = pRADEONEnt->MonInfo2;
- pRADEONEnt->MonInfo2 = MonInfo;
- pRADEONEnt->MonType1 = pRADEONEnt->MonType2;
- pRADEONEnt->MonType2 = tmp1;
- if ((pRADEONEnt->MonType1 == MT_CRT) ||
- (pRADEONEnt->MonType2 == MT_CRT)) {
- pRADEONEnt->ReversedDAC ^= 1;
- }
- }
- }
-
- /* 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) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Displays Configured by MonitorLayout: \n\tMonitor1--Type %d, Monitor2--Type %d\n\n",
- pRADEONEnt->MonType1, pRADEONEnt->MonType2);
- } else {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Displays Detected: Monitor1--Type %d, Monitor2--Type %d\n\n",
- pRADEONEnt->MonType1, pRADEONEnt->MonType2);
- }
-
- if(ignore_edid) {
- pRADEONEnt->MonInfo1 = NULL;
- pRADEONEnt->MonInfo2 = NULL;
- }
-
- if (!ignore_edid) {
- if (pRADEONEnt->MonInfo1) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n");
- xf86PrintEDID( pRADEONEnt->MonInfo1 );
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n");
- }
- if (pRADEONEnt->MonInfo2) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor2 EDID data ---------------------------\n");
- xf86PrintEDID( pRADEONEnt->MonInfo2 );
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor2 EDID data --------------------\n");
- }
- }
-
- 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;
-}
-
-
-/* Read the Video BIOS block and the FP registers (if applicable). */
-static Bool RADEONGetBIOSParameters(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
-{
- RADEONInfoPtr info = RADEONPTR(pScrn);
- unsigned long tmp, i;
-
- if (!(info->VBIOS = xalloc(RADEON_VBIOS_SIZE))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Cannot allocate space for hold Video BIOS!\n");
- return FALSE;
- }
-
- if (pInt10) {
- info->BIOSAddr = pInt10->BIOSseg << 4;
- (void)memcpy(info->VBIOS, xf86int10Addr(pInt10, info->BIOSAddr),
- RADEON_VBIOS_SIZE);
- } else {
- xf86ReadPciBIOS(0, info->PciTag, 0, info->VBIOS, RADEON_VBIOS_SIZE);
- if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Video BIOS not detected in PCI space!\n");
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Attempting to read Video BIOS from "
- "legacy ISA space!\n");
- info->BIOSAddr = 0x000c0000;
- xf86ReadDomainMemory(info->PciTag, info->BIOSAddr,
- RADEON_VBIOS_SIZE, info->VBIOS);
- }
- }
-
- if (info->VBIOS[0] != 0x55 || info->VBIOS[1] != 0xaa) {
- xfree(info->VBIOS);
- info->FPBIOSstart = 0;
- info->VBIOS = NULL;
- info->BIOSAddr = 0x00000000;
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Video BIOS not found!\n");
- } else
- info->FPBIOSstart = RADEON_BIOS16(0x48);
- info->OverlayOnCRTC2 = FALSE;
-
- if (!info->IsSecondary)
- RADEONQueryConnectedDisplays(pScrn, pInt10);
-
- {
- RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
-
- info->Clone = FALSE;
- info->CloneType = MT_NONE;
-
- if(info->HasCRTC2) {
- if(info->IsSecondary) {
- info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2;
- if(info->DisplayType == MT_NONE) return FALSE;
- } else {
- info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1;
-
- if(!pRADEONEnt->HasSecondary) {
- info->CloneType = (RADEONMonitorType)pRADEONEnt->MonType2;
- if (info->CloneType != MT_NONE)
- info->Clone = TRUE;
- }
- }
- } else {
- info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType1;
- }
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Display == Type %d\n",
- (info->IsSecondary ? "Secondary" : "Primary"),
- info->DisplayType);
-
- if (info->Clone)
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clone Display == Type %d\n",
- info->CloneType);
-
- info->HBlank = 0;
- info->HOverPlus = 0;
- info->HSyncWidth = 0;
- info->VBlank = 0;
- info->VOverPlus = 0;
- info->VSyncWidth = 0;
- info->DotClock = 0;
- info->UseBiosDividers = FALSE;
-
- if (info->DisplayType == MT_LCD && info->VBIOS &&
- !(xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) {
- tmp = RADEON_BIOS16(info->FPBIOSstart + 0x40);
- if (!tmp) {
- info->PanelPwrDly = 200;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "No Panel Info Table found in BIOS!\n");
- } else {
- char stmp[30];
- int tmp0;
-
- for (i = 0; i < 24; i++)
- stmp[i] = RADEON_BIOS8(tmp+i+1);
- stmp[24] = 0;
-
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "Panel ID string: %s\n", stmp);
-
- info->PanelXRes = RADEON_BIOS16(tmp+25);
- info->PanelYRes = RADEON_BIOS16(tmp+27);
- xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n",
- info->PanelXRes, info->PanelYRes);
-
- info->PanelPwrDly = RADEON_BIOS16(tmp+44);
- if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0)
- info->PanelPwrDly = 2000;
-
- /* some panels only work well with certain divider combinations.
- */
- info->RefDivider = RADEON_BIOS16(tmp+46);
- info->PostDivider = RADEON_BIOS8(tmp+48);
- info->FeedbackDivider = RADEON_BIOS16(tmp+49);
- if ((info->RefDivider != 0) &&
- (info->FeedbackDivider > 3)) {
- info->UseBiosDividers = TRUE;
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "BIOS provided dividers will be used.\n");
- }
-
- /* 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) &&
- (RADEON_BIOS16(tmp0+2) == info->PanelYRes)) {
- info->HBlank = (RADEON_BIOS16(tmp0+17) -
- RADEON_BIOS16(tmp0+19)) * 8;
- info->HOverPlus = (RADEON_BIOS16(tmp0+21) -
- RADEON_BIOS16(tmp0+19) - 1) * 8;
- info->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8;
- info->VBlank = (RADEON_BIOS16(tmp0+24) -
- RADEON_BIOS16(tmp0+26));
- info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) -
- RADEON_BIOS16(tmp0+26));
- info->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11);
- info->DotClock = RADEON_BIOS16(tmp0+9) * 10;
- 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;
-}
-
+#if defined(__powerpc__)
static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -1713,121 +1295,181 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn)
return TRUE;
}
+#endif
+
+static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH);
+ CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH);
+
+ info->PanelPwrDly = 200;
+ if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) {
+ info->PanelYRes = (fp_vert_stretch>>12) + 1;
+ } else {
+ info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1;
+ }
+ if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) {
+ info->PanelXRes = ((fp_vert_stretch>>16) + 1) * 8;
+ } else {
+ info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8;
+ }
+
+ if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) {
+ info->PanelXRes = 640;
+ info->PanelYRes = 480;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Panel size %dx%d is derived, this may not be correct.\n"
+ "If not, use PanelSize option to overwrite this setting\n",
+ info->PanelXRes, info->PanelYRes);
+}
+
+static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (!RADEONGetLVDSInfoFromBIOS(pScrn))
+ RADEONGetPanelInfoFromReg(pScrn);
+
+ if (info->DotClock == 0) {
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ 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->PortInfo[0].MonInfo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Panel size is not correctly detected.\n"
+ "Please try to use PanelSize option for correct settings.\n");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
- CARD32 tmp;
- int i, n;
+ int i;
for (i=0; i<4; i++) {
- info->tmds_pll[i].value = 0;
- info->tmds_pll[i].freq = 0;
+ 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;
- }
- */
- }
- }
+ if (RADEONGetTMDSInfoFromBIOS(pScrn)) 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;
+ 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.
- */
-static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn)
+static void RADEONGetPanelInfo (ScrnInfoPtr pScrn)
{
- RADEONInfoPtr info = RADEONPTR(pScrn);
- RADEONPLLPtr pll = &info->pll;
- CARD16 bios_header;
- CARD16 pll_info_block;
- double min_dotclock;
-
- if (!info->VBIOS) {
-
- pll->min_pll_freq = 12500;
- pll->max_pll_freq = 35000;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ char* s;
+
+ if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) {
+ info->PanelPwrDly = 200;
+ if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s);
+ RADEONGetPanelInfoFromReg(pScrn);
+ }
+ } else {
+ if(info->DisplayType == MT_LCD) {
+ RADEONGetLVDSInfo(pScrn);
+ } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) {
+ RADEONGetTMDSInfo(pScrn);
+ if (!pScrn->monitor->DDC)
+ RADEONGetHardCodedEDIDFromBIOS(pScrn);
+ }
+ }
+}
- if (!RADEONProbePLLParameters(pScrn)) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "Video BIOS not detected, using default PLL parameters!\n");
-
- switch (info->Chipset) {
- case PCI_CHIP_R200_QL:
- case PCI_CHIP_R200_QN:
- case PCI_CHIP_R200_QO:
- case PCI_CHIP_R200_BB:
- pll->reference_freq = 2700;
- pll->reference_div = 12;
- pll->xclk = 27500;
- break;
- case PCI_CHIP_RV250_Id:
- case PCI_CHIP_RV250_Ie:
- case PCI_CHIP_RV250_If:
- case PCI_CHIP_RV250_Ig:
- pll->reference_freq = 2700;
- pll->reference_div = 12;
- pll->xclk = 24975;
- break;
- case PCI_CHIP_RV200_QW:
- pll->reference_freq = 2700;
- pll->reference_div = 12;
- pll->xclk = 23000;
- break;
- default:
- pll->reference_freq = 2700;
- pll->reference_div = 67;
- pll->xclk = 16615;
- break;
+static void RADEONGetClockInfo(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+ RADEONPLLPtr pll = &info->pll;
+ double min_dotclock;
+
+ if (RADEONGetClockInfoFromBIOS(pScrn)) {
+ if (pll->reference_div < 2) {
+ /* retrive it from register setting for fitting into current PLL algorithm.
+ We'll probably need a new routine to calculate the best ref_div from BIOS
+ provided min_input_pll and max_input_pll
+ */
+ CARD32 tmp;
+ tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV);
+ if (IS_R300_VARIANT ||
+ (info->ChipFamily == CHIP_FAMILY_RS300)) {
+ pll->reference_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT;
+ } else {
+ pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK;
}
- }
+
+ if (pll->reference_div < 2) pll->reference_div = 12;
+ }
+
} else {
- bios_header = RADEON_BIOS16(0x48);
- pll_info_block = RADEON_BIOS16(bios_header + 0x30);
- RADEONTRACE(("Header at 0x%04x; PLL Information at 0x%04x\n",
- bios_header, pll_info_block));
+ xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
+ "Video BIOS not detected, using default clock settings!\n");
+
+#if defined(__powerpc__)
+ if (RADEONProbePLLParameters(pScrn)) return;
+#endif
+ if (info->IsIGP)
+ pll->reference_freq = 1432;
+ else
+ pll->reference_freq = 2700;
- pll->reference_freq = RADEON_BIOS16(pll_info_block + 0x0e);
- pll->reference_div = RADEON_BIOS16(pll_info_block + 0x10);
- pll->min_pll_freq = RADEON_BIOS32(pll_info_block + 0x12);
- pll->max_pll_freq = RADEON_BIOS32(pll_info_block + 0x16);
- pll->xclk = RADEON_BIOS16(pll_info_block + 0x08);
+ pll->reference_div = 12;
+ pll->min_pll_freq = 12500;
+ pll->max_pll_freq = 35000;
+ pll->xclk = 10300;
+
+ info->sclk = 200.00;
+ info->mclk = 200.00;
}
+ xf86DrvMsg (pScrn->scrnIndex, X_INFO,
+ "PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n",
+ pll->reference_freq,
+ pll->reference_div,
+ pll->min_pll_freq, pll->max_pll_freq, pll->xclk);
+
/* (Some?) Radeon BIOSes seem too lie about their minimum dot
* clocks. Allow users to override the detected minimum dot clock
* value (e.g., and allow it to be suitable for TV sets).
@@ -1847,10 +1489,392 @@ static Bool RADEONGetPLLParameters(ScrnInfoPtr pScrn)
pll->min_pll_freq = min_dotclock * 1000;
}
}
+}
+
+static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ const char *s;
+ Bool ignore_edid = FALSE;
+ int i = 0, second = 0, max_mt;
+
+ const char *MonTypeName[7] =
+ {
+ "AUTO",
+ "NONE",
+ "CRT",
+ "LVDS",
+ "TMDS",
+ "CTV",
+ "STV"
+ };
+
+ const RADEONMonitorType MonTypeID[7] =
+ {
+ MT_UNKNOWN, /* this is just a dummy value for AUTO DETECTION */
+ MT_NONE, /* NONE -> NONE */
+ MT_CRT, /* CRT -> CRT */
+ MT_LCD, /* Laptop LCDs are driven via LVDS port */
+ MT_DFP, /* DFPs are driven via TMDS */
+ MT_CTV, /* CTV -> CTV */
+ MT_STV, /* STV -> STV */
+ };
+
+ const char *TMDSTypeName[3] =
+ {
+ "NONE",
+ "Internal",
+ "External"
+ };
+
+ const char *DDCTypeName[5] =
+ {
+ "NONE",
+ "MONID",
+ "DVI_DDC",
+ "VGA_DDC",
+ "CRT2_DDC"
+ };
+
+ const char *DACTypeName[3] =
+ {
+ "Unknown",
+ "Primary",
+ "TVDAC/ExtDAC",
+ };
+
+ const char *ConnectorTypeName[8] =
+ {
+ "None",
+ "Proprietary",
+ "VGA",
+ "DVI-I",
+ "DVI-D",
+ "CTV",
+ "STV",
+ "Unsupported"
+ };
+
+ const char *ConnectorTypeNameATOM[10] =
+ {
+ "None",
+ "VGA",
+ "DVI-I",
+ "DVI-D",
+ "DVI-A",
+ "STV",
+ "CTV",
+ "LVDS",
+ "Digital",
+ "Unsupported"
+ };
+
+ max_mt = 5;
+
+ if(info->IsSecondary) {
+ info->DisplayType = (RADEONMonitorType)pRADEONEnt->MonType2;
+ if(info->DisplayType == MT_NONE) return FALSE;
+ return TRUE;
+ }
+
+
+ /* We first get the information about all connectors from BIOS.
+ * This is how the card is phyiscally wired up.
+ * The information should be correct even on a OEM card.
+ * If not, we may have problem -- need to use MonitorLayout option.
+ */
+ for (i = 0; i < 2; i++) {
+ pRADEONEnt->PortInfo[i].MonType = MT_UNKNOWN;
+ pRADEONEnt->PortInfo[i].MonInfo = NULL;
+ pRADEONEnt->PortInfo[i].DDCType = DDC_NONE_DETECTED;
+ pRADEONEnt->PortInfo[i].DACType = DAC_UNKNOWN;
+ pRADEONEnt->PortInfo[i].TMDSType = TMDS_UNKNOWN;
+ pRADEONEnt->PortInfo[i].ConnectorType = CONNECTOR_NONE;
+ }
+
+ if (!RADEONGetConnectorInfoFromBIOS(pScrn)) {
+ /* Below is the most common setting, but may not be true */
+ pRADEONEnt->PortInfo[0].MonType = MT_UNKNOWN;
+ pRADEONEnt->PortInfo[0].MonInfo = NULL;
+ pRADEONEnt->PortInfo[0].DDCType = DDC_DVI;
+ pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC;
+ pRADEONEnt->PortInfo[0].TMDSType = TMDS_INT;
+ pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_DVI_D;
+
+ pRADEONEnt->PortInfo[1].MonType = MT_UNKNOWN;
+ pRADEONEnt->PortInfo[1].MonInfo = NULL;
+ pRADEONEnt->PortInfo[1].DDCType = DDC_VGA;
+ pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY;
+ pRADEONEnt->PortInfo[1].TMDSType = TMDS_EXT;
+ pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT;
+ }
+
+ /* always make TMDS_INT port first*/
+ if (pRADEONEnt->PortInfo[1].TMDSType == TMDS_INT) {
+ RADEONConnector connector;
+ connector = pRADEONEnt->PortInfo[0];
+ pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1];
+ pRADEONEnt->PortInfo[1] = connector;
+ } else if ((pRADEONEnt->PortInfo[0].TMDSType != TMDS_INT &&
+ pRADEONEnt->PortInfo[1].TMDSType != TMDS_INT)) {
+ /* no TMDS_INT port, make primary DAC port first */
+ if (pRADEONEnt->PortInfo[1].DACType == DAC_PRIMARY) {
+ RADEONConnector connector;
+ connector = pRADEONEnt->PortInfo[0];
+ pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1];
+ pRADEONEnt->PortInfo[1] = connector;
+ }
+ }
+
+ if (info->HasSingleDAC) {
+ /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/
+ if (pRADEONEnt->PortInfo[0].ConnectorType == CONNECTOR_CRT) {
+ pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC;
+ pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY;
+ } else {
+ pRADEONEnt->PortInfo[1].DACType = DAC_TVDAC;
+ pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY;
+ }
+ } else if (!info->HasCRTC2) {
+ pRADEONEnt->PortInfo[0].DACType = DAC_PRIMARY;
+ }
+
+ /* IgnoreEDID option is different from the NoDDCxx options used by DDC module
+ * When IgnoreEDID is used, monitor detection will still use DDC
+ * detection, but all EDID data will not be used in mode validation.
+ * You can use this option when you have a DDC monitor but want specify your own
+ * monitor timing parameters by using HSync, VRefresh and Modeline,
+ */
+ if (xf86GetOptValBool(info->Options, OPTION_IGNORE_EDID, &ignore_edid)) {
+ if (ignore_edid)
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "IgnoreEDID is specified, EDID data will be ignored\n");
+ }
+
+ /*
+ * MonitorLayout option takes a string for two monitors connected in following format:
+ * Option "MonitorLayout" "primary-port-display, secondary-port-display"
+ * primary and secondary port displays can have one of following:
+ * NONE, CRT, LVDS, TMDS
+ * With this option, driver will bring up monitors as specified,
+ * not using auto-detection routines to probe monitors.
+ *
+ * This option can be used when the false monitor detection occurs.
+ *
+ * This option can also be used to disable one connected display.
+ * For example, if you have a laptop connected to an external CRT
+ * and you want to disable the internal LCD panel, you can specify
+ * Option "MonitorLayout" "NONE, CRT"
+ *
+ * This option can also used to disable Clone mode. One there is only
+ * one monitor is specified, clone mode will be turned off automatically
+ * even you have two monitors connected.
+ *
+ * Another usage of this option is you want to config the server
+ * to start up with a certain monitor arrangement even one monitor
+ * is not plugged in when server starts.
+ */
+ if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) {
+ char s1[5], s2[5];
+ i = 0;
+ /* When using user specified monitor types, we will not do DDC detection
+ *
+ */
+ do {
+ switch(*s) {
+ case ',':
+ s1[i] = '\0';
+ i = 0;
+ second = 1;
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ if (second)
+ s2[i] = *s;
+ else
+ s1[i] = *s;
+ i++;
+ break;
+ }
+ if (i > 4) i = 4;
+ } while(*s++);
+ s2[i] = '\0';
+
+ for (i = 0; i < max_mt; i++) {
+ if (strcmp(s1, MonTypeName[i]) == 0) {
+ pRADEONEnt->PortInfo[0].MonType = MonTypeID[i];
+ break;
+ }
+ }
+ if (i == max_mt)
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Invalid Monitor type specified for 2nd port \n");
+
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "MonitorLayout Option: \n\tMonitor1--Type %s, Monitor2--Type %s\n\n", s1, s2);
+
+ if (pRADEONEnt->PortInfo[1].MonType == MT_CRT) {
+ pRADEONEnt->PortInfo[1].DACType = DAC_PRIMARY;
+ pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN;
+ pRADEONEnt->PortInfo[1].DDCType = DDC_VGA;
+ pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_CRT;
+ pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC;
+ pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN;
+ pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED;
+ pRADEONEnt->PortInfo[0].ConnectorType = pRADEONEnt->PortInfo[0].MonType+1;
+ pRADEONEnt->PortInfo[0].MonInfo = NULL;
+ }
+
+ if (!ignore_edid) {
+ if ((pRADEONEnt->PortInfo[0].MonType > MT_NONE) &&
+ (pRADEONEnt->PortInfo[0].MonType < MT_STV))
+ RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType,
+ &pRADEONEnt->PortInfo[0]);
+ if ((pRADEONEnt->PortInfo[1].MonType > MT_NONE) &&
+ (pRADEONEnt->PortInfo[1].MonType < MT_STV))
+ RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType,
+ &pRADEONEnt->PortInfo[1]);
+ }
+
+ }
+
+ if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) {
+
+ if(((!info->HasCRTC2) || info->IsDellServer) &&
+ (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN)) {
+ if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0])));
+ else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0])));
+ else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0])));
+ else
+ pRADEONEnt->PortInfo[0].MonType = MT_CRT;
+
+ if (!ignore_edid) {
+ if (pRADEONEnt->PortInfo[0].MonInfo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n");
+ xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo );
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n");
+ }
+ }
+
+ pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType;
+ pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo;
+ pRADEONEnt->MonType2 = MT_NONE;
+ pRADEONEnt->MonInfo2 = NULL;
+ info->MergeType = MT_NONE;
+ return TRUE;
+ }
+
+ /* Primary Head (DVI or Laptop Int. panel)*/
+ /* A ddc capable display connected on DVI port */
+ if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) {
+ if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[0].DDCType, &pRADEONEnt->PortInfo[0])));
+ else if (info->IsMobility &&
+ (INREG(RADEON_BIOS_4_SCRATCH) & 4)) {
+ /* non-DDC laptop panel connected on primary */
+ pRADEONEnt->PortInfo[0].MonType = MT_LCD;
+ } else {
+ /* CRT on DVI, TODO: not reliable, make it always return false for now*/
+ pRADEONEnt->PortInfo[0].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[0].DACType));
+ }
+ }
+
+ /* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/
+ if (pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) {
+ if((pRADEONEnt->PortInfo[1].MonType =
+ RADEONDisplayDDCConnected(pScrn, pRADEONEnt->PortInfo[1].DDCType, &pRADEONEnt->PortInfo[1])));
+ else if (info->IsMobility &&
+ (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON)) {
+ /* non-DDC TMDS panel connected through DVO */
+ pRADEONEnt->PortInfo[1].MonType = MT_DFP;
+ } else
+ pRADEONEnt->PortInfo[1].MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pRADEONEnt->PortInfo[1].DACType));
+ }
+ }
+
+ if(ignore_edid) {
+ pRADEONEnt->PortInfo[0].MonInfo = NULL;
+ pRADEONEnt->PortInfo[1].MonInfo = NULL;
+ } else {
+ if (pRADEONEnt->PortInfo[0].MonInfo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 1 ----------------------\n");
+ xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo );
+ }
+
+ if (pRADEONEnt->PortInfo[1].MonInfo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on port 2-----------------------\n");
+ xf86PrintEDID(pRADEONEnt->PortInfo[1].MonInfo );
+ }
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n");
+
+ pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType;
+ pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo;
+ pRADEONEnt->MonType2 = pRADEONEnt->PortInfo[1].MonType;
+ pRADEONEnt->MonInfo2 = pRADEONEnt->PortInfo[1].MonInfo;
+ if (pRADEONEnt->PortInfo[0].MonType == MT_NONE) {
+ if (pRADEONEnt->PortInfo[1].MonType == MT_NONE) {
+ pRADEONEnt->MonType1 = MT_CRT;
+ pRADEONEnt->MonInfo1 = NULL;
+ } else {
+ RADEONConnector tmp;
+ pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[1].MonType;
+ pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[1].MonInfo;
+ tmp = pRADEONEnt->PortInfo[0];
+ pRADEONEnt->PortInfo[0] = pRADEONEnt->PortInfo[1];
+ pRADEONEnt->PortInfo[1] = tmp;
+ }
+ pRADEONEnt->MonType2 = MT_NONE;
+ pRADEONEnt->MonInfo2 = NULL;
+ }
+
+ info->DisplayType = pRADEONEnt->MonType1;
+ pRADEONEnt->ReversedDAC = FALSE;
+ info->OverlayOnCRTC2 = FALSE;
+ info->MergeType = MT_NONE;
+ if (pRADEONEnt->MonType2 != MT_NONE) {
+ if(!pRADEONEnt->HasSecondary) {
+ info->MergeType = pRADEONEnt->MonType2;
+ }
+
+ if (pRADEONEnt->PortInfo[1].DACType == DAC_TVDAC) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reversed DAC decteced\n");
+ pRADEONEnt->ReversedDAC = TRUE;
+ }
+ } else {
+ pRADEONEnt->HasSecondary = FALSE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n",
+ MonTypeName[pRADEONEnt->PortInfo[0].MonType+1],
+ info->IsAtomBios ?
+ ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]:
+ ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType],
+ DACTypeName[pRADEONEnt->PortInfo[0].DACType+1],
+ TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1],
+ DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Secondary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n",
+ MonTypeName[pRADEONEnt->PortInfo[1].MonType+1],
+ info->IsAtomBios ?
+ ConnectorTypeNameATOM[pRADEONEnt->PortInfo[1].ConnectorType]:
+ ConnectorTypeName[pRADEONEnt->PortInfo[1].ConnectorType],
+ DACTypeName[pRADEONEnt->PortInfo[1].DACType+1],
+ TMDSTypeName[pRADEONEnt->PortInfo[1].TMDSType+1],
+ DDCTypeName[pRADEONEnt->PortInfo[1].DDCType]);
return TRUE;
}
+
/* This is called by RADEONPreInit to set up the default visual */
static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn)
{
@@ -1940,22 +1964,89 @@ 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);
+
+
+ /* This function has many problems with newer cards.
+ * Even with older cards, all registers changed here are not
+ * restored properly when X quits, this will also cause
+ * various problems, especially with radeonfb.
+ * Since we don't have DRI support for R300 and above cards,
+ * we just hardcode these values for now.
+ * Need to revisit this whole function!!!
+ */
+ if (IS_R300_VARIANT) {
+ info->fbLocation = 0;
+
+ if (!info->IsSecondary) {
+ RADEONWaitForIdleMMIO(pScrn);
+ OUTREG (RADEON_MC_FB_LOCATION, (INREG(RADEON_CONFIG_MEMSIZE) - 1) & 0xffff0000);
+ OUTREG(RADEON_DISPLAY_BASE_ADDR, info->fbLocation);
+ OUTREG(RADEON_DISPLAY2_BASE_ADDR, info->fbLocation);
+ OUTREG(RADEON_OV0_BASE_ADDR, info->fbLocation);
+ }
+ return;
+ }
+
+ if (info->IsIGP) {
+ mc_fb_location = INREG(RADEON_NB_TOM);
+
+ OUTREG(RADEON_GRPH2_BUFFER_CNTL,
+ INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000);
+
+ } 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)))
+ (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)) {
+ if (IS_R300_VARIANT) {
tmp &= R300_MEM_NUM_CHANNELS_MASK;
switch (tmp) {
case 0: info->RamWidth = 64; break;
@@ -1973,7 +2064,7 @@ static void RADEONGetVRamType(ScrnInfoPtr pScrn)
else info->RamWidth = 64;
}
- /* This may not be correct, as some cards can have half of channel disabled
+ /* This may not be correct, as some cards can have half of channel disabled
* ToDo: identify these cases
*/
}
@@ -1991,8 +2082,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
MessageType from;
unsigned char *RADEONMMIO = info->MMIO;
#ifdef XF86DRI
- const char *s;
- CARD32 agpCommand;
+ const char *s;
#endif
/* Chipset */
@@ -2026,6 +2116,8 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
info->HasCRTC2 = TRUE;
info->IsMobility = FALSE;
info->IsIGP = FALSE;
+ info->IsDellServer = FALSE;
+ info->HasSingleDAC = FALSE;
switch (info->Chipset) {
case PCI_CHIP_RADEON_LY:
case PCI_CHIP_RADEON_LZ:
@@ -2036,6 +2128,23 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
case PCI_CHIP_RV100_QY:
case PCI_CHIP_RV100_QZ:
info->ChipFamily = CHIP_FAMILY_RV100;
+
+ /* DELL triple-head configuration. */
+ if ((info->PciInfo->subsysVendor == PCI_VENDOR_DELL) &&
+ ((info->PciInfo->subsysCard == 0x016c) ||
+ (info->PciInfo->subsysCard == 0x016d) ||
+ (info->PciInfo->subsysCard == 0x016e) ||
+ (info->PciInfo->subsysCard == 0x016f) ||
+ (info->PciInfo->subsysCard == 0x0170) ||
+ (info->PciInfo->subsysCard == 0x017d) ||
+ (info->PciInfo->subsysCard == 0x017e) ||
+ (info->PciInfo->subsysCard == 0x0183) ||
+ (info->PciInfo->subsysCard == 0x018a) ||
+ (info->PciInfo->subsysCard == 0x019a))) {
+ info->IsDellServer = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DELL server detected, force to special setup\n");
+ }
+
break;
case PCI_CHIP_RS100_4336:
@@ -2085,10 +2194,13 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
break;
case PCI_CHIP_RS300_5835:
+ case PCI_CHIP_RS350_7835:
info->IsMobility = TRUE;
case PCI_CHIP_RS300_5834:
+ case PCI_CHIP_RS350_7834:
info->ChipFamily = CHIP_FAMILY_RS300;
info->IsIGP = TRUE;
+ info->HasSingleDAC = TRUE;
break;
case PCI_CHIP_RV280_5C61:
@@ -2139,6 +2251,46 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
info->ChipFamily = CHIP_FAMILY_R350;
break;
+ case PCI_CHIP_RV380_3150:
+ case PCI_CHIP_RV380_3154:
+ info->IsMobility = TRUE;
+ case PCI_CHIP_RV380_3E50:
+ case PCI_CHIP_RV380_3E54:
+ info->ChipFamily = CHIP_FAMILY_RV380;
+ break;
+
+ case PCI_CHIP_RV370_5460:
+ case PCI_CHIP_RV370_5464:
+ info->IsMobility = TRUE;
+ case PCI_CHIP_RV370_5B60:
+ case PCI_CHIP_RV370_5B64:
+ case PCI_CHIP_RV370_5B65:
+ info->ChipFamily = CHIP_FAMILY_RV380;
+ break;
+
+ case PCI_CHIP_R420_JN:
+ info->IsMobility = TRUE;
+ case PCI_CHIP_R420_JH:
+ case PCI_CHIP_R420_JI:
+ case PCI_CHIP_R420_JJ:
+ case PCI_CHIP_R420_JK:
+ case PCI_CHIP_R420_JL:
+ case PCI_CHIP_R420_JM:
+ case PCI_CHIP_R420_JP:
+ info->ChipFamily = CHIP_FAMILY_R420;
+ break;
+
+ case PCI_CHIP_R423_UH:
+ case PCI_CHIP_R423_UI:
+ case PCI_CHIP_R423_UJ:
+ case PCI_CHIP_R423_UK:
+ case PCI_CHIP_R423_UQ:
+ case PCI_CHIP_R423_UR:
+ case PCI_CHIP_R423_UT:
+ case PCI_CHIP_R423_5D57:
+ info->ChipFamily = CHIP_FAMILY_R420;
+ break;
+
default:
/* Original Radeon/7200 */
info->ChipFamily = CHIP_FAMILY_RADEON;
@@ -2189,30 +2341,25 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
(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);
+ OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024);
+ } else {
+ /* There are different HDP mapping schemes depending on single/multi funciton setting,
+ * chip family, HDP mode, and the generation of HDP mapping scheme.
+ * To make things simple, we only allow maximum 128M addressable FB. Anything more than
+ * 128M is configured as invisible FB to CPU that can only be accessed from chip side.
+ */
+ pScrn->videoRam = INREG(RADEON_CONFIG_MEMSIZE) / 1024;
+ if (pScrn->videoRam > 128*1024) pScrn->videoRam = 128*1024;
+ if ((info->ChipFamily == CHIP_FAMILY_RV350) ||
+ (info->ChipFamily == CHIP_FAMILY_RV380) ||
+ (info->ChipFamily == CHIP_FAMILY_R420)) {
+ OUTREGP (RADEON_HOST_PATH_CNTL, (1<<23), ~(1<<23));
+ }
}
- 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;
@@ -2229,8 +2376,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 =
@@ -2301,7 +2447,7 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
if (pciReadLong(info->PciTag, PCI_CMD_STAT_REG) & RADEON_CAP_LIST) {
CARD32 cap_ptr, cap_id;
-
+
cap_ptr = pciReadLong(info->PciTag,
RADEON_CAPABILITIES_PTR_PCI_CONFIG)
& RADEON_CAP_PTR_MASK;
@@ -2334,14 +2480,17 @@ static Bool RADEONPreInitConfig(ScrnInfoPtr pScrn)
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Invalid BusType option, using detected type\n");
}
- } else if (xf86ReturnOptValBool(info->Options, OPTION_IS_PCI, FALSE)) {
- info->IsPCI = TRUE;
- xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forced into PCI mode\n");
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "ForcePCIMode is deprecated -- "
- "use BusType option instead\n");
}
#endif
+ xf86GetOptValBool(info->Options, OPTION_SHOWCACHE, &info->showCache);
+ if (info->showCache)
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option ShowCache enabled\n");
+
+#ifdef RENDER
+ info->RenderAccel = xf86ReturnOptValBool (info->Options,
+ OPTION_RENDER_ACCEL, TRUE);
+#endif
return TRUE;
}
@@ -2682,25 +2831,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
@@ -2716,7 +2869,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.
*/
@@ -2823,8 +2976,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 */
@@ -2882,7 +3040,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;
@@ -3116,243 +3274,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", clone_mode_names[0]);
- }
- }
-
- 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;
- }
- }
-
- 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;
-
- 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 ((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;
- }
- }
-
- 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) {
+ if (info->MergeType == MT_CRT && !info->ddc_mode) {
+
modesFound =
- xf86ValidateModes(pScrn, pScrn->monitor->Modes,
- clone_mode_names,
+ xf86ValidateModes(pScrn,
+ pScrn->monitor->Modes,
+ pScrn1->display->modes,
clockRanges,
- NULL, /* linePitches */
- 8 * 64, /* minPitch */
- 8 * 1024, /* maxPitch */
- 64 * pScrn->bitsPerPixel, /* pitchInc */
- 128, /* minHeight */
- 2048, /* maxHeight */
- pScrn->display->virtualX,
- pScrn->display->virtualY,
+ 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);
- } else {
- /* Try to add DDC modes */
- info->IsSecondary = TRUE; /*fake secondary head*/
- modesFound = RADEONValidateDDCModes(pScrn, clone_mode_names,
- info->CloneType);
- info->IsSecondary = FALSE;
- /* 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 (modesFound == -1) return 0;
- tmp_mode = clone_mode;
- clone_mode->next = NULL;
- }
- pScrn->modes = pScrn->modes->next;
+ xf86PruneDriverModes(pScrn);
+ if (!modesFound || !pScrn->modes) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ return 0;
}
- /* no longer needed, free it */
- pScrn->modes = save_mode;
+ } else {
+ /* First, free any allocated modes during configuration, since
+ * we don't need them
+ */
while (pScrn->modes)
- xf86DeleteMode(&pScrn->modes, pScrn->modes);
- pScrn->modes = NULL;
-
- /* modepool is no longer needed, free it */
+ xf86DeleteMode(&pScrn->modes, pScrn->modes);
while (pScrn->modePool)
- xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
- pScrn->modePool = NULL;
+ xf86DeleteMode(&pScrn->modePool, pScrn->modePool);
- modesFound = valid;
- }
+ /* Next try to add DDC modes */
+ modesFound = RADEONValidateDDCModes(pScrn, pScrn1->display->modes,
+ info->MergeType, 1);
- /* 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;
- }
+ /* If that fails and we're connect to a flat panel, then try to
+ * add the flat panel modes
+ */
+ if (info->MergeType != MT_CRT) {
+
+ /* 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;
+ }
+ }
- free(clone_mode_names);
- clone_mode_names = 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);
- /* 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;
+ /* 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;
+ }
- /*
- * 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.
*/
@@ -3391,48 +3472,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");
@@ -3459,16 +3513,16 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10)
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Panel size is forced to: %s\n", s);
- /* We can't trust BIOS or DDC timings anymore,
+ /* 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
+ 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) &&
+ if ((tmp_mode->HDisplay == PanelX) &&
(tmp_mode->VDisplay == PanelY)) {
float refresh =
@@ -3573,7 +3627,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
@@ -3644,30 +3698,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;
@@ -3702,16 +3836,21 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn)
int errmaj = 0, errmin = 0;
info->xaaReq.majorversion = 1;
- info->xaaReq.minorversion = 1;
+ info->xaaReq.minorversion = 2;
if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL,
&info->xaaReq, &errmaj, &errmin)) {
- info->xaaReq.minorversion = 0;
+ info->xaaReq.minorversion = 1;
if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL,
&info->xaaReq, &errmaj, &errmin)) {
- LoaderErrorMsg(NULL, "xaa", errmaj, errmin);
- return FALSE;
+ info->xaaReq.minorversion = 0;
+
+ if (!LoadSubModule(pScrn->module, "xaa", NULL, NULL, NULL,
+ &info->xaaReq, &errmaj, &errmin)) {
+ LoaderErrorMsg(NULL, "xaa", errmaj, errmin);
+ return FALSE;
+ }
}
}
xf86LoaderReqSymLists(xaaSymbols, NULL);
@@ -3779,8 +3918,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:
@@ -3903,9 +4044,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;
@@ -4027,7 +4166,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
info->videoKey = 0x1E;
}
- info->DispPriority = 1;
+ info->DispPriority = 1;
if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) {
if (strcmp(s, "AUTO") == 0) {
info->DispPriority = 1;
@@ -4036,7 +4175,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
} else if (strcmp(s, "HIGH") == 0) {
info->DispPriority = 2;
} else
- info->DispPriority = 1;
+ info->DispPriority = 1;
}
if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) {
@@ -4046,7 +4185,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
xf86LoaderReqSymLists(fbdevHWSymbols, NULL);
if (fbdevHWInit(pScrn, info->PciInfo, NULL)) {
- pScrn->ValidMode = fbdevHWValidMode;
+ pScrn->ValidMode = fbdevHWValidModeWeak();
info->FBDev = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Using framebuffer device\n");
@@ -4071,13 +4210,17 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
RADEONPreInitDDC(pScrn);
- if (!RADEONGetBIOSParameters(pScrn, pInt10))
- goto fail;
-
- if (info->DisplayType == MT_DFP)
- RADEONGetTMDSInfo(pScrn);
+ RADEONGetBIOSInfo(pScrn, pInt10);
+ if (!RADEONQueryConnectedMonitors(pScrn)) goto fail;
+ RADEONGetClockInfo(pScrn);
+ RADEONGetPanelInfo(pScrn);
- if (!RADEONGetPLLParameters(pScrn)) goto fail;
+ /* 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 (!RADEONPreInitGamma(pScrn)) goto fail;
@@ -4105,7 +4248,7 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags)
info->MMIO = NULL;
xf86DrvMsg(pScrn->scrnIndex, X_NOTICE,
- "For information on using the multimedia capabilities\n of this"
+ "For information on using the multimedia capabilities\n\tof this"
" adapter, please see http://gatos.sf.net.\n");
return TRUE;
@@ -4131,6 +4274,7 @@ fail:
fail2:
if(info->MMIO) RADEONUnmapMMIO(pScrn);
info->MMIO = NULL;
+
fail1:
RADEONFreeRec(pScrn);
@@ -4151,7 +4295,7 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors,
if (info->CPStarted) DRILock(pScrn->pScreen, 0);
#endif
- if (info->accelOn) info->accel->Sync(pScrn);
+ if (info->accelOn && pScrn->pScreen) info->accel->Sync(pScrn);
if (info->FBDev) {
fbdevHWLoadPalette(pScrn, numColors, indices, colors, pVisual);
@@ -4212,7 +4356,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. */
@@ -4284,6 +4428,12 @@ static void RADEONBlockHandler(int i, pointer blockData,
if (info->VideoTimerCallback)
(*info->VideoTimerCallback)(pScrn, currentTime.milliseconds);
+
+#ifdef RENDER
+ if(info->RenderCallback)
+ (*info->RenderCallback)(pScrn);
+#endif
+
}
/* Called at the start of each server generation. */
@@ -4293,6 +4443,10 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
RADEONInfoPtr info = RADEONPTR(pScrn);
BoxRec MemBox;
int y2;
+#ifdef RENDER
+ int subPixelOrder = SubPixelUnknown;
+ char* s;
+#endif
RADEONTRACE(("RADEONScreenInit %x %d\n",
pScrn->memPhysBase, pScrn->fbOffset));
@@ -4316,6 +4470,13 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
info->PaletteSavedOnVT = FALSE;
RADEONSave(pScrn);
+
+ if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
+ RADEONSetDynamicClock(pScrn, 1);
+ } else {
+ RADEONSetDynamicClock(pScrn, 0);
+ }
+
if (info->FBDev) {
unsigned char *RADEONMMIO = info->MMIO;
@@ -4329,14 +4490,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,
@@ -4365,48 +4518,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,
@@ -4435,10 +4592,14 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
fbPictureInit (pScreen, 0, 0);
#ifdef RENDER
- if (PictureGetSubpixelOrder (pScreen) == SubPixelUnknown)
- {
- int subPixelOrder;
+ if ((s = xf86GetOptValString(info->Options, OPTION_SUBPIXEL_ORDER))) {
+ if (strcmp(s, "RGB") == 0) subPixelOrder = SubPixelHorizontalRGB;
+ else if (strcmp(s, "BGR") == 0) subPixelOrder = SubPixelHorizontalBGR;
+ else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone;
+ PictureSetSubpixelOrder (pScreen, subPixelOrder);
+ }
+ if (PictureGetSubpixelOrder (pScreen) == SubPixelUnknown) {
switch (info->DisplayType) {
case MT_NONE: subPixelOrder = SubPixelUnknown; break;
case MT_LCD: subPixelOrder = SubPixelHorizontalRGB; break;
@@ -4458,15 +4619,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
int bufferSize = ((pScrn->virtualY * width_bytes
+ RADEON_BUFFER_ALIGN)
& ~RADEON_BUFFER_ALIGN);
- int depthSize = ((((pScrn->virtualY+15) & ~15) * width_bytes
- + RADEON_BUFFER_ALIGN)
- & ~RADEON_BUFFER_ALIGN);
+ int depthSize;
int l;
int scanlines;
info->frontOffset = 0;
info->frontPitch = pScrn->displayWidth;
+ /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels,
+ * and its height a multiple of 16 lines.
+ */
+ info->depthPitch = (pScrn->displayWidth + 31) & ~31;
+ depthSize = ((((pScrn->virtualY+15) & ~15) * info->depthPitch
+ * info->CurrentLayout.pixel_bytes + RADEON_BUFFER_ALIGN)
+ & ~RADEON_BUFFER_ALIGN);
+
switch (info->CPMode) {
case RADEON_DEFAULT_CP_PIO_MODE:
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n");
@@ -4557,7 +4724,6 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
info->depthOffset = ((info->textureOffset - depthSize +
RADEON_BUFFER_ALIGN) &
~(CARD32)RADEON_BUFFER_ALIGN);
- info->depthPitch = pScrn->displayWidth;
/* Reserve space for the shared back buffer */
if (info->noBackBuffer) {
@@ -4638,13 +4804,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
{
@@ -4700,10 +4866,6 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (RADEONAccelInit(pScreen)) {
xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
info->accelOn = TRUE;
-
- /* FIXME: Figure out why this was added because it shouldn't be! */
- /* This is needed by the DRI and XAA code for shared entities */
- pScrn->pScreen = pScreen;
} else {
xf86DrvMsg(scrnIndex, X_ERROR,
"Acceleration initialization failed\n");
@@ -4775,6 +4937,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);
@@ -4785,11 +4958,13 @@ 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. */
+ /* we need to re-calculate bandwidth because of AGPMode difference. */
RADEONInitDispBandwidth(pScrn);
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
@@ -4831,13 +5006,11 @@ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
if (info->HasCRTC2 &&
!info->IsSwitching &&
info->ChipFamily != CHIP_FAMILY_R200 &&
- info->ChipFamily != CHIP_FAMILY_R300 &&
- info->ChipFamily != CHIP_FAMILY_R350 &&
- info->ChipFamily != CHIP_FAMILY_RV350) {
+ !IS_R300_VARIANT) {
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);
@@ -4899,6 +5072,13 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
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);
+
+ if (info->IsDellServer) {
+ OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl);
+ OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
+ OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
+ OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
+ }
}
/* Write CRTC2 registers */
@@ -4918,9 +5098,7 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
OUTREG(RADEON_TV_DAC_CNTL, 0x00280203);
if ((info->ChipFamily == CHIP_FAMILY_R200) ||
- (info->ChipFamily == CHIP_FAMILY_R300) ||
- (info->ChipFamily == CHIP_FAMILY_R350) ||
- (info->ChipFamily == CHIP_FAMILY_RV350)) {
+ IS_R300_VARIANT) {
OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl);
} else {
OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug);
@@ -4935,8 +5113,8 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch);
OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl);
- if ((info->DisplayType == MT_DFP && info->IsSecondary) ||
- info->CloneType == MT_DFP) {
+ if ((info->DisplayType == MT_DFP && info->IsSecondary) ||
+ 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);
@@ -4971,9 +5149,14 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore)
OUTREG(RADEON_GRPH_BUFFER_CNTL,
INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
+ if (info->IsMobility) {
+ OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch);
+ OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch);
+ OUTREG(RADEON_BIOS_6_SCRATCH, restore->bios_6_scratch);
+ }
+
if (info->DisplayType != MT_DFP) {
unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
- OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch);
if (info->IsMobility || info->IsIGP) {
/* Asic bug, when turning off LVDS_ON, we have to make sure
@@ -5096,10 +5279,8 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
RADEON_PLL_DIV_SEL,
~(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 (IS_R300_VARIANT ||
+ (info->ChipFamily == CHIP_FAMILY_RS300)) {
if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
/* When restoring console mode, use saved PPLL_REF_DIV
* setting.
@@ -5139,11 +5320,6 @@ 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",
- 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);
-
RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n",
restore->ppll_ref_div,
restore->ppll_div_3,
@@ -5154,7 +5330,7 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn,
restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK,
(restore->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16));
- usleep(5000); /* Let the clock to lock */
+ usleep(50000); /* Let the clock to lock */
OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
RADEON_VCLK_SRC_SEL_PPLLCLK,
@@ -5298,7 +5474,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);
}
@@ -5383,6 +5559,13 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
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);
+
+ if (info->IsDellServer) {
+ save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL);
+ save->dac2_cntl = INREG(RADEON_DAC_CNTL2);
+ save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG);
+ save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+ }
}
/* Read flat panel registers */
@@ -5402,7 +5585,9 @@ static void RADEONSaveFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
save->lvds_pll_cntl = INREG(RADEON_LVDS_PLL_CNTL);
save->tmds_pll_cntl = INREG(RADEON_TMDS_PLL_CNTL);
save->tmds_transmitter_cntl= INREG(RADEON_TMDS_TRANSMITTER_CNTL);
+ save->bios_4_scratch = INREG(RADEON_BIOS_4_SCRATCH);
save->bios_5_scratch = INREG(RADEON_BIOS_5_SCRATCH);
+ save->bios_6_scratch = INREG(RADEON_BIOS_6_SCRATCH);
if (info->ChipFamily == CHIP_FAMILY_RV280) {
/* bit 22 of TMDS_PLL_CNTL is read-back inverted */
@@ -5504,7 +5689,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);
}
@@ -5583,7 +5768,7 @@ static void RADEONRestore(ScrnInfoPtr pScrn)
/* 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
@@ -5650,6 +5835,7 @@ 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)
{
@@ -5686,10 +5872,13 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
int stop_req, max_stop_req;
float read_return_rate, time_disp1_drop_priority;
+ /* R420 family not supported yet */
+ if (info->ChipFamily == CHIP_FAMILY_R420) return;
+
if (pRADEONEnt->pSecondaryScrn) {
if (info->IsSecondary) return;
info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn);
- } else if (info->Clone) info2 = info;
+ } else if (info->MergedFB) info2 = info;
/*
* Determine if there is enough bandwidth for current display mode
@@ -5697,12 +5886,14 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
mem_bw = info->mclk * (info->RamWidth / 8) * (info->IsDDR ? 2 : 1);
mode1 = info->CurrentLayout.mode;
- if (info->Clone)
- mode2 = info->CurCloneMode;
- else if ((pRADEONEnt->HasSecondary) && info2)
+ 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
+ } else {
mode2 = NULL;
+ }
pix_clk = mode1->Clock/1000.0;
if (mode2)
@@ -5711,35 +5902,29 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
pix_clk2 = 0;
peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes);
- if (info2)
+ 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,
+ 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 ]
+ 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))
+ if (IS_RV100_VARIANT)
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 */
@@ -5751,8 +5936,8 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
mem_trp = MemTrpMemTimingCntl[ (temp & 0x700) >> 8];
mem_tras = MemTrasMemTimingCntl[(temp & 0xf000) >> 12];
}
-
- /* Get values from the MEM_SDRAM_MODE_REG register...converting its */
+
+ /* 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 */
@@ -5761,9 +5946,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
mem_tcas = MemTcas2 [data];
}
- if ((info->ChipFamily == CHIP_FAMILY_R300) ||
- (info->ChipFamily == CHIP_FAMILY_R350) ||
- (info->ChipFamily == CHIP_FAMILY_RV350)) {
+ if (IS_R300_VARIANT) {
/* on the R300, Tcas is included in Trbs.
*/
@@ -5804,9 +5987,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
/* 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)) {
+ if (IS_R300_VARIANT) {
/*not enough for R350 ???*/
/*
if (!mode2) sclk_delay = 150;
@@ -5828,7 +6009,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
}
mc_latency_sclk = sclk_delay / sclk_eff;
-
+
if (info->IsDDR) {
if (info->RamWidth == 32) {
k1 = 40;
@@ -5870,7 +6051,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
/*
Find the critical point of the display buffer.
*/
- critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5);
+ critical_point= (CARD32)(disp_drain_rate * disp_latency + 0.5);
/* ???? */
/*
@@ -5880,10 +6061,10 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
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;
+ if (info->ChipFamily == CHIP_FAMILY_R300)
+ critical_point += 0x10;
else
- critical_point = 0;
+ critical_point = 0;
}
else
critical_point = 0;
@@ -5893,7 +6074,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
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;
+ if (max_stop_req - critical_point < 4) critical_point = 0;
temp = info->SavedReg.grph_buffer_cntl;
temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
@@ -5937,18 +6118,18 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
RADEON_GRPH_CRITICAL_AT_SOF |
RADEON_GRPH_STOP_CNTL);
- if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+ 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 +
+ 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)
+ if (info->ChipFamily == CHIP_FAMILY_R300)
critical_point2 += 0x10;
else
critical_point2 = 0;
@@ -5964,7 +6145,7 @@ static void RADEONInitDispBandwidth(ScrnInfoPtr pScrn)
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,
@@ -5975,10 +6156,7 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
int format;
int hsync_start;
int hsync_wid;
- int hsync_fudge;
int vsync_wid;
- int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
- int hsync_fudge_fp[] = { 0x02, 0x02, 0x00, 0x00, 0x05, 0x05 };
switch (info->CurrentLayout.pixel_code) {
case 4: format = 1; break;
@@ -5996,7 +6174,6 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
if ((info->DisplayType == MT_DFP) ||
(info->DisplayType == MT_LCD)) {
- hsync_fudge = hsync_fudge_fp[format-1];
if (mode->Flags & RADEON_USE_RMX) {
#if 0
mode->CrtcHDisplay = info->PanelXRes;
@@ -6011,8 +6188,6 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
mode->Clock = info->DotClock;
mode->Flags = info->Flags | RADEON_USE_RMX;
}
- } else {
- hsync_fudge = hsync_fudge_default[format-1];
}
save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
@@ -6050,7 +6225,7 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
if (!hsync_wid) hsync_wid = 1;
- hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
+ hsync_start = mode->CrtcHSyncStart - 8;
save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
@@ -6088,16 +6263,15 @@ 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->crtc_more_cntl = 0;
+ 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.
+ */
+ save->crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
+ }
save->surface_cntl = 0;
save->disp_merge_cntl = info->SavedReg.disp_merge_cntl;
@@ -6118,6 +6292,23 @@ static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
}
#endif
+ if (info->IsDellServer) {
+ save->dac2_cntl = info->SavedReg.dac2_cntl;
+ save->tv_dac_cntl = info->SavedReg.tv_dac_cntl;
+ save->crtc2_gen_cntl = info->SavedReg.crtc2_gen_cntl;
+ save->disp_hw_debug = info->SavedReg.disp_hw_debug;
+
+ save->dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL;
+ save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
+
+ /* For CRT on DAC2, don't turn it on if BIOS didn't
+ enable it, even it's detected.
+ */
+ save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
+ save->tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16));
+ save->tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16));
+ }
+
RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
save->crtc_pitch, pScrn->virtualX,
info->CurrentLayout.displayWidth));
@@ -6134,9 +6325,7 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
int format;
int hsync_start;
int hsync_wid;
- int hsync_fudge;
int vsync_wid;
- int hsync_fudge_default[] = { 0x00, 0x12, 0x09, 0x09, 0x06, 0x05 };
switch (info->CurrentLayout.pixel_code) {
case 4: format = 1; break;
@@ -6152,8 +6341,6 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
return FALSE;
}
- hsync_fudge = hsync_fudge_default[format-1];
-
save->crtc2_gen_cntl = (RADEON_CRTC2_EN
| RADEON_CRTC2_CRT2_ON
| (format << 8)
@@ -6174,9 +6361,7 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
save->dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL;
save->disp_output_cntl = info->SavedReg.disp_output_cntl;
if (info->ChipFamily == CHIP_FAMILY_R200 ||
- info->ChipFamily == CHIP_FAMILY_R300 ||
- info->ChipFamily == CHIP_FAMILY_R350 ||
- info->ChipFamily == CHIP_FAMILY_RV350) {
+ IS_R300_VARIANT) {
save->disp_output_cntl &= ~(RADEON_DISP_DAC_SOURCE_MASK |
RADEON_DISP_DAC2_SOURCE_MASK);
if (pRADEONEnt->MonType1 != MT_CRT) {
@@ -6217,7 +6402,7 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8;
if (!hsync_wid) hsync_wid = 1;
- hsync_start = mode->CrtcHSyncStart - 8 + hsync_fudge;
+ hsync_start = mode->CrtcHSyncStart - 8;
save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
@@ -6250,31 +6435,35 @@ 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) {
+ if ((info->DisplayType == MT_DFP && info->IsSecondary) ||
+ 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;
- save->fp2_gen_cntl = (RADEON_FP2_PANEL_FORMAT |
- RADEON_FP2_ON);
- if (info->ChipFamily >= CHIP_FAMILY_R200) {
- save->fp2_gen_cntl |= RADEON_FP2_DV0_EN;
- }
+ save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | RADEON_FP2_ON;
if (info->ChipFamily == CHIP_FAMILY_R200 ||
- info->ChipFamily == CHIP_FAMILY_R300 ||
- info->ChipFamily == CHIP_FAMILY_R350 ||
- info->ChipFamily == CHIP_FAMILY_RV350) {
- save->fp2_gen_cntl &= ~RADEON_FP2_SOURCE_SEL_MASK;
- save->fp2_gen_cntl |= RADEON_FP2_SOURCE_SEL_CRTC2;
+ IS_R300_VARIANT) {
+ save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK |
+ RADEON_FP2_DVO_RATE_SEL_SDR);
+
+ save->fp2_gen_cntl |= (R200_FP2_SOURCE_SEL_CRTC2 |
+ RADEON_FP2_DVO_EN);
} else {
save->fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_MASK;
save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2;
@@ -6285,16 +6474,6 @@ static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
else
save->fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format */
- /* 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.
- */
-
- /* 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
- * to the console mode.
- */
- info->SavedReg.fp2_gen_cntl = RADEON_FP2_ON;
}
RADEONTRACE(("Pitch = %d bytes (virtualX = %d, displayWidth = %d)\n",
@@ -6412,6 +6591,16 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
else
save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */
+ if (IS_R300_VARIANT ||
+ (info->ChipFamily == CHIP_FAMILY_R200)) {
+ save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
+ if (mode->Flags & RADEON_USE_RMX)
+ save->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
+ else
+ save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
+ } else
+ save->fp_gen_cntl |= RADEON_FP_SEL_CRTC1;
+
save->lvds_gen_cntl = orig->lvds_gen_cntl;
save->lvds_pll_cntl = orig->lvds_pll_cntl;
@@ -6425,7 +6614,7 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
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.
@@ -6438,15 +6627,6 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
} else {
if (info->DisplayType == MT_LCD) {
- RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
-
- /* 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)
- save->bios_5_scratch = 0x01020201;
- else
- save->bios_5_scratch = orig->bios_5_scratch;
save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON);
save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN);
@@ -6461,9 +6641,7 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
break;
}
}
- if ((info->ChipFamily == CHIP_FAMILY_R300) ||
- (info->ChipFamily == CHIP_FAMILY_R350) ||
- (info->ChipFamily == CHIP_FAMILY_RV350) ||
+ if (IS_R300_VARIANT ||
(info->ChipFamily == CHIP_FAMILY_RV280)) {
if (tmp & 0xfff00000)
save->tmds_pll_cntl = tmp;
@@ -6471,14 +6649,12 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
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,
+ 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) ||
- (info->ChipFamily == CHIP_FAMILY_R350) ||
- (info->ChipFamily == CHIP_FAMILY_RV350) ||
+ if (IS_R300_VARIANT ||
(info->ChipFamily == CHIP_FAMILY_R200) || !info->HasCRTC2)
save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN);
else /* weird, RV chips got this bit reversed? */
@@ -6488,6 +6664,36 @@ static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr orig,
}
}
+ if (info->IsMobility) {
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+
+ /* To work correctly with laptop hotkeys.
+ * Since there is no machnism for accessing ACPI evnets
+ * and the driver currently doesn't know how to validate
+ * a mode dynamically, we have to tell BIOS don't do
+ * display switching after X has started.
+ * If LCD is on, lid close/open should still work
+ * with below settings
+ */
+ if (info->DisplayType == MT_LCD) {
+ if (pRADEONEnt->MonType2 == MT_CRT)
+ save->bios_5_scratch = 0x0201;
+ else if (pRADEONEnt->MonType2 == MT_DFP)
+ save->bios_5_scratch = 0x0801;
+ else
+ save->bios_5_scratch = orig->bios_5_scratch;
+ } else {
+ if (pRADEONEnt->MonType2 == MT_CRT)
+ save->bios_5_scratch = 0x0200;
+ else if (pRADEONEnt->MonType2 == MT_DFP)
+ save->bios_5_scratch = 0x0800;
+ else
+ save->bios_5_scratch = 0x0;
+ }
+ save->bios_4_scratch = 0x4;
+ save->bios_6_scratch = orig->bios_6_scratch | 0x40000000;
+ }
+
save->fp_crtc_h_total_disp = save->crtc_h_total_disp;
save->fp_crtc_v_total_disp = save->crtc_v_total_disp;
save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid;
@@ -6682,6 +6888,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 {
if (!RADEONInitCrtcRegisters(pScrn, save, mode, info))
return FALSE;
@@ -6700,16 +6923,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;
@@ -6774,56 +7006,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;
}
@@ -6839,6 +7022,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;
}
@@ -6875,11 +7065,21 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
- int reg, Base = y * info->CurrentLayout.displayWidth + x;
+ int reg, Base;
#ifdef XF86DRI
RADEONSAREAPrivPtr pSAREAPriv;
#endif
+ if (info->showCache && y) {
+ int lastline = info->FbMapSize /
+ ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
+
+ lastline -= pScrn->currentMode->VDisplay;
+ y += (pScrn->virtualY - 1) * (y / 3 + 1);
+ if (y > lastline) y = lastline;
+ }
+ Base = y * info->CurrentLayout.displayWidth + x;
+
switch (info->CurrentLayout.pixel_code) {
case 15:
case 16: Base *= 2; break;
@@ -6925,7 +7125,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);
@@ -6978,9 +7180,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;
}
@@ -7033,6 +7232,11 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen)
}
#endif
+ if(info->RenderTex) {
+ xf86FreeOffscreenLinear(info->RenderTex);
+ info->RenderTex = NULL;
+ }
+
if (pScrn->vtSema) {
RADEONRestore(pScrn);
}
@@ -7062,9 +7266,47 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen)
void RADEONFreeScreen(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
RADEONTRACE(("RADEONFreeScreen\n"));
+ /* when server quits at PreInit, we don't need do this anymore*/
+ if (!info) return;
+
+ 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);
@@ -7127,9 +7369,9 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC)
} else {
CARD32 fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL);
if (IsOn) {
- fp2_gen_cntl |= RADEON_FP2_DV0_EN;
+ fp2_gen_cntl |= RADEON_FP2_DVO_EN;
} else {
- fp2_gen_cntl &= ~RADEON_FP2_DV0_EN;
+ fp2_gen_cntl &= ~RADEON_FP2_DVO_EN;
}
OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
}
@@ -7145,6 +7387,8 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
+ if (!pScrn->vtSema) return;
+
#ifdef XF86DRI
if (info->CPStarted) DRILock(pScrn->pScreen, 0);
#endif
@@ -7167,7 +7411,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);
}
@@ -7180,7 +7424,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);
@@ -7197,7 +7441,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);
@@ -7212,7 +7456,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);
}
@@ -7225,21 +7469,17 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
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) {
- OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DV0_EN, ~RADEON_FP2_DV0_EN);
+ OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN);
}
} else if (info->DisplayType == MT_CRT) {
RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC);
}
} else {
- if (info->Clone) {
- if (info->CloneType == 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) {
- OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DV0_EN, ~RADEON_FP2_DV0_EN);
- }
- } else if (info->CloneType == MT_CRT) {
- RADEONDacPowerSet(pScrn, TRUE, !pRADEONEnt->ReversedDAC);
+ 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) {
+ OUTREGP (RADEON_FP2_GEN_CNTL, RADEON_FP2_DVO_EN, ~RADEON_FP2_DVO_EN);
}
}
if (info->DisplayType == MT_DFP) {
@@ -7251,7 +7491,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
usleep (info->PanelPwrDly * 1000);
OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON);
} else if (info->DisplayType == MT_CRT) {
- if ((pRADEONEnt->HasSecondary) || info->Clone) {
+ if ((pRADEONEnt->HasSecondary) || info->MergedFB) {
RADEONDacPowerSet(pScrn, TRUE, pRADEONEnt->ReversedDAC);
} else {
RADEONDacPowerSet(pScrn, TRUE, TRUE);
@@ -7268,21 +7508,17 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
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) {
- OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DV0_EN);
+ OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN);
}
} else if (info->DisplayType == MT_CRT) {
RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC);
}
} else {
- if (info->Clone) {
- if(info->CloneType == 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) {
- OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DV0_EN);
- }
- } else if (info->CloneType == MT_CRT) {
- RADEONDacPowerSet(pScrn, FALSE, !pRADEONEnt->ReversedDAC);
+ 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) {
+ OUTREGP (RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_DVO_EN);
}
}
if (info->DisplayType == MT_DFP) {
@@ -7304,7 +7540,7 @@ static void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn,
OUTPLL(RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
}
} else if (info->DisplayType == MT_CRT) {
- if ((pRADEONEnt->HasSecondary) || info->Clone) {
+ if ((pRADEONEnt->HasSecondary) || info->MergedFB) {
RADEONDacPowerSet(pScrn, FALSE, pRADEONEnt->ReversedDAC);
} else {
/* single CRT, turning both DACs off, we don't really know
@@ -7323,3 +7559,551 @@ 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;
+ }
+ }
+}
+
+static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 tmp;
+ switch(mode) {
+ case 0: /* Turn everything OFF (ForceON to everything)*/
+ if ( !info->HasCRTC2 ) {
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP |
+ RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP |
+ RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE |
+ RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP |
+ RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB |
+ RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM |
+ RADEON_SCLK_FORCE_RB);
+ OUTPLL(RADEON_SCLK_CNTL, tmp);
+ } else if (info->ChipFamily == CHIP_FAMILY_RV350) {
+ /* for RV350/M10, no delays are required. */
+ tmp = INPLL(pScrn, R300_SCLK_CNTL2);
+ tmp |= (R300_SCLK_FORCE_TCL |
+ R300_SCLK_FORCE_GA |
+ R300_SCLK_FORCE_CBA);
+ OUTPLL(R300_SCLK_CNTL2, tmp);
+
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
+ RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 |
+ RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
+ R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
+ RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
+ R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
+ R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
+ R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
+ OUTPLL(RADEON_SCLK_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
+ tmp |= RADEON_SCLK_MORE_FORCEON;
+ OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
+ tmp |= (RADEON_FORCEON_MCLKA |
+ RADEON_FORCEON_MCLKB |
+ RADEON_FORCEON_YCLKA |
+ RADEON_FORCEON_YCLKB |
+ RADEON_FORCEON_MC);
+ OUTPLL(RADEON_MCLK_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+ tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
+ RADEON_PIXCLK_DAC_ALWAYS_ONb |
+ R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
+ OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+ tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
+ RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+ RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+ R300_DVOCLK_ALWAYS_ONb |
+ RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+ RADEON_PIXCLK_GV_ALWAYS_ONb |
+ R300_PIXCLK_DVO_ALWAYS_ONb |
+ RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+ RADEON_PIXCLK_TMDS_ALWAYS_ONb |
+ R300_PIXCLK_TRANS_ALWAYS_ONb |
+ R300_PIXCLK_TVO_ALWAYS_ONb |
+ R300_P2G2CLK_ALWAYS_ONb |
+ R300_P2G2CLK_ALWAYS_ONb |
+ R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
+ OUTPLL(RADEON_PIXCLKS_CNTL, tmp);
+ } else {
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2);
+ tmp |= RADEON_SCLK_FORCE_SE;
+
+ if ( !info->HasCRTC2 ) {
+ tmp |= ( RADEON_SCLK_FORCE_RB |
+ RADEON_SCLK_FORCE_TDM |
+ RADEON_SCLK_FORCE_TAM |
+ RADEON_SCLK_FORCE_PB |
+ RADEON_SCLK_FORCE_RE |
+ RADEON_SCLK_FORCE_VIP |
+ RADEON_SCLK_FORCE_IDCT |
+ RADEON_SCLK_FORCE_TOP |
+ RADEON_SCLK_FORCE_DISP1 |
+ RADEON_SCLK_FORCE_DISP2 |
+ RADEON_SCLK_FORCE_HDP );
+ } else if ((info->ChipFamily == CHIP_FAMILY_R300) ||
+ (info->ChipFamily == CHIP_FAMILY_R350)) {
+ tmp |= ( RADEON_SCLK_FORCE_HDP |
+ RADEON_SCLK_FORCE_DISP1 |
+ RADEON_SCLK_FORCE_DISP2 |
+ RADEON_SCLK_FORCE_TOP |
+ RADEON_SCLK_FORCE_IDCT |
+ RADEON_SCLK_FORCE_VIP);
+ }
+ OUTREG(RADEON_SCLK_CNTL, tmp);
+
+ usleep(16000);
+
+ if ((info->ChipFamily == CHIP_FAMILY_R300) ||
+ (info->ChipFamily == CHIP_FAMILY_R350)) {
+ tmp = INPLL(pScrn, R300_SCLK_CNTL2);
+ tmp |= ( R300_SCLK_FORCE_TCL |
+ R300_SCLK_FORCE_GA |
+ R300_SCLK_FORCE_CBA);
+ OUTPLL(R300_SCLK_CNTL2, tmp);
+ usleep(16000);
+ }
+
+ if (info->IsIGP) {
+ tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
+ tmp &= ~(RADEON_FORCEON_MCLKA |
+ RADEON_FORCEON_YCLKA);
+ OUTREG(RADEON_MCLK_CNTL, tmp);
+ usleep(16000);
+ }
+
+ if ((info->ChipFamily == CHIP_FAMILY_RV200) ||
+ (info->ChipFamily == CHIP_FAMILY_RV250) ||
+ (info->ChipFamily == CHIP_FAMILY_RV280)) {
+ tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
+ tmp |= RADEON_SCLK_MORE_FORCEON;
+ OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+ usleep(16000);
+ }
+
+ tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+ tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
+ RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+ RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+ RADEON_PIXCLK_GV_ALWAYS_ONb |
+ RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
+ RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+ RADEON_PIXCLK_TMDS_ALWAYS_ONb);
+
+ OUTREG(RADEON_PIXCLKS_CNTL, tmp);
+ usleep(16000);
+
+ tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+ tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
+ RADEON_PIXCLK_DAC_ALWAYS_ONb);
+ OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Disabled\n");
+ break;
+ case 1:
+ if (!info->HasCRTC2) {
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ if ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) >
+ RADEON_CFG_ATI_REV_A13) {
+ tmp &= ~(RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_RB);
+ }
+ tmp &= ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 |
+ RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE |
+ RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE |
+ RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM |
+ RADEON_SCLK_FORCE_TDM);
+ OUTPLL (RADEON_SCLK_CNTL, tmp);
+ } else if ((info->ChipFamily == CHIP_FAMILY_R300) ||
+ (info->ChipFamily == CHIP_FAMILY_R350) ||
+ (info->ChipFamily == CHIP_FAMILY_RV350)) {
+ if (info->ChipFamily == CHIP_FAMILY_RV350) {
+ tmp = INPLL(pScrn, R300_SCLK_CNTL2);
+ tmp &= ~(R300_SCLK_FORCE_TCL |
+ R300_SCLK_FORCE_GA |
+ R300_SCLK_FORCE_CBA);
+ tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT |
+ R300_SCLK_GA_MAX_DYN_STOP_LAT |
+ R300_SCLK_CBA_MAX_DYN_STOP_LAT);
+ OUTPLL(R300_SCLK_CNTL2, tmp);
+
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
+ RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 |
+ RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 |
+ R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT |
+ RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR |
+ R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
+ R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
+ R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
+ tmp |= RADEON_DYN_STOP_LAT_MASK;
+ OUTPLL(RADEON_SCLK_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
+ tmp &= ~RADEON_SCLK_MORE_FORCEON;
+ tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
+ OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+ tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
+ RADEON_PIXCLK_DAC_ALWAYS_ONb);
+ OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+ tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
+ RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+ RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb |
+ R300_DVOCLK_ALWAYS_ONb |
+ RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+ RADEON_PIXCLK_GV_ALWAYS_ONb |
+ R300_PIXCLK_DVO_ALWAYS_ONb |
+ RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+ RADEON_PIXCLK_TMDS_ALWAYS_ONb |
+ R300_PIXCLK_TRANS_ALWAYS_ONb |
+ R300_PIXCLK_TVO_ALWAYS_ONb |
+ R300_P2G2CLK_ALWAYS_ONb |
+ R300_P2G2CLK_ALWAYS_ONb);
+ OUTPLL(RADEON_PIXCLKS_CNTL, tmp);
+
+ tmp = INPLL(pScrn, RADEON_MCLK_MISC);
+ tmp |= (RADEON_MC_MCLK_DYN_ENABLE |
+ RADEON_IO_MCLK_DYN_ENABLE);
+ OUTPLL(RADEON_MCLK_MISC, tmp);
+
+ tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
+ tmp |= (RADEON_FORCEON_MCLKA |
+ RADEON_FORCEON_MCLKB);
+
+ tmp &= ~(RADEON_FORCEON_YCLKA |
+ RADEON_FORCEON_YCLKB |
+ RADEON_FORCEON_MC);
+
+ /* Some releases of vbios have set DISABLE_MC_MCLKA
+ and DISABLE_MC_MCLKB bits in the vbios table. Setting these
+ bits will cause H/W hang when reading video memory with dynamic clocking
+ enabled. */
+ if ((tmp & R300_DISABLE_MC_MCLKA) &&
+ (tmp & R300_DISABLE_MC_MCLKB)) {
+ /* If both bits are set, then check the active channels */
+ tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
+ if (info->RamWidth == 64) {
+ if (INREG(RADEON_MEM_CNTL) & R300_MEM_USE_CD_CH_ONLY)
+ tmp &= ~R300_DISABLE_MC_MCLKB;
+ else
+ tmp &= ~R300_DISABLE_MC_MCLKA;
+ } else {
+ tmp &= ~(R300_DISABLE_MC_MCLKA |
+ R300_DISABLE_MC_MCLKB);
+ }
+ }
+
+ OUTPLL(RADEON_MCLK_CNTL, tmp);
+ } else {
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ tmp &= ~(R300_SCLK_FORCE_VAP);
+ tmp |= RADEON_SCLK_FORCE_CP;
+ OUTPLL(RADEON_SCLK_CNTL, tmp);
+ usleep(15000);
+
+ tmp = INPLL(pScrn, R300_SCLK_CNTL2);
+ tmp &= ~(R300_SCLK_FORCE_TCL |
+ R300_SCLK_FORCE_GA |
+ R300_SCLK_FORCE_CBA);
+ OUTPLL(R300_SCLK_CNTL2, tmp);
+ }
+ } else {
+ tmp = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL);
+
+ tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK |
+ RADEON_DISP_DYN_STOP_LAT_MASK |
+ RADEON_DYN_STOP_MODE_MASK);
+
+ tmp |= (RADEON_ENGIN_DYNCLK_MODE |
+ (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
+ OUTPLL(RADEON_CLK_PWRMGT_CNTL, tmp);
+ usleep(15000);
+
+ tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL);
+ tmp |= RADEON_SCLK_DYN_START_CNTL;
+ OUTPLL(RADEON_CLK_PIN_CNTL, tmp);
+ usleep(15000);
+
+ /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
+ to lockup randomly, leave them as set by BIOS.
+ */
+ tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+ /*tmp &= RADEON_SCLK_SRC_SEL_MASK;*/
+ tmp &= ~RADEON_SCLK_FORCEON_MASK;
+
+ /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/
+ if (((info->ChipFamily == CHIP_FAMILY_RV250) &&
+ ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
+ RADEON_CFG_ATI_REV_A13)) ||
+ ((info->ChipFamily == CHIP_FAMILY_RV100) &&
+ ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <=
+ RADEON_CFG_ATI_REV_A13))){
+ tmp |= RADEON_SCLK_FORCE_CP;
+ tmp |= RADEON_SCLK_FORCE_VIP;
+ }
+
+ OUTPLL(RADEON_SCLK_CNTL, tmp);
+
+ if ((info->ChipFamily == CHIP_FAMILY_RV200) ||
+ (info->ChipFamily == CHIP_FAMILY_RV250) ||
+ (info->ChipFamily == CHIP_FAMILY_RV280)) {
+ tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
+ tmp &= ~RADEON_SCLK_MORE_FORCEON;
+
+ /* RV200::A11 A12 RV250::A11 A12 */
+ if (((info->ChipFamily == CHIP_FAMILY_RV200) ||
+ (info->ChipFamily == CHIP_FAMILY_RV250)) &&
+ ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
+ RADEON_CFG_ATI_REV_A13)) {
+ tmp |= RADEON_SCLK_MORE_FORCEON;
+ }
+ OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+ usleep(15000);
+ }
+
+ /* RV200::A11 A12, RV250::A11 A12 */
+ if (((info->ChipFamily == CHIP_FAMILY_RV200) ||
+ (info->ChipFamily == CHIP_FAMILY_RV250)) &&
+ ((INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) <
+ RADEON_CFG_ATI_REV_A13)) {
+ tmp = INPLL(pScrn, RADEON_PLL_PWRMGT_CNTL);
+ tmp |= RADEON_TCL_BYPASS_DISABLE;
+ OUTREG(RADEON_PLL_PWRMGT_CNTL, tmp);
+ }
+ usleep(15000);
+
+ /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK)*/
+ tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
+ tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
+ RADEON_PIX2CLK_DAC_ALWAYS_ONb |
+ RADEON_PIXCLK_BLEND_ALWAYS_ONb |
+ RADEON_PIXCLK_GV_ALWAYS_ONb |
+ RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb |
+ RADEON_PIXCLK_LVDS_ALWAYS_ONb |
+ RADEON_PIXCLK_TMDS_ALWAYS_ONb);
+
+ OUTPLL(RADEON_PIXCLKS_CNTL, tmp);
+ usleep(15000);
+
+ tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
+ tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
+ RADEON_PIXCLK_DAC_ALWAYS_ONb);
+
+ OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+ usleep(15000);
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Enabled\n");
+ break;
+ default:
+ break;
+ }
+}
+
+void RADEONFillInScreenInfo(ScrnInfoPtr pScrn)
+{
+ pScrn->driverVersion = RADEON_VERSION_CURRENT;
+ pScrn->driverName = RADEON_DRIVER_NAME;
+ pScrn->name = RADEON_NAME;
+ pScrn->PreInit = RADEONPreInit;
+ pScrn->ScreenInit = RADEONScreenInit;
+ pScrn->SwitchMode = RADEONSwitchMode;
+#ifdef X_XF86MiscPassMessage
+ pScrn->HandleMessage = RADEONHandleMessage;
+#endif
+ pScrn->AdjustFrame = RADEONAdjustFrame;
+ pScrn->EnterVT = RADEONEnterVT;
+ pScrn->LeaveVT = RADEONLeaveVT;
+ pScrn->FreeScreen = RADEONFreeScreen;
+ pScrn->ValidMode = RADEONValidMode;
+}
diff --git a/src/radeon_macros.h b/src/radeon_macros.h
index b420a30f..71b90834 100644
--- a/src/radeon_macros.h
+++ b/src/radeon_macros.h
@@ -55,6 +55,14 @@
#endif
#include "compiler.h"
+#define RADEON_BIOS8(v) (info->VBIOS[v])
+#define RADEON_BIOS16(v) (info->VBIOS[v] | \
+ (info->VBIOS[(v) + 1] << 8))
+#define RADEON_BIOS32(v) (info->VBIOS[v] | \
+ (info->VBIOS[(v) + 1] << 8) | \
+ (info->VBIOS[(v) + 2] << 16) | \
+ (info->VBIOS[(v) + 3] << 24))
+
/* Memory mapped register access macros */
#define INREG8(addr) MMIO_IN8(RADEONMMIO, addr)
#define INREG16(addr) MMIO_IN16(RADEONMMIO, addr)
diff --git a/src/radeon_mergedfb.c b/src/radeon_mergedfb.c
new file mode 100644
index 00000000..06bb8446
--- /dev/null
+++ b/src/radeon_mergedfb.c
@@ -0,0 +1,1562 @@
+/* $XFree86$ */
+/*
+ * Copyright 2003 Alex Deucher.
+ *
+ * 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 on 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 ALEX DEUCHER, OR ANY OTHER
+ * CONTRIBUTORS 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.
+ */
+
+/*
+ * Authors:
+ * Alex Deucher <agd5f@yahoo.com>
+ */
+
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86Resources.h"
+#include "xf86_OSproc.h"
+#include "extnsionst.h" /* required */
+#include "panoramiXproto.h" /* required */
+#include "dixstruct.h"
+#include "vbe.h"
+
+
+#include "radeon.h"
+#include "radeon_macros.h"
+#include "radeon_reg.h"
+#include "radeon_mergedfb.h"
+
+/* psuedo xinerama support */
+static unsigned char RADEONXineramaReqCode = 0;
+int RADEONXineramaPixWidth = 0;
+int RADEONXineramaPixHeight = 0;
+int RADEONXineramaNumScreens = 0;
+RADEONXineramaData *RADEONXineramadataPtr = NULL;
+static int RADEONXineramaGeneration;
+Bool RADEONnoPanoramiXExtension = TRUE;
+
+int RADEONProcXineramaQueryVersion(ClientPtr client);
+int RADEONProcXineramaGetState(ClientPtr client);
+int RADEONProcXineramaGetScreenCount(ClientPtr client);
+int RADEONProcXineramaGetScreenSize(ClientPtr client);
+int RADEONProcXineramaIsActive(ClientPtr client);
+int RADEONProcXineramaQueryScreens(ClientPtr client);
+int RADEONSProcXineramaDispatch(ClientPtr client);
+
+static void
+RADEONChooseCursorCRTC(ScrnInfoPtr pScrn1, int x, int y);
+
+/* mergedfb functions */
+/* Helper function for CRT2 monitor vrefresh/hsync options
+ * (Taken from mga, sis drivers)
+ */
+int
+RADEONStrToRanges(range *r, char *s, int max)
+{
+ float num = 0.0;
+ int rangenum = 0;
+ Bool gotdash = FALSE;
+ Bool nextdash = FALSE;
+ char* strnum = NULL;
+ do {
+ switch(*s) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ if(strnum == NULL) {
+ strnum = s;
+ gotdash = nextdash;
+ nextdash = FALSE;
+ }
+ break;
+ case '-':
+ case ' ':
+ case 0:
+ if(strnum == NULL) break;
+ sscanf(strnum, "%f", &num);
+ strnum = NULL;
+ if(gotdash)
+ r[rangenum - 1].hi = num;
+ else {
+ r[rangenum].lo = num;
+ r[rangenum].hi = num;
+ rangenum++;
+ }
+ if(*s == '-') nextdash = (rangenum != 0);
+ else if(rangenum >= max) return rangenum;
+ break;
+ default :
+ return 0;
+ }
+ } while(*(s++) != 0);
+
+ return rangenum;
+}
+
+/* Copy and link two modes form merged-fb mode
+ * (Taken from mga, sis drivers)
+ * Copys mode i, links the result to dest, and returns it.
+ * Links i and j in Private record.
+ * If dest is NULL, return value is copy of i linked to itself.
+ * For mergedfb auto-config, we only check the dimension
+ * against virtualX/Y, if they were user-provided.
+ */
+static DisplayModePtr
+RADEONCopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest,
+ DisplayModePtr i, DisplayModePtr j,
+ RADEONScrn2Rel srel)
+{
+ DisplayModePtr mode;
+ int dx = 0,dy = 0;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if(!((mode = xalloc(sizeof(DisplayModeRec))))) return dest;
+ memcpy(mode, i, sizeof(DisplayModeRec));
+ if(!((mode->Private = xalloc(sizeof(RADEONMergedDisplayModeRec))))) {
+ xfree(mode);
+ return dest;
+ }
+ ((RADEONMergedDisplayModePtr)mode->Private)->CRT1 = i;
+ ((RADEONMergedDisplayModePtr)mode->Private)->CRT2 = j;
+ ((RADEONMergedDisplayModePtr)mode->Private)->CRT2Position = srel;
+ mode->PrivSize = 0;
+
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ if(!(pScrn->display->virtualX)) {
+ dx = i->HDisplay + j->HDisplay;
+ } else {
+ dx = min(pScrn->virtualX, i->HDisplay + j->HDisplay);
+ }
+ dx -= mode->HDisplay;
+ if(!(pScrn->display->virtualY)) {
+ dy = max(i->VDisplay, j->VDisplay);
+ } else {
+ dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay));
+ }
+ dy -= mode->VDisplay;
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ if(!(pScrn->display->virtualY)) {
+ dy = i->VDisplay + j->VDisplay;
+ } else {
+ dy = min(pScrn->virtualY, i->VDisplay + j->VDisplay);
+ }
+ dy -= mode->VDisplay;
+ if(!(pScrn->display->virtualX)) {
+ dx = max(i->HDisplay, j->HDisplay);
+ } else {
+ dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay));
+ }
+ dx -= mode->HDisplay;
+ break;
+ case radeonClone:
+ if(!(pScrn->display->virtualX)) {
+ dx = max(i->HDisplay, j->HDisplay);
+ } else {
+ dx = min(pScrn->virtualX, max(i->HDisplay, j->HDisplay));
+ }
+ dx -= mode->HDisplay;
+ if(!(pScrn->display->virtualY)) {
+ dy = max(i->VDisplay, j->VDisplay);
+ } else {
+ dy = min(pScrn->virtualY, max(i->VDisplay, j->VDisplay));
+ }
+ dy -= mode->VDisplay;
+ break;
+ }
+ mode->HDisplay += dx;
+ mode->HSyncStart += dx;
+ mode->HSyncEnd += dx;
+ mode->HTotal += dx;
+ mode->VDisplay += dy;
+ mode->VSyncStart += dy;
+ mode->VSyncEnd += dy;
+ mode->VTotal += dy;
+ mode->Clock = 0;
+
+ if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) >
+ (pScrn->videoRam * 1024)) ||
+ (mode->HDisplay > 8192) ||
+ (mode->VDisplay > 8192) ) {
+
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Skipped %dx%d, not enough video RAM or beyond hardware specs\n",
+ mode->HDisplay, mode->VDisplay);
+ xfree(mode->Private);
+ xfree(mode);
+
+ return dest;
+ }
+
+ if(srel != radeonClone) {
+ info->AtLeastOneNonClone = TRUE;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Merged %dx%d and %dx%d to %dx%d%s\n",
+ i->HDisplay, i->VDisplay, j->HDisplay, j->VDisplay,
+ mode->HDisplay, mode->VDisplay, (srel == radeonClone) ? " (Clone)" : "");
+
+ mode->next = mode;
+ mode->prev = mode;
+
+ if(dest) {
+ mode->next = dest->next; /* Insert node after "dest" */
+ dest->next->prev = mode;
+ mode->prev = dest;
+ dest->next = mode;
+ }
+
+ return mode;
+}
+
+/* Helper function to find a mode from a given name
+ * (Taken from mga driver)
+ */
+static DisplayModePtr
+RADEONGetModeFromName(char* str, DisplayModePtr i)
+{
+ DisplayModePtr c = i;
+ if(!i) return NULL;
+ do {
+ if(strcmp(str, c->name) == 0) return c;
+ c = c->next;
+ } while(c != i);
+ return NULL;
+}
+
+static DisplayModePtr
+RADEONFindWidestTallestMode(DisplayModePtr i, Bool tallest)
+{
+ DisplayModePtr c = i, d = NULL;
+ int max = 0;
+ if(!i) return NULL;
+ do {
+ if(tallest) {
+ if(c->VDisplay > max) {
+ max = c->VDisplay;
+ d = c;
+ }
+ } else {
+ if(c->HDisplay > max) {
+ max = c->HDisplay;
+ d = c;
+ }
+ }
+ c = c->next;
+ } while(c != i);
+ return d;
+}
+
+static DisplayModePtr
+RADEONGenerateModeListFromLargestModes(ScrnInfoPtr pScrn,
+ DisplayModePtr i, DisplayModePtr j,
+ RADEONScrn2Rel srel)
+{
+
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ DisplayModePtr mode1 = NULL;
+ DisplayModePtr mode2 = NULL;
+ DisplayModePtr result = NULL;
+ int p = 0;
+ int count = 0;
+
+ info->AtLeastOneNonClone = FALSE;
+
+
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ mode1 = RADEONFindWidestTallestMode(i, FALSE);
+ mode2 = RADEONFindWidestTallestMode(j, FALSE);
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ mode1 = RADEONFindWidestTallestMode(i, TRUE);
+ mode2 = RADEONFindWidestTallestMode(j, TRUE);
+ break;
+ case radeonClone:
+ mode1 = i;
+ mode2 = j;
+ while (pScrn->display->modes[count]) count++;
+ for (p = 0; p < count; p++) {
+ result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel);
+ mode1 = mode1->next;
+ mode2 = mode2->next;
+ }
+ }
+
+ if(mode1 && mode2) {
+ if (srel == radeonClone)
+ return result;
+ else
+ return(RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel));
+ } else {
+ return NULL;
+ }
+}
+
+/* Generate the merged-fb mode modelist
+ * (Taken from mga driver)
+ */
+static DisplayModePtr
+RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str,
+ DisplayModePtr i, DisplayModePtr j,
+ RADEONScrn2Rel srel)
+{
+ char* strmode = str;
+ char modename[256];
+ Bool gotdash = FALSE;
+ RADEONScrn2Rel sr;
+ DisplayModePtr mode1 = NULL;
+ DisplayModePtr mode2 = NULL;
+ DisplayModePtr result = NULL;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ info->AtLeastOneNonClone = FALSE;
+
+ do {
+ switch(*str) {
+ case 0:
+ case '-':
+ case ' ':
+ if((strmode != str)) {
+
+ strncpy(modename, strmode, str - strmode);
+ modename[str - strmode] = 0;
+
+ if(gotdash) {
+ if(mode1 == NULL) return NULL;
+ mode2 = RADEONGetModeFromName(modename, j);
+ if(!mode2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Mode \"%s\" is not a supported mode for CRT2\n", modename);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Skipping metamode \"%s-%s\".\n", mode1->name, modename);
+ mode1 = NULL;
+ }
+ } else {
+ mode1 = RADEONGetModeFromName(modename, i);
+ if(!mode1) {
+ char* tmps = str;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Mode \"%s\" is not a supported mode for CRT1\n", modename);
+ gotdash = FALSE;
+ while(*tmps == ' ') tmps++;
+ if(*tmps == '-') { /* skip the next mode */
+ tmps++;
+ while((*tmps == ' ') && (*tmps != 0)) tmps++; /* skip spaces */
+ while((*tmps != ' ') && (*tmps != '-') && (*tmps != 0)) tmps++; /* skip modename */
+ strncpy(modename,strmode,tmps - strmode);
+ modename[tmps - strmode] = 0;
+ str = tmps-1;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Skipping metamode \"%s\".\n", modename);
+ mode1 = NULL;
+ }
+ }
+ gotdash = FALSE;
+ }
+ strmode = str + 1;
+ gotdash |= (*str == '-');
+
+ if(*str != 0) break;
+ /* Fall through otherwise */
+
+ default:
+ if(!gotdash && mode1) {
+ sr = srel;
+ if(!mode2) {
+ mode2 = RADEONGetModeFromName(mode1->name, j);
+ sr = radeonClone;
+ }
+ if(!mode2) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Mode: \"%s\" is not a supported mode for CRT2\n", mode1->name);
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Skipping metamode \"%s\".\n", mode1->name);
+ mode1 = NULL;
+ } else {
+ result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, sr);
+ mode1 = NULL;
+ mode2 = NULL;
+ }
+ }
+ break;
+
+ }
+
+ } while(*(str++) != 0);
+
+ return result;
+}
+
+DisplayModePtr
+RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str,
+ DisplayModePtr i, DisplayModePtr j,
+ RADEONScrn2Rel srel)
+{
+ if(str != NULL) {
+ return(RADEONGenerateModeListFromMetaModes(pScrn, str, i, j, srel));
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "No MetaModes given, linking %s modes by default\n",
+ (srel == radeonClone) ? "first" : "largest");
+ return(RADEONGenerateModeListFromLargestModes(pScrn, i, j, srel));
+ }
+}
+
+void
+RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn)
+{
+ DisplayModePtr mode, bmode;
+ int max;
+ static const char *str = "MergedFB: Virtual %s %d\n";
+
+ if(!(pScrn->display->virtualX)) {
+ mode = bmode = pScrn->modes;
+ max = 0;
+ do {
+ if(mode->HDisplay > max) max = mode->HDisplay;
+ mode = mode->next;
+ } while(mode != bmode);
+ pScrn->virtualX = max;
+ pScrn->displayWidth = max;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", max);
+ }
+ if(!(pScrn->display->virtualY)) {
+ mode = bmode = pScrn->modes;
+ max = 0;
+ do {
+ if(mode->VDisplay > max) max = mode->VDisplay;
+ mode = mode->next;
+ } while(mode != bmode);
+ pScrn->virtualY = max;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", max);
+ }
+}
+
+/* Pseudo-Xinerama extension for MergedFB mode */
+void
+RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+ ScrnInfoPtr pScrn2 = NULL;
+ int crt1scrnnum = 0, crt2scrnnum = 1;
+ int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0;
+ DisplayModePtr currentMode, firstMode;
+ Bool infochanged = FALSE;
+
+ if(!info->MergedFB) return;
+
+ if(RADEONnoPanoramiXExtension) return;
+
+ if(!RADEONXineramadataPtr) return;
+
+ if(info->CRT2IsScrn0) {
+ crt1scrnnum = 1;
+ crt2scrnnum = 0;
+ }
+
+ pScrn2 = info->CRT2pScrn;
+
+ /* Attention: Usage of RandR may lead into virtual X and Y values
+ * actually smaller than our MetaModes! To avoid this, we calculate
+ * the maxCRT fields here (and not somewhere else, like in CopyNLink)
+ */
+
+ if((info->RADEONXineramaVX != pScrn1->virtualX) || (info->RADEONXineramaVY != pScrn1->virtualY)) {
+
+ if(!(pScrn1->modes)) {
+ xf86DrvMsg(pScrn1->scrnIndex, X_ERROR,
+ "Internal error: RADEONUpdateXineramaScreenInfo(): pScrn->modes is NULL\n");
+ return;
+ }
+
+ info->maxCRT1_X1 = info->maxCRT1_X2 = 0;
+ info->maxCRT1_Y1 = info->maxCRT1_Y2 = 0;
+ info->maxCRT2_X1 = info->maxCRT2_X2 = 0;
+ info->maxCRT2_Y1 = info->maxCRT2_Y2 = 0;
+ info->maxClone_X1 = info->maxClone_X2 = 0;
+ info->maxClone_Y1 = info->maxClone_Y2 = 0;
+
+ currentMode = firstMode = pScrn1->modes;
+
+ do {
+
+ DisplayModePtr p = currentMode->next;
+ DisplayModePtr i = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT1;
+ DisplayModePtr j = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT2;
+ RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT2Position;
+
+ if((i->HDisplay <= pScrn1->virtualX) && (j->HDisplay <= pScrn1->virtualX) &&
+ (i->VDisplay <= pScrn1->virtualY) && (j->VDisplay <= pScrn1->virtualY)) {
+
+ if(srel != radeonClone) {
+ if(info->maxCRT1_X1 <= i->HDisplay) {
+ info->maxCRT1_X1 = i->HDisplay; /* Largest CRT1 mode */
+ if(info->maxCRT1_X2 < j->HDisplay) {
+ info->maxCRT1_X2 = j->HDisplay; /* Largest X of CRT2 mode displayed with largest CRT1 mode */
+ }
+ }
+ if(info->maxCRT2_X2 <= j->HDisplay) {
+ info->maxCRT2_X2 = j->HDisplay; /* Largest CRT2 mode */
+ if(info->maxCRT2_X1 < i->HDisplay) {
+ info->maxCRT2_X1 = i->HDisplay; /* Largest X of CRT1 mode displayed with largest CRT2 mode */
+ }
+ }
+ if(info->maxCRT1_Y1 <= i->VDisplay) {
+ info->maxCRT1_Y1 = i->VDisplay;
+ if(info->maxCRT1_Y2 < j->VDisplay) {
+ info->maxCRT1_Y2 = j->VDisplay;
+ }
+ }
+ if(info->maxCRT2_Y2 <= j->VDisplay) {
+ info->maxCRT2_Y2 = j->VDisplay;
+ if(info->maxCRT2_Y1 < i->VDisplay) {
+ info->maxCRT2_Y1 = i->VDisplay;
+ }
+ }
+ } else {
+ if(info->maxClone_X1 < i->HDisplay) {
+ info->maxClone_X1 = i->HDisplay;
+ }
+ if(info->maxClone_X2 < j->HDisplay) {
+ info->maxClone_X2 = j->HDisplay;
+ }
+ if(info->maxClone_Y1 < i->VDisplay) {
+ info->maxClone_Y1 = i->VDisplay;
+ }
+ if(info->maxClone_Y2 < j->VDisplay) {
+ info->maxClone_Y2 = j->VDisplay;
+ }
+ }
+ }
+ currentMode = p;
+
+ } while((currentMode) && (currentMode != firstMode));
+
+ info->RADEONXineramaVX = pScrn1->virtualX;
+ info->RADEONXineramaVY = pScrn1->virtualY;
+ infochanged = TRUE;
+
+ }
+
+ /* leftof
+
+ V 1:
+ CRT2: x = 0
+ y = 0
+ w = (maxCRT2 X)
+ h = (virtual Y)
+ CRT1: x = (virtual X) - (maxCRT1 X)
+ y = 0
+ w = (maxCRT1 X)
+ h = (virtual Y)
+
+ V 2:
+ CRT2: x = 0
+ y = 0
+ w = max CRT2 mode X
+ h = virtual Y size
+ CRT1: x = (max) CRT2 mode X von dem Metamode, wo CRT1 mode maximal breit ist
+ y = 0
+ w = max CRT1 mode X
+ h = virtual Y size
+
+ V 3: (current)
+ CRT1: x = (maxCRT2 X von dem MMode, wo maxCRT1 X)
+ y = 0
+ w = (virtual X) - x
+ h = (virtual Y)
+ CRT2: x = 0
+ y = 0
+ w = (virtual X) - (maxCRT1 X von dem MMode, wo maxCRT2 X)
+ h = (virtual Y)
+
+ */
+ switch(info->CRT2Position) {
+ case radeonLeftOf: /* V 1 */
+ x1 = min(info->maxCRT1_X2, pScrn1->virtualX - info->maxCRT1_X1); /* pScrn1->virtualX - pSiS->maxCRT1_X1;
+*/
+ if(x1 < 0) x1 = 0;
+ y1 = 0; /* 0; */
+ w1 = pScrn1->virtualX - x1; /* pSiS->maxCRT1_X1; */
+ h1 = pScrn1->virtualY; /* pScrn1->virtualY; */
+ x2 = 0; /* 0; */
+ y2 = 0; /* 0; */
+ w2 = max(info->maxCRT2_X2, pScrn1->virtualX - info->maxCRT2_X1); /* pSiS->maxCRT2_X2; */
+ if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX;
+ h2 = pScrn1->virtualY; /* pScrn1->virtualY; */
+ break;
+ case radeonRightOf:
+ x1 = 0; /* 0; */
+ y1 = 0; /* 0; */
+ w1 = max(info->maxCRT1_X1, pScrn1->virtualX - info->maxCRT1_X2); /* pSiS->maxCRT1_X1; */
+ if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX;
+ h1 = pScrn1->virtualY; /* pScrn1->virtualY; */
+ x2 = min(info->maxCRT2_X1, pScrn1->virtualX - info->maxCRT2_X2); /* pScrn1->virtualX - pSiS->maxCRT2_X2;
+*/
+ if(x2 < 0) x2 = 0;
+ y2 = 0; /* 0; */
+ w2 = pScrn1->virtualX - x2; /* pSiS->maxCRT2_X2; */
+ h2 = pScrn1->virtualY; /* pScrn1->virtualY; */
+ break;
+ case radeonAbove:
+ x1 = 0; /* 0; */
+ y1 = min(info->maxCRT1_Y2, pScrn1->virtualY - info->maxCRT1_Y1); /* pScrn1->virtualY - pSiS->maxCRT1_Y1;
+*/
+ if(y1 < 0) y1 = 0;
+ w1 = pScrn1->virtualX; /* pScrn1->virtualX; */
+ h1 = pScrn1->virtualY - y1; /* pSiS->maxCRT1_Y1; */
+ x2 = 0; /* 0; */
+ y2 = 0; /* 0; */
+ w2 = pScrn1->virtualX; /* pScrn1->virtualX; */
+ h2 = max(info->maxCRT2_Y2, pScrn1->virtualY - info->maxCRT2_Y1); /* pSiS->maxCRT2_Y2; */
+ if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY;
+ break;
+ case radeonBelow:
+ x1 = 0; /* 0; */
+ y1 = 0; /* 0; */
+ w1 = pScrn1->virtualX; /* pScrn1->virtualX; */
+ h1 = max(info->maxCRT1_Y1, pScrn1->virtualY - info->maxCRT1_Y2); /* pSiS->maxCRT1_Y1; */
+ if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY;
+ x2 = 0; /* 0; */
+ y2 = min(info->maxCRT2_Y1, pScrn1->virtualY - info->maxCRT2_Y2); /* pScrn1->virtualY - pSiS->maxCRT2_Y2;
+*/
+ if(y2 < 0) y2 = 0;
+ w2 = pScrn1->virtualX; /* pScrn1->virtualX; */
+ h2 = pScrn1->virtualY - y2; /* pSiS->maxCRT2_Y2; */
+ break;
+ default:
+ xf86DrvMsg(pScrn1->scrnIndex, X_ERROR,
+ "Internal error: UpdateXineramaInfo(): unsupported CRT2Position (%d)\n",
+ info->CRT2Position);
+ }
+ RADEONXineramadataPtr[crt1scrnnum].x = x1;
+ RADEONXineramadataPtr[crt1scrnnum].y = y1;
+ RADEONXineramadataPtr[crt1scrnnum].width = w1;
+ RADEONXineramadataPtr[crt1scrnnum].height = h1;
+ RADEONXineramadataPtr[crt2scrnnum].x = x2;
+ RADEONXineramadataPtr[crt2scrnnum].y = y2;
+ RADEONXineramadataPtr[crt2scrnnum].width = w2;
+ RADEONXineramadataPtr[crt2scrnnum].height = h2;
+
+ if(infochanged) {
+ xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
+ "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n",
+ crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1);
+ xf86DrvMsg(pScrn1->scrnIndex, X_INFO,
+ "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n",
+ crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1);
+ }
+
+}
+
+/* Proc */
+
+int
+RADEONProcXineramaQueryVersion(ClientPtr client)
+{
+ xPanoramiXQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = RADEON_XINERAMA_MAJOR_VERSION;
+ rep.minorVersion = RADEON_XINERAMA_MINOR_VERSION;
+ if(client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+int
+RADEONProcXineramaGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ WindowPtr pWin;
+ xPanoramiXGetStateReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ pWin = LookupWindow(stuff->window, client);
+ if(!pWin) return BadWindow;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !RADEONnoPanoramiXExtension;
+ if(client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.state, n);
+ }
+ WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *)&rep);
+ return client->noClientException;
+}
+
+int
+RADEONProcXineramaGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ pWin = LookupWindow(stuff->window, client);
+ if(!pWin) return BadWindow;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.ScreenCount = RADEONXineramaNumScreens;
+ if(client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.ScreenCount, n);
+ }
+ WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *)&rep);
+ return client->noClientException;
+}
+
+int
+RADEONProcXineramaGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ pWin = LookupWindow (stuff->window, client);
+ if(!pWin) return BadWindow;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.width = RADEONXineramadataPtr[stuff->screen].width;
+ rep.height = RADEONXineramadataPtr[stuff->screen].height;
+ if(client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.width, n);
+ swaps(&rep.height, n);
+ }
+ WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), (char *)&rep);
+ return client->noClientException;
+}
+
+int
+RADEONProcXineramaIsActive(ClientPtr client)
+{
+ xXineramaIsActiveReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !RADEONnoPanoramiXExtension;
+ if(client->swapped) {
+ register int n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.state, n);
+ }
+ WriteToClient(client, sizeof(xXineramaIsActiveReply), (char *) &rep);
+ return client->noClientException;
+}
+
+int
+RADEONProcXineramaQueryScreens(ClientPtr client)
+{
+ xXineramaQueryScreensReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.number = (RADEONnoPanoramiXExtension) ? 0 : RADEONXineramaNumScreens;
+ rep.length = rep.number * sz_XineramaScreenInfo >> 2;
+ if(client->swapped) {
+ register int n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.number, n);
+ }
+ WriteToClient(client, sizeof(xXineramaQueryScreensReply), (char *)&rep);
+
+ if(!RADEONnoPanoramiXExtension) {
+ xXineramaScreenInfo scratch;
+ int i;
+
+ for(i = 0; i < RADEONXineramaNumScreens; i++) {
+ scratch.x_org = RADEONXineramadataPtr[i].x;
+ scratch.y_org = RADEONXineramadataPtr[i].y;
+ scratch.width = RADEONXineramadataPtr[i].width;
+ scratch.height = RADEONXineramadataPtr[i].height;
+ if(client->swapped) {
+ register int n;
+ swaps(&scratch.x_org, n);
+ swaps(&scratch.y_org, n);
+ swaps(&scratch.width, n);
+ swaps(&scratch.height, n);
+ }
+ WriteToClient(client, sz_XineramaScreenInfo, (char *)&scratch);
+ }
+ }
+
+ return client->noClientException;
+}
+
+static int
+RADEONProcXineramaDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return RADEONProcXineramaQueryVersion(client);
+ case X_PanoramiXGetState:
+ return RADEONProcXineramaGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return RADEONProcXineramaGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return RADEONProcXineramaGetScreenSize(client);
+ case X_XineramaIsActive:
+ return RADEONProcXineramaIsActive(client);
+ case X_XineramaQueryScreens:
+ return RADEONProcXineramaQueryScreens(client);
+ }
+ return BadRequest;
+}
+
+/* SProc */
+
+static int
+RADEONSProcXineramaQueryVersion (ClientPtr client)
+{
+ REQUEST(xPanoramiXQueryVersionReq);
+ register int n;
+ swaps(&stuff->length,n);
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ return RADEONProcXineramaQueryVersion(client);
+}
+
+static int
+RADEONSProcXineramaGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ register int n;
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ return RADEONProcXineramaGetState(client);
+}
+
+static int
+RADEONSProcXineramaGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ register int n;
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ return RADEONProcXineramaGetScreenCount(client);
+}
+
+static int
+RADEONSProcXineramaGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ register int n;
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ return RADEONProcXineramaGetScreenSize(client);
+}
+
+static int
+RADEONSProcXineramaIsActive(ClientPtr client)
+{
+ REQUEST(xXineramaIsActiveReq);
+ register int n;
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+ return RADEONProcXineramaIsActive(client);
+}
+
+static int
+RADEONSProcXineramaQueryScreens(ClientPtr client)
+{
+ REQUEST(xXineramaQueryScreensReq);
+ register int n;
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+ return RADEONProcXineramaQueryScreens(client);
+}
+
+int
+RADEONSProcXineramaDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_PanoramiXQueryVersion:
+ return RADEONSProcXineramaQueryVersion(client);
+ case X_PanoramiXGetState:
+ return RADEONSProcXineramaGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return RADEONSProcXineramaGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return RADEONSProcXineramaGetScreenSize(client);
+ case X_XineramaIsActive:
+ return RADEONSProcXineramaIsActive(client);
+ case X_XineramaQueryScreens:
+ return RADEONSProcXineramaQueryScreens(client);
+ }
+ return BadRequest;
+}
+
+static void
+RADEONXineramaResetProc(ExtensionEntry* extEntry)
+{
+ if(RADEONXineramadataPtr) {
+ Xfree(RADEONXineramadataPtr);
+ RADEONXineramadataPtr = NULL;
+ }
+}
+
+void
+RADEONXineramaExtensionInit(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ Bool success = FALSE;
+
+ if(!(RADEONXineramadataPtr)) {
+
+ if(!info->MergedFB) {
+ RADEONnoPanoramiXExtension = TRUE;
+ return;
+ }
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Xinerama active, not initializing Radeon Pseudo-Xinerama\n");
+ RADEONnoPanoramiXExtension = TRUE;
+ return;
+ }
+#endif
+
+ if(RADEONnoPanoramiXExtension) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Radeon Pseudo-Xinerama disabled\n");
+ return;
+ }
+
+ if(info->CRT2Position == radeonClone) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Running MergedFB in Clone mode, Radeon Pseudo-Xinerama disabled\n");
+ RADEONnoPanoramiXExtension = TRUE;
+ return;
+ }
+
+ if(!(info->AtLeastOneNonClone)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Only Clone modes defined, Radeon Pseudo-Xinerama disabled\n");
+ RADEONnoPanoramiXExtension = TRUE;
+ return;
+ }
+
+ RADEONXineramaNumScreens = 2;
+
+ while(RADEONXineramaGeneration != serverGeneration) {
+
+ info->XineramaExtEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
+ RADEONProcXineramaDispatch,
+ RADEONSProcXineramaDispatch,
+ RADEONXineramaResetProc,
+ StandardMinorOpcode);
+
+ if(!info->XineramaExtEntry) break;
+
+ RADEONXineramaReqCode = (unsigned char)info->XineramaExtEntry->base;
+
+ if(!(RADEONXineramadataPtr = (RADEONXineramaData *)
+ xcalloc(RADEONXineramaNumScreens, sizeof(RADEONXineramaData)))) break;
+
+ RADEONXineramaGeneration = serverGeneration;
+ success = TRUE;
+ }
+
+ if(!success) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Failed to initialize Radeon Pseudo-Xinerama extension\n");
+ RADEONnoPanoramiXExtension = TRUE;
+ return;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Initialized Radeon Pseudo-Xinerama extension\n");
+
+ info->RADEONXineramaVX = 0;
+ info->RADEONXineramaVY = 0;
+
+ }
+
+ RADEONUpdateXineramaScreenInfo(pScrn);
+
+}
+/* End of PseudoXinerama */
+
+static Bool
+InRegion(int x, int y, region r)
+{
+ return (r.x0 <= x) && (x <= r.x1) && (r.y0 <= y) && (y <= r.y1);
+}
+
+void
+RADEONMergePointerMoved(int scrnIndex, int x, int y)
+{
+ ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+ ScrnInfoPtr pScrn2 = info->CRT2pScrn;
+ region out, in1, in2, f2, f1;
+ int deltax, deltay;
+
+ f1.x0 = info->CRT1frameX0;
+ f1.x1 = info->CRT1frameX1;
+ f1.y0 = info->CRT1frameY0;
+ f1.y1 = info->CRT1frameY1;
+ f2.x0 = pScrn2->frameX0;
+ f2.x1 = pScrn2->frameX1;
+ f2.y0 = pScrn2->frameY0;
+ f2.y1 = pScrn2->frameY1;
+
+ /* Define the outer region. Crossing this causes all frames to move */
+ out.x0 = pScrn1->frameX0;
+ out.x1 = pScrn1->frameX1;
+ out.y0 = pScrn1->frameY0;
+ out.y1 = pScrn1->frameY1;
+
+ /*
+ * Define the inner sliding window. Being outsize both frames but
+ * inside the outer clipping window will slide corresponding frame
+ */
+ in1 = out;
+ in2 = out;
+ switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) {
+ case radeonLeftOf:
+ in1.x0 = f1.x0;
+ in2.x1 = f2.x1;
+ break;
+ case radeonRightOf:
+ in1.x1 = f1.x1;
+ in2.x0 = f2.x0;
+ break;
+ case radeonBelow:
+ in1.y1 = f1.y1;
+ in2.y0 = f2.y0;
+ break;
+ case radeonAbove:
+ in1.y0 = f1.y0;
+ in2.y1 = f2.y1;
+ break;
+ case radeonClone:
+ break;
+ }
+
+ deltay = 0;
+ deltax = 0;
+
+ if(InRegion(x, y, out)) { /* inside outer region */
+
+ /* xf86DrvMsg(0, X_INFO, "1: %d %d | %d %d %d %d | %d %d %d %d\n",
+ x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */
+
+ if(InRegion(x, y, in1) && !InRegion(x, y, f1)) {
+ REBOUND(f1.x0, f1.x1, x);
+ REBOUND(f1.y0, f1.y1, y);
+ deltax = 1;
+ /* xf86DrvMsg(0, X_INFO, "2: %d %d | %d %d %d %d | %d %d %d %d\n",
+ x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1); */
+ }
+ if(InRegion(x, y, in2) && !InRegion(x, y, f2)) {
+ REBOUND(f2.x0, f2.x1, x);
+ REBOUND(f2.y0, f2.y1, y);
+ deltax = 1;
+ }
+
+ } else { /* outside outer region */
+
+ /* xf86DrvMsg(0, X_INFO, "3: %d %d | %d %d %d %d | %d %d %d %d\n",
+ x, y, in1.x0, in1.x1, in1.y0, in1.y1, f1.x0, f1.x1, f1.y0, f1.y1);
+ xf86DrvMsg(0, X_INFO, "3-out: %d %d %d %d\n",
+ out.x0, out.x1, out.y0, out.y1); */
+
+ if(out.x0 > x) {
+ deltax = x - out.x0;
+ }
+ if(out.x1 < x) {
+ deltax = x - out.x1;
+ }
+ if(deltax) {
+ pScrn1->frameX0 += deltax;
+ pScrn1->frameX1 += deltax;
+ f1.x0 += deltax;
+ f1.x1 += deltax;
+ f2.x0 += deltax;
+ f2.x1 += deltax;
+ }
+
+ if(out.y0 > y) {
+ deltay = y - out.y0;
+ }
+ if(out.y1 < y) {
+ deltay = y - out.y1;
+ }
+ if(deltay) {
+ pScrn1->frameY0 += deltay;
+ pScrn1->frameY1 += deltay;
+ f1.y0 += deltay;
+ f1.y1 += deltay;
+ f2.y0 += deltay;
+ f2.y1 += deltay;
+ }
+
+ switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) {
+ case radeonLeftOf:
+ if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); }
+ if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); }
+ break;
+ case radeonRightOf:
+ if(x <= f1.x1) { REBOUND(f1.y0, f1.y1, y); }
+ if(x >= f2.x0) { REBOUND(f2.y0, f2.y1, y); }
+ break;
+ case radeonBelow:
+ if(y <= f1.y1) { REBOUND(f1.x0, f1.x1, x); }
+ if(y >= f2.y0) { REBOUND(f2.x0, f2.x1, x); }
+ break;
+ case radeonAbove:
+ if(y >= f1.y0) { REBOUND(f1.x0, f1.x1, x); }
+ if(y <= f2.y1) { REBOUND(f2.x0, f2.x1, x); }
+ break;
+ case radeonClone:
+ break;
+ }
+
+ }
+
+ if(deltax || deltay) {
+ info->CRT1frameX0 = f1.x0;
+ info->CRT1frameY0 = f1.y0;
+ pScrn2->frameX0 = f2.x0;
+ pScrn2->frameY0 = f2.y0;
+
+ info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1;
+ info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1;
+ pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1;
+ pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1;
+ pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1;
+ pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1;
+
+ RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE);
+ RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE);
+ }
+}
+
+static void
+RADEONAdjustFrameMergedHelper(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+ ScrnInfoPtr pScrn2 = info->CRT2pScrn;
+ int VTotal = info->CurrentLayout.mode->VDisplay;
+ int HTotal = info->CurrentLayout.mode->HDisplay;
+ int VMax = VTotal;
+ int HMax = HTotal;
+
+ BOUND(x, 0, pScrn1->virtualX - HTotal);
+ BOUND(y, 0, pScrn1->virtualY - VTotal);
+
+ switch(SDMPTR(pScrn1)->CRT2Position) {
+ case radeonLeftOf:
+ pScrn2->frameX0 = x;
+ BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay);
+ info->CRT1frameX0 = x + CDMPTR->CRT2->HDisplay;
+ BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay);
+ break;
+ case radeonRightOf:
+ info->CRT1frameX0 = x;
+ BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay);
+ pScrn2->frameX0 = x + CDMPTR->CRT1->HDisplay;
+ BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay);
+ break;
+ case radeonAbove:
+ BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay);
+ pScrn2->frameY0 = y;
+ BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay);
+ info->CRT1frameY0 = y + CDMPTR->CRT2->VDisplay;
+ break;
+ case radeonBelow:
+ BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay);
+ info->CRT1frameY0 = y;
+ BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay);
+ pScrn2->frameY0 = y + CDMPTR->CRT1->VDisplay;
+ break;
+ case radeonClone:
+ BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay);
+ BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay);
+ BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay);
+ BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay);
+ break;
+ }
+
+ BOUND(info->CRT1frameX0, 0, pScrn1->virtualX - CDMPTR->CRT1->HDisplay);
+ BOUND(info->CRT1frameY0, 0, pScrn1->virtualY - CDMPTR->CRT1->VDisplay);
+ BOUND(pScrn2->frameX0, 0, pScrn1->virtualX - CDMPTR->CRT2->HDisplay);
+ BOUND(pScrn2->frameY0, 0, pScrn1->virtualY - CDMPTR->CRT2->VDisplay);
+
+ pScrn1->frameX0 = x;
+ pScrn1->frameY0 = y;
+
+ info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1;
+ info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1;
+ pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1;
+ pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1;
+ pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1;
+ pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1;
+/*
+ RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE);
+ RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE);
+*/
+}
+
+void
+RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+ ScrnInfoPtr pScrn2 = info->CRT2pScrn;
+
+ RADEONAdjustFrameMergedHelper(scrnIndex, x, y, flags);
+ RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE);
+ RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE);
+}
+
+void
+RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+ MessageType from = X_DEFAULT;
+ xf86MonPtr DDC1 = (xf86MonPtr)(pScrn1->monitor->DDC);
+ xf86MonPtr DDC2 = (xf86MonPtr)(pScrn2->monitor->DDC);
+ int ddcWidthmm = 0, ddcHeightmm = 0;
+ const char *dsstr = "MergedFB: Display dimensions: (%d, %d) mm\n";
+
+ /* This sets the DPI for MergedFB mode. The problem is that
+ * this can never be exact, because the output devices may
+ * have different dimensions. This function tries to compromise
+ * through a few assumptions, and it just calculates an average DPI
+ * value for both monitors.
+ */
+
+ /* Given DisplaySize should regard BOTH monitors */
+ pScrn1->widthmm = pScrn1->monitor->widthmm;
+ pScrn1->heightmm = pScrn1->monitor->heightmm;
+
+ /* Get DDC display size; if only either CRT1 or CRT2 provided these,
+ * assume equal dimensions for both, otherwise add dimensions
+ */
+ if( (DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) &&
+ (DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0)) ) {
+ ddcWidthmm = max(DDC1->features.hsize, DDC2->features.hsize) * 10;
+ ddcHeightmm = max(DDC1->features.vsize, DDC2->features.vsize) * 10;
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ ddcWidthmm = (DDC1->features.hsize + DDC2->features.hsize) * 10;
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ ddcHeightmm = (DDC1->features.vsize + DDC2->features.vsize) * 10;
+ default:
+ break;
+ }
+
+ } else if(DDC1 && (DDC1->features.hsize > 0 && DDC1->features.vsize > 0)) {
+ ddcWidthmm = DDC1->features.hsize * 10;
+ ddcHeightmm = DDC1->features.vsize * 10;
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ ddcWidthmm *= 2;
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ ddcHeightmm *= 2;
+ default:
+ break;
+ }
+ } else if(DDC2 && (DDC2->features.hsize > 0 && DDC2->features.vsize > 0) ) {
+ ddcWidthmm = DDC2->features.hsize * 10;
+ ddcHeightmm = DDC2->features.vsize * 10;
+ switch(srel) {
+ case radeonLeftOf:
+ case radeonRightOf:
+ ddcWidthmm *= 2;
+ break;
+ case radeonAbove:
+ case radeonBelow:
+ ddcHeightmm *= 2;
+ default:
+ break;
+ }
+ }
+
+ if(monitorResolution > 0) {
+
+ /* Set command line given values (overrules given options) */
+ pScrn1->xDpi = monitorResolution;
+ pScrn1->yDpi = monitorResolution;
+ from = X_CMDLINE;
+
+ } else if(info->MergedFBXDPI) {
+
+ /* Set option-wise given values (overrule DisplaySize) */
+ pScrn1->xDpi = info->MergedFBXDPI;
+ pScrn1->yDpi = info->MergedFBYDPI;
+ from = X_CONFIG;
+
+ } else if(pScrn1->widthmm > 0 || pScrn1->heightmm > 0) {
+
+ /* Set values calculated from given DisplaySize */
+ from = X_CONFIG;
+ if(pScrn1->widthmm > 0) {
+ pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
+ }
+ if(pScrn1->heightmm > 0) {
+ pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
+ }
+ xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm);
+
+ } else if(ddcWidthmm && ddcHeightmm) {
+
+ /* Set values from DDC-provided display size */
+ from = X_PROBED;
+ xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, ddcWidthmm, ddcHeightmm );
+ pScrn1->widthmm = ddcWidthmm;
+ pScrn1->heightmm = ddcHeightmm;
+ if(pScrn1->widthmm > 0) {
+ pScrn1->xDpi = (int)((double)pScrn1->virtualX * 25.4 / pScrn1->widthmm);
+ }
+ if(pScrn1->heightmm > 0) {
+ pScrn1->yDpi = (int)((double)pScrn1->virtualY * 25.4 / pScrn1->heightmm);
+ }
+
+ } else {
+
+ pScrn1->xDpi = pScrn1->yDpi = DEFAULT_DPI;
+
+ }
+
+ /* Sanity check */
+ if(pScrn1->xDpi > 0 && pScrn1->yDpi <= 0)
+ pScrn1->yDpi = pScrn1->xDpi;
+ if(pScrn1->yDpi > 0 && pScrn1->xDpi <= 0)
+ pScrn1->xDpi = pScrn1->yDpi;
+
+ pScrn2->xDpi = pScrn1->xDpi;
+ pScrn2->yDpi = pScrn1->yDpi;
+
+ xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n",
+ pScrn1->xDpi, pScrn1->yDpi);
+}
+
+/* radeon cursor helpers */
+static void
+RADEONChooseCursorCRTC(ScrnInfoPtr pScrn1, int x, int y)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn1);
+ unsigned char *RADEONMMIO = info->MMIO;
+ RADEONScrn2Rel srel =
+ ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position;
+ ScrnInfoPtr pScrn2 = info->CRT2pScrn;
+
+ if (srel == radeonClone) {
+ /* show cursor 2 */
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN,
+ ~RADEON_CRTC2_CUR_EN);
+ /* show cursor 1 */
+ OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN,
+ ~RADEON_CRTC_CUR_EN);
+ }
+ else {
+ if (((x >= pScrn1->frameX0) && (x <= pScrn1->frameX1)) &&
+ ((y >= pScrn1->frameY0) && (y <= pScrn1->frameY1))) {
+ /* hide cursor 2 */
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN);
+ /* show cursor 1 */
+ OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN,
+ ~RADEON_CRTC_CUR_EN);
+ }
+ if (((x >= pScrn2->frameX0) && (x <= pScrn2->frameX1)) &&
+ ((y >= pScrn2->frameY0) && (y <= pScrn2->frameY1))) {
+ /* hide cursor 1 */
+ OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN);
+ /* show cursor 2 */
+ OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN,
+ ~RADEON_CRTC2_CUR_EN);
+ }
+ }
+}
+
+void
+RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ xf86CursorInfoPtr cursor = info->cursor;
+ int xorigin = 0;
+ int yorigin = 0;
+ int stride = 256;
+ ScrnInfoPtr pScrn2 = info->CRT2pScrn;
+ DisplayModePtr mode1 = CDMPTR->CRT1;
+ DisplayModePtr mode2 = CDMPTR->CRT2;
+ int x1, y1, x2, y2;
+ int total_y1 = pScrn->frameY1 - pScrn->frameY0;
+ int total_y2 = pScrn2->frameY1 - pScrn2->frameY0;
+
+ if (x < 0) xorigin = -x+1;
+ if (y < 0) yorigin = -y+1;
+ /* if (y > total_y) y = total_y; */
+ if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1;
+ if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
+
+ x += pScrn->frameX0;
+ y += pScrn->frameY0;
+
+ x1 = x - info->CRT1frameX0;
+ y1 = y - info->CRT1frameY0;
+
+ x2 = x - pScrn2->frameX0;
+ y2 = y - pScrn2->frameY0;
+
+ if (y1 > total_y1)
+ y1 = total_y1;
+ if (y2 > total_y2)
+ y2 = total_y2;
+
+ if(mode1->Flags & V_INTERLACE)
+ y1 /= 2;
+ else if(mode1->Flags & V_DBLSCAN)
+ y1 *= 2;
+
+ if(mode2->Flags & V_INTERLACE)
+ y2 /= 2;
+ else if(mode2->Flags & V_DBLSCAN)
+ y2 *= 2;
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+
+ RADEONChooseCursorCRTC(pScrn, x, y);
+
+ /* cursor1 */
+ OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK
+ | (xorigin << 16)
+ | yorigin));
+ OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK
+ | ((xorigin ? 0 : x1) << 16)
+ | (yorigin ? 0 : y1)));
+ OUTREG(RADEON_CUR_OFFSET, info->cursor_start + yorigin * stride);
+ /* cursor2 */
+ 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 + yorigin * stride);
+
+}
+
+/* radeon Xv helpers */
+
+/* choose the crtc for the overlay for mergedfb based on the location
+ of the output window and the orientation of the crtcs */
+
+void
+RADEONChooseOverlayCRTC(
+ ScrnInfoPtr pScrn,
+ BoxPtr dstBox
+) {
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONScrn2Rel srel =
+ ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position;
+
+ if (srel == radeonLeftOf) {
+ if (dstBox->x1 >= info->CRT2pScrn->frameX1)
+ info->OverlayOnCRTC2 = FALSE;
+ else
+ info->OverlayOnCRTC2 = TRUE;
+ }
+ if (srel == radeonRightOf) {
+ if (dstBox->x2 <= info->CRT2pScrn->frameX0)
+ info->OverlayOnCRTC2 = FALSE;
+ else
+ info->OverlayOnCRTC2 = TRUE;
+ }
+ if (srel == radeonAbove) {
+ if (dstBox->y1 >= info->CRT2pScrn->frameY1)
+ info->OverlayOnCRTC2 = FALSE;
+ else
+ info->OverlayOnCRTC2 = TRUE;
+ }
+ if (srel == radeonBelow) {
+ if (dstBox->y2 <= info->CRT2pScrn->frameY0)
+ info->OverlayOnCRTC2 = FALSE;
+ else
+ info->OverlayOnCRTC2 = TRUE;
+ }
+}
diff --git a/src/radeon_mergedfb.h b/src/radeon_mergedfb.h
new file mode 100644
index 00000000..e51ce5c4
--- /dev/null
+++ b/src/radeon_mergedfb.h
@@ -0,0 +1,124 @@
+/* $XFree86$ */
+/*
+ * Copyright 2003 Alex Deucher.
+ *
+ * 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 on 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 ALEX DEUCHER, OR ANY OTHER
+ * CONTRIBUTORS 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.
+ */
+
+/*
+ * Authors:
+ * Alex Deucher <agd5f@yahoo.com>
+ *
+ */
+
+#ifndef _RADEON_MERGEDFB_H_
+#define _RADEON_MERGEDFB_H_
+
+#include "xf86.h"
+
+#include "radeon.h"
+
+#if 0
+ /* 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
+
+/* needed for pseudo-xinerama by radeon_driver.c */
+Bool RADEONnoPanoramiXExtension = TRUE;
+
+/* Relative merge position */
+typedef enum {
+ radeonLeftOf,
+ radeonRightOf,
+ radeonAbove,
+ radeonBelow,
+ radeonClone
+} RADEONScrn2Rel;
+#endif
+
+#define SDMPTR(x) ((RADEONMergedDisplayModePtr)(x->currentMode->Private))
+#define CDMPTR ((RADEONMergedDisplayModePtr)(info->CurrentLayout.mode->Private))
+
+#define BOUND(test,low,hi) { \
+ if(test < low) test = low; \
+ if(test > hi) test = hi; }
+
+#define REBOUND(low,hi,test) { \
+ if(test < low) { \
+ hi += test-low; \
+ low = test; } \
+ if(test > hi) { \
+ low += test-hi; \
+ hi = test; } }
+
+typedef struct _MergedDisplayModeRec {
+ DisplayModePtr CRT1;
+ DisplayModePtr CRT2;
+ RADEONScrn2Rel CRT2Position;
+} RADEONMergedDisplayModeRec, *RADEONMergedDisplayModePtr;
+
+typedef struct _region {
+ int x0,x1,y0,y1;
+} region;
+
+typedef struct _RADEONXineramaData {
+ int x;
+ int y;
+ int width;
+ int height;
+} RADEONXineramaData;
+
+/* needed by radeon_driver.c */
+extern void
+RADEONAdjustFrameMerged(int scrnIndex, int x, int y, int flags);
+extern void
+RADEONMergePointerMoved(int scrnIndex, int x, int y);
+extern DisplayModePtr
+RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str,
+ DisplayModePtr i, DisplayModePtr j,
+ RADEONScrn2Rel srel);
+extern int
+RADEONStrToRanges(range *r, char *s, int max);
+extern void
+RADEONXineramaExtensionInit(ScrnInfoPtr pScrn);
+extern void
+RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1);
+extern void
+RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel);
+extern void
+RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn);
+
+/* needed by radeon_cursor.c */
+extern void
+RADEONSetCursorPositionMerged(ScrnInfoPtr pScrn, int x, int y);
+
+/* needed by radeon_video.c */
+extern void
+RADEONChooseOverlayCRTC(ScrnInfoPtr, BoxPtr);
+
+#endif /* _RADEON_MERGEDFB_H_ */
diff --git a/src/radeon_misc.c b/src/radeon_misc.c
index 6d6b17d6..c7671b7b 100644
--- a/src/radeon_misc.c
+++ b/src/radeon_misc.c
@@ -38,7 +38,7 @@ static XF86ModuleVersionInfo RADEONVersionRec =
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
- XF86_VERSION_CURRENT,
+ XORG_VERSION_CURRENT,
RADEON_VERSION_MAJOR, RADEON_VERSION_MINOR, RADEON_VERSION_PATCH,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
diff --git a/src/radeon_probe.c b/src/radeon_probe.c
index a8edceb8..49352ea9 100644
--- a/src/radeon_probe.c
+++ b/src/radeon_probe.c
@@ -49,106 +49,7 @@
#include "xf86misc.h"
#include "xf86Resources.h"
-#ifdef XFree86LOADER
-
-/*
- * The following exists to prevent the compiler from considering entry points
- * defined in a separate module from being constants.
- */
-static xf86PreInitProc *const volatile PreInitProc = RADEONPreInit;
-static xf86ScreenInitProc *const volatile ScreenInitProc = RADEONScreenInit;
-static xf86SwitchModeProc *const volatile SwitchModeProc = RADEONSwitchMode;
-static xf86AdjustFrameProc *const volatile AdjustFrameProc = RADEONAdjustFrame;
-static xf86EnterVTProc *const volatile EnterVTProc = RADEONEnterVT;
-static xf86LeaveVTProc *const volatile LeaveVTProc = RADEONLeaveVT;
-static xf86FreeScreenProc *const volatile FreeScreenProc = RADEONFreeScreen;
-static xf86ValidModeProc *const volatile ValidModeProc = RADEONValidMode;
-#ifdef X_XF86MiscPassMessage
-static xf86HandleMessageProc *const volatile HandleMessageProc
- = RADEONHandleMessage;
-#endif
-
-#define RADEONPreInit PreInitProc
-#define RADEONScreenInit ScreenInitProc
-#define RADEONSwitchMode SwitchModeProc
-#define RADEONAdjustFrame AdjustFrameProc
-#define RADEONEnterVT EnterVTProc
-#define RADEONLeaveVT LeaveVTProc
-#define RADEONFreeScreen FreeScreenProc
-#define RADEONValidMode ValidModeProc
-#ifdef X_XF86MiscPassMessage
-# define RADEONHandleMessage HandleMessageProc
-#endif
-
-#endif
-
-SymTabRec RADEONChipsets[] = {
- { PCI_CHIP_RADEON_QD, "ATI Radeon QD (AGP)" },
- { 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)" },
- { 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)" },
- { PCI_CHIP_RADEON_LZ, "ATI Radeon Mobility M6 LZ (AGP)" },
- { PCI_CHIP_RS100_4136, "ATI Radeon IGP320 (A3) 4136" },
- { PCI_CHIP_RS100_4336, "ATI Radeon IGP320M (U1) 4336" },
- { PCI_CHIP_RS200_4137, "ATI Radeon IGP330/340/350 (A4) 4137" },
- { PCI_CHIP_RS200_4337, "ATI Radeon IGP330M/340M/350M (U2) 4337" },
- { 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_QL, "ATI Radeon 8500 QL (AGP)" },
- { PCI_CHIP_R200_QM, "ATI Radeon 9100 QM (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_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 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_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 }
-};
+#include "radeon_chipset.h"
PciChipsets RADEONPciChipsets[] = {
{ PCI_CHIP_RADEON_QD, PCI_CHIP_RADEON_QD, RES_SHARED_VGA },
@@ -181,6 +82,8 @@ PciChipsets RADEONPciChipsets[] = {
{ PCI_CHIP_RV250_Lg, PCI_CHIP_RV250_Lg, RES_SHARED_VGA },
{ PCI_CHIP_RS300_5834, PCI_CHIP_RS300_5834, RES_SHARED_VGA },
{ PCI_CHIP_RS300_5835, PCI_CHIP_RS300_5835, RES_SHARED_VGA },
+ { PCI_CHIP_RS350_7834, PCI_CHIP_RS350_7834, RES_SHARED_VGA },
+ { PCI_CHIP_RS350_7835, PCI_CHIP_RS350_7835, RES_SHARED_VGA },
{ 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 },
@@ -215,11 +118,40 @@ PciChipsets RADEONPciChipsets[] = {
{ 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 },
+ { PCI_CHIP_RV380_3E50, PCI_CHIP_RV380_3E50, RES_SHARED_VGA },
+ { PCI_CHIP_RV380_3E54, PCI_CHIP_RV380_3E54, RES_SHARED_VGA },
+ { PCI_CHIP_RV380_3150, PCI_CHIP_RV380_3150, RES_SHARED_VGA },
+ { PCI_CHIP_RV380_3154, PCI_CHIP_RV380_3154, RES_SHARED_VGA },
+ { PCI_CHIP_RV370_5B60, PCI_CHIP_RV370_5B60, RES_SHARED_VGA },
+ { PCI_CHIP_RV370_5B62, PCI_CHIP_RV370_5B62, RES_SHARED_VGA },
+ { PCI_CHIP_RV370_5B64, PCI_CHIP_RV370_5B64, RES_SHARED_VGA },
+ { PCI_CHIP_RV370_5B65, PCI_CHIP_RV370_5B65, RES_SHARED_VGA },
+ { PCI_CHIP_RV370_5460, PCI_CHIP_RV370_5460, RES_SHARED_VGA },
+ { PCI_CHIP_RV370_5464, PCI_CHIP_RV370_5464, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JH, PCI_CHIP_R420_JH, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JI, PCI_CHIP_R420_JI, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JJ, PCI_CHIP_R420_JJ, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JK, PCI_CHIP_R420_JK, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JL, PCI_CHIP_R420_JL, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JM, PCI_CHIP_R420_JM, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JN, PCI_CHIP_R420_JN, RES_SHARED_VGA },
+ { PCI_CHIP_R420_JP, PCI_CHIP_R420_JP, RES_SHARED_VGA },
+ { PCI_CHIP_R423_UH, PCI_CHIP_R423_UH, RES_SHARED_VGA },
+ { PCI_CHIP_R423_UI, PCI_CHIP_R423_UI, RES_SHARED_VGA },
+ { PCI_CHIP_R423_UJ, PCI_CHIP_R423_UJ, RES_SHARED_VGA },
+ { PCI_CHIP_R423_UK, PCI_CHIP_R423_UK, RES_SHARED_VGA },
+ { PCI_CHIP_R423_UQ, PCI_CHIP_R423_UQ, RES_SHARED_VGA },
+ { PCI_CHIP_R423_UR, PCI_CHIP_R423_UR, RES_SHARED_VGA },
+ { PCI_CHIP_R423_UT, PCI_CHIP_R423_UT, RES_SHARED_VGA },
+ { PCI_CHIP_R423_5D57, PCI_CHIP_R423_5D57, RES_SHARED_VGA },
+
{ -1, -1, RES_UNDEFINED }
};
int gRADEONEntityIndex = -1;
+const int getRADEONEntityIndex(void) { return gRADEONEntityIndex; }
+
/* Return the options for supported chipset 'n'; NULL otherwise */
const OptionInfoRec *
RADEONAvailableOptions(int chipid, int busid)
@@ -234,7 +166,7 @@ RADEONAvailableOptions(int chipid, int busid)
chipid -= PCI_VENDOR_ATI << 16;
for (i = 0; RADEONPciChipsets[i].PCIid > 0; i++) {
if (chipid == RADEONPciChipsets[i].PCIid)
- return RADEONOptions;
+ return RADEONOptionsWeak();
}
return NULL;
}
@@ -317,21 +249,8 @@ RADEONProbe(DriverPtr drv, int flags)
xf86LoaderReqSymLists(RADEONSymbols, NULL);
#endif
- pScrn->driverVersion = RADEON_VERSION_CURRENT;
- pScrn->driverName = RADEON_DRIVER_NAME;
- pScrn->name = RADEON_NAME;
pScrn->Probe = RADEONProbe;
- pScrn->PreInit = RADEONPreInit;
- pScrn->ScreenInit = RADEONScreenInit;
- pScrn->SwitchMode = RADEONSwitchMode;
-#ifdef X_XF86MiscPassMessage
- pScrn->HandleMessage = RADEONHandleMessage;
-#endif
- pScrn->AdjustFrame = RADEONAdjustFrame;
- pScrn->EnterVT = RADEONEnterVT;
- pScrn->LeaveVT = RADEONLeaveVT;
- pScrn->FreeScreen = RADEONFreeScreen;
- pScrn->ValidMode = RADEONValidMode;
+ RADEONFillInScreenInfo(pScrn);
foundScreen = TRUE;
}
@@ -363,7 +282,6 @@ RADEONProbe(DriverPtr drv, int flags)
pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
pRADEONEnt = pPriv->ptr;
pRADEONEnt->HasSecondary = FALSE;
- pRADEONEnt->IsSecondaryRestored = FALSE;
} else {
pRADEONEnt = pPriv->ptr;
pRADEONEnt->HasSecondary = TRUE;
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index af32f252..a104cbc9 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -45,6 +45,76 @@
#define _XF86MISC_SERVER_
#include "xf86misc.h"
+typedef enum
+{
+ DDC_NONE_DETECTED,
+ DDC_MONID,
+ DDC_DVI,
+ DDC_VGA,
+ DDC_CRT2
+} RADEONDDCType;
+
+typedef enum
+{
+ MT_UNKNOWN = -1,
+ MT_NONE = 0,
+ MT_CRT = 1,
+ MT_LCD = 2,
+ MT_DFP = 3,
+ MT_CTV = 4,
+ MT_STV = 5
+} RADEONMonitorType;
+
+typedef enum
+{
+ CONNECTOR_NONE,
+ CONNECTOR_PROPRIETARY,
+ CONNECTOR_CRT,
+ CONNECTOR_DVI_I,
+ CONNECTOR_DVI_D,
+ CONNECTOR_CTV,
+ CONNECTOR_STV,
+ CONNECTOR_UNSUPPORTED
+} RADEONConnectorType;
+
+typedef enum
+{
+ CONNECTOR_NONE_ATOM,
+ CONNECTOR_VGA_ATOM,
+ CONNECTOR_DVI_I_ATOM,
+ CONNECTOR_DVI_D_ATOM,
+ CONNECTOR_DVI_A_ATOM,
+ CONNECTOR_STV_ATOM,
+ CONNECTOR_CTV_ATOM,
+ CONNECTOR_LVDS_ATOM,
+ CONNECTOR_DIGITAL_ATOM,
+ CONNECTOR_UNSUPPORTED_ATOM
+} RADEONConnectorTypeATOM;
+
+typedef enum
+{
+ DAC_UNKNOWN = -1,
+ DAC_PRIMARY = 0,
+ DAC_TVDAC = 1
+} RADEONDacType;
+
+typedef enum
+{
+ TMDS_UNKNOWN = -1,
+ TMDS_INT = 0,
+ TMDS_EXT = 1
+} RADEONTmdsType;
+
+typedef struct
+{
+ RADEONDDCType DDCType;
+ RADEONDacType DACType;
+ RADEONTmdsType TMDSType;
+ RADEONConnectorType ConnectorType;
+ RADEONMonitorType MonType;
+ xf86MonPtr MonInfo;
+} RADEONConnector;
+
typedef struct
{
Bool HasSecondary;
@@ -65,6 +135,7 @@ typedef struct
xf86MonPtr MonInfo2;
Bool ReversedDAC; /* TVDAC used as primary dac */
Bool ReversedTMDS; /* DDC_DVI is used for external TMDS */
+ RADEONConnector PortInfo[2];
} RADEONEntRec, *RADEONEntPtr;
/* radeon_probe.c */
@@ -104,6 +175,10 @@ extern ModeStatus RADEONValidMode
FunctionPrototype((int, DisplayModePtr, Bool,
int));
-extern const OptionInfoRec RADEONOptions[];
+extern const OptionInfoRec *RADEONOptionsWeak
+ FunctionPrototype((void));
+
+extern void RADEONFillInScreenInfo
+ FunctionPrototype((ScrnInfoPtr));
#endif /* _RADEON_PROBE_H_ */
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 8af5da5c..8849cabd 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -203,11 +203,20 @@
#define RADEON_CAPABILITIES_ID 0x0f50 /* PCI */
#define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */
#define RADEON_CLK_PIN_CNTL 0x0001 /* PLL */
+# define RADEON_SCLK_DYN_START_CNTL (1 << 15)
#define RADEON_CLOCK_CNTL_DATA 0x000c
#define RADEON_CLOCK_CNTL_INDEX 0x0008
# define RADEON_PLL_WR_EN (1 << 7)
# define RADEON_PLL_DIV_SEL (3 << 8)
# define RADEON_PLL2_DIV_SEL_MASK ~(3 << 8)
+#define RADEON_CLK_PWRMGT_CNTL 0x0014
+# define RADEON_ENGIN_DYNCLK_MODE (1 << 12)
+# define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13)
+# define RADEON_ACTIVE_HILO_LAT_SHIFT 13
+# define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12)
+# define RADEON_DYN_STOP_MODE_MASK (7 << 21)
+#define RADEON_PLL_PWRMGT_CNTL 0x0015
+# define RADEON_TCL_BYPASS_DISABLE (1 << 20)
#define RADEON_CLR_CMP_CLR_3D 0x1a24
#define RADEON_CLR_CMP_CLR_DST 0x15c8
#define RADEON_CLR_CMP_CLR_SRC 0x15c4
@@ -303,8 +312,8 @@
# define RADEON_CRTC2_HSYNC_DIS (1 << 28)
# 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_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)
@@ -413,10 +422,10 @@
# define RADEON_DAC_PDWN_B (1 << 18)
#define RADEON_TV_DAC_CNTL 0x088c
# define RADEON_TV_DAC_STD_MASK 0x0300
+# define RADEON_TV_DAC_BGSLEEP (1 << 6)
# define RADEON_TV_DAC_RDACPD (1 << 24)
# define RADEON_TV_DAC_GDACPD (1 << 25)
# define RADEON_TV_DAC_BDACPD (1 << 26)
-# define RADEON_TV_DAC_BGSLEEP (1 << 26)
#define RADEON_DISP_HW_DEBUG 0x0d14
# define RADEON_CRT2_DISP1_SEL (1 << 5)
#define RADEON_DISP_OUTPUT_CNTL 0x0d64
@@ -629,10 +638,17 @@
# define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010
#define RADEON_FP_GEN_CNTL 0x0284
# define RADEON_FP_FPON (1 << 0)
+# define RADEON_FP_BLANK_EN (1 << 1)
# define RADEON_FP_TMDS_EN (1 << 2)
# define RADEON_FP_PANEL_FORMAT (1 << 3)
# define RADEON_FP_EN_TMDS (1 << 7)
# define RADEON_FP_DETECT_SENSE (1 << 8)
+# define R200_FP_SOURCE_SEL_MASK (3 << 10)
+# define R200_FP_SOURCE_SEL_CRTC1 (0 << 10)
+# define R200_FP_SOURCE_SEL_CRTC2 (1 << 10)
+# define R200_FP_SOURCE_SEL_RMX (2 << 10)
+# define R200_FP_SOURCE_SEL_TRANS (3 << 10)
+# define RADEON_FP_SEL_CRTC1 (0 << 13)
# define RADEON_FP_SEL_CRTC2 (1 << 13)
# define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15)
# define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
@@ -648,8 +664,10 @@
# define RADEON_FP2_BLANK_EN (1 << 1)
# define RADEON_FP2_ON (1 << 2)
# define RADEON_FP2_PANEL_FORMAT (1 << 3)
-# define RADEON_FP2_SOURCE_SEL_MASK (3 << 10)
-# define RADEON_FP2_SOURCE_SEL_CRTC2 (1 << 10)
+# define R200_FP2_SOURCE_SEL_MASK (3 << 10)
+# define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10)
+# define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10)
+# define R200_FP2_SOURCE_SEL_RMX (2 << 10)
# define RADEON_FP2_SRC_SEL_MASK (3 << 13)
# define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13)
# define RADEON_FP2_FP_POL (1 << 16)
@@ -659,8 +677,8 @@
# define RADEON_FP2_PAD_FLOP_EN (1 << 22)
# define RADEON_FP2_CRC_EN (1 << 23)
# define RADEON_FP2_CRC_READ_EN (1 << 24)
-# define RADEON_FP2_DV0_EN (1 << 25)
-# define RADEON_FP2_DV0_RATE_SEL_SDR (1 << 26)
+# define RADEON_FP2_DVO_EN (1 << 25)
+# define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26)
#define RADEON_FP_H_SYNC_STRT_WID 0x02c4
#define RADEON_FP_H2_SYNC_STRT_WID 0x03c4
#define RADEON_FP_HORZ_STRETCH 0x028c
@@ -779,6 +797,13 @@
# define RADEON_FORCEON_YCLKB (1 << 19)
# define RADEON_FORCEON_MC (1 << 20)
# define RADEON_FORCEON_AIC (1 << 21)
+# define R300_DISABLE_MC_MCLKA (1 << 21)
+# define R300_DISABLE_MC_MCLKB (1 << 21)
+#define RADEON_MCLK_MISC 0x001f /* PLL */
+# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1<<12)
+# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13)
+# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14)
+# define RADEON_IO_MCLK_DYN_ENABLE (1 << 14)
#define RADEON_MDGPIO_A_REG 0x01ac
#define RADEON_MDGPIO_EN_REG 0x01b0
#define RADEON_MDGPIO_MASK 0x0198
@@ -981,8 +1006,19 @@
# define RADEON_PIX2CLK_ALWAYS_ONb (1<<6)
# define RADEON_PIX2CLK_DAC_ALWAYS_ONb (1<<7)
# define RADEON_PIXCLK_TV_SRC_SEL (1 << 8)
+# define RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb (1 << 9)
+# define R300_DVOCLK_ALWAYS_ONb (1 << 10)
+# define RADEON_PIXCLK_BLEND_ALWAYS_ONb (1 << 11)
+# define RADEON_PIXCLK_GV_ALWAYS_ONb (1 << 12)
+# define RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb (1 << 13)
+# define R300_PIXCLK_DVO_ALWAYS_ONb (1 << 13)
# define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14)
# define RADEON_PIXCLK_TMDS_ALWAYS_ONb (1 << 15)
+# define R300_PIXCLK_TRANS_ALWAYS_ONb (1 << 16)
+# define R300_PIXCLK_TVO_ALWAYS_ONb (1 << 17)
+# define R300_P2G2CLK_ALWAYS_ONb (1 << 18)
+# define R300_P2G2CLK_DAC_ALWAYS_ONb (1 << 19)
+# define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23)
#define RADEON_PLANE_3D_MASK_C 0x1d44
#define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */
#define RADEON_PMI_CAP_ID 0x0f5c /* PCI */
@@ -1047,10 +1083,42 @@
# define RADEON_SC_SIGN_MASK_LO 0x8000
# define RADEON_SC_SIGN_MASK_HI 0x80000000
#define RADEON_SCLK_CNTL 0x000d /* PLL */
+# define RADEON_SCLK_SRC_SEL_MASK 0x0007
# define RADEON_DYN_STOP_LAT_MASK 0x00007ff8
# define RADEON_CP_MAX_DYN_STOP_LAT 0x0008
# define RADEON_SCLK_FORCEON_MASK 0xffff8000
+# define RADEON_SCLK_FORCE_DISP2 (1<<15)
+# define RADEON_SCLK_FORCE_CP (1<<16)
+# define RADEON_SCLK_FORCE_HDP (1<<17)
+# define RADEON_SCLK_FORCE_DISP1 (1<<18)
+# define RADEON_SCLK_FORCE_TOP (1<<19)
+# define RADEON_SCLK_FORCE_E2 (1<<20)
+# define RADEON_SCLK_FORCE_SE (1<<21)
+# define RADEON_SCLK_FORCE_IDCT (1<<22)
+# define RADEON_SCLK_FORCE_VIP (1<<23)
+# define RADEON_SCLK_FORCE_RE (1<<24)
+# define RADEON_SCLK_FORCE_PB (1<<25)
+# define RADEON_SCLK_FORCE_TAM (1<<26)
+# define RADEON_SCLK_FORCE_TDM (1<<27)
+# define RADEON_SCLK_FORCE_RB (1<<28)
+# define RADEON_SCLK_FORCE_TV_SCLK (1<<29)
+# define RADEON_SCLK_FORCE_SUBPIC (1<<30)
+# define RADEON_SCLK_FORCE_OV0 (1<<31)
+# define R300_SCLK_FORCE_VAP (1<<21)
+# define R300_SCLK_FORCE_SR (1<<25)
+# define R300_SCLK_FORCE_PX (1<<26)
+# define R300_SCLK_FORCE_TX (1<<27)
+# define R300_SCLK_FORCE_US (1<<28)
+# define R300_SCLK_FORCE_SU (1<<30)
+#define R300_SCLK_CNTL2 0x1e /* PLL */
+# define R300_SCLK_TCL_MAX_DYN_STOP_LAT (1<<10)
+# define R300_SCLK_GA_MAX_DYN_STOP_LAT (1<<11)
+# define R300_SCLK_CBA_MAX_DYN_STOP_LAT (1<<12)
+# define R300_SCLK_FORCE_TCL (1<<13)
+# define R300_SCLK_FORCE_CBA (1<<14)
+# define R300_SCLK_FORCE_GA (1<<15)
#define RADEON_SCLK_MORE_CNTL 0x0035 /* PLL */
+# define RADEON_SCLK_MORE_MAX_DYN_STOP_LAT 0x0007
# define RADEON_SCLK_MORE_FORCEON 0x0700
#define RADEON_SDRAM_MODE_REG 0x0158
#define RADEON_SEQ8_DATA 0x03c5 /* VGA */
@@ -1124,6 +1192,7 @@
# define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03
# define RADEON_PIXCLK_ALWAYS_ONb (1<<6)
# define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7)
+# define R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF (1<<23)
#define RADEON_VENDOR_ID 0x0f00 /* PCI */
#define RADEON_VGA_DDA_CONFIG 0x02e8
@@ -1718,6 +1787,18 @@
# define RADEON_ROUND_PREC_8TH_PIX (1 << 30)
# define RADEON_ROUND_PREC_4TH_PIX (2 << 30)
# define RADEON_ROUND_PREC_HALF_PIX (3 << 30)
+#define R200_RE_CNTL 0x1c50
+# define R200_STIPPLE_ENABLE 0x1
+# define R200_SCISSOR_ENABLE 0x2
+# define R200_PATTERN_ENABLE 0x4
+# define R200_PERSPECTIVE_ENABLE 0x8
+# define R200_POINT_SMOOTH 0x20
+# define R200_VTX_STQ0_D3D 0x00010000
+# define R200_VTX_STQ1_D3D 0x00040000
+# define R200_VTX_STQ2_D3D 0x00100000
+# define R200_VTX_STQ3_D3D 0x00400000
+# define R200_VTX_STQ4_D3D 0x01000000
+# define R200_VTX_STQ5_D3D 0x04000000
#define RADEON_SE_CNTL_STATUS 0x2140
# define RADEON_VC_NO_SWAP (0 << 0)
# define RADEON_VC_16BIT_SWAP (1 << 0)
@@ -1937,7 +2018,528 @@
#define RADEON_SE_ZBIAS_FACTOR 0x1db0
#define RADEON_SE_ZBIAS_CONSTANT 0x1db4
+#define RADEON_SE_VTX_FMT 0x2080
+# define RADEON_SE_VTX_FMT_XY 0x00000000
+# define RADEON_SE_VTX_FMT_W0 0x00000001
+# define RADEON_SE_VTX_FMT_FPCOLOR 0x00000002
+# define RADEON_SE_VTX_FMT_FPALPHA 0x00000004
+# define RADEON_SE_VTX_FMT_PKCOLOR 0x00000008
+# define RADEON_SE_VTX_FMT_FPSPEC 0x00000010
+# define RADEON_SE_VTX_FMT_FPFOG 0x00000020
+# define RADEON_SE_VTX_FMT_PKSPEC 0x00000040
+# define RADEON_SE_VTX_FMT_ST0 0x00000080
+# define RADEON_SE_VTX_FMT_ST1 0x00000100
+# define RADEON_SE_VTX_FMT_Q1 0x00000200
+# define RADEON_SE_VTX_FMT_ST2 0x00000400
+# define RADEON_SE_VTX_FMT_Q2 0x00000800
+# define RADEON_SE_VTX_FMT_ST3 0x00001000
+# define RADEON_SE_VTX_FMT_Q3 0x00002000
+# define RADEON_SE_VTX_FMT_Q0 0x00004000
+# define RADEON_SE_VTX_FMT_BLND_WEIGHT_CNT_MASK 0x00038000
+# define RADEON_SE_VTX_FMT_N0 0x00040000
+# define RADEON_SE_VTX_FMT_XY1 0x08000000
+# define RADEON_SE_VTX_FMT_Z1 0x10000000
+# define RADEON_SE_VTX_FMT_W1 0x20000000
+# define RADEON_SE_VTX_FMT_N1 0x40000000
+# define RADEON_SE_VTX_FMT_Z 0x80000000
+#define RADEON_SE_VF_CNTL 0x2084
+# define RADEON_VF_PRIM_TYPE_POINT_LIST 1
+# define RADEON_VF_PRIM_TYPE_LINE_LIST 2
+# define RADEON_VF_PRIM_TYPE_LINE_STRIP 3
+# define RADEON_VF_PRIM_TYPE_TRIANGLE_LIST 4
+# define RADEON_VF_PRIM_TYPE_TRIANGLE_FAN 5
+# define RADEON_VF_PRIM_TYPE_TRIANGLE_STRIP 6
+# define RADEON_VF_PRIM_TYPE_TRIANGLE_FLAG 7
+# define RADEON_VF_PRIM_TYPE_RECTANGLE_LIST 8
+# define RADEON_VF_PRIM_TYPE_POINT_LIST_3 9
+# define RADEON_VF_PRIM_TYPE_LINE_LIST_3 10
+# define RADEON_VF_PRIM_TYPE_SPIRIT_LIST 11
+# define RADEON_VF_PRIM_TYPE_LINE_LOOP 12
+# define RADEON_VF_PRIM_TYPE_QUAD_LIST 13
+# define RADEON_VF_PRIM_TYPE_QUAD_STRIP 14
+# define RADEON_VF_PRIM_TYPE_POLYGON 15
+# define RADEON_VF_PRIM_WALK_STATE (0<<4)
+# define RADEON_VF_PRIM_WALK_INDEX (1<<4)
+# define RADEON_VF_PRIM_WALK_LIST (2<<4)
+# define RADEON_VF_PRIM_WALK_DATA (3<<4)
+# define RADEON_VF_COLOR_ORDER_RGBA (1<<6)
+# define RADEON_VF_RADEON_MODE (1<<8)
+# define RADEON_VF_TCL_OUTPUT_CTL_ENA (1<<9)
+# define RADEON_VF_PROG_STREAM_ENA (1<<10)
+# define RADEON_VF_INDEX_SIZE_SHIFT 11
+# define RADEON_VF_NUM_VERTICES_SHIFT 16
+
+#define RADEON_SE_PORT_DATA0 0x2000
+
+#define R200_SE_VAP_CNTL 0x2080
+# define R200_VAP_TCL_ENABLE 0x00000001
+# define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010
+# define R200_VAP_FORCE_W_TO_ONE 0x00010000
+# define R200_VAP_D3D_TEX_DEFAULT 0x00020000
+# define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18
+# define R200_VAP_VF_MAX_VTX_NUM (9 << 18)
+# define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000
+#define R200_VF_MAX_VTX_INDX 0x210c
+#define R200_VF_MIN_VTX_INDX 0x2110
+#define R200_SE_VTE_CNTL 0x20b0
+# define R200_VPORT_X_SCALE_ENA 0x00000001
+# define R200_VPORT_X_OFFSET_ENA 0x00000002
+# define R200_VPORT_Y_SCALE_ENA 0x00000004
+# define R200_VPORT_Y_OFFSET_ENA 0x00000008
+# define R200_VPORT_Z_SCALE_ENA 0x00000010
+# define R200_VPORT_Z_OFFSET_ENA 0x00000020
+# define R200_VTX_XY_FMT 0x00000100
+# define R200_VTX_Z_FMT 0x00000200
+# define R200_VTX_W0_FMT 0x00000400
+# define R200_VTX_W0_NORMALIZE 0x00000800
+# define R200_VTX_ST_DENORMALIZED 0x00001000
+#define R200_SE_VAP_CNTL_STATUS 0x2140
+# define R200_VC_NO_SWAP (0 << 0)
+# define R200_VC_16BIT_SWAP (1 << 0)
+# define R200_VC_32BIT_SWAP (2 << 0)
+#define R200_PP_TXFILTER_0 0x2c00
+# define R200_MAG_FILTER_NEAREST (0 << 0)
+# define R200_MAG_FILTER_LINEAR (1 << 0)
+# define R200_MAG_FILTER_MASK (1 << 0)
+# define R200_MIN_FILTER_NEAREST (0 << 1)
+# define R200_MIN_FILTER_LINEAR (1 << 1)
+# define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1)
+# define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1)
+# define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1)
+# define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1)
+# define R200_MIN_FILTER_ANISO_NEAREST (8 << 1)
+# define R200_MIN_FILTER_ANISO_LINEAR (9 << 1)
+# define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1)
+# define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1)
+# define R200_MIN_FILTER_MASK (15 << 1)
+# define R200_MAX_ANISO_1_TO_1 (0 << 5)
+# define R200_MAX_ANISO_2_TO_1 (1 << 5)
+# define R200_MAX_ANISO_4_TO_1 (2 << 5)
+# define R200_MAX_ANISO_8_TO_1 (3 << 5)
+# define R200_MAX_ANISO_16_TO_1 (4 << 5)
+# define R200_MAX_ANISO_MASK (7 << 5)
+# define R200_MAX_MIP_LEVEL_MASK (0x0f << 16)
+# define R200_MAX_MIP_LEVEL_SHIFT 16
+# define R200_YUV_TO_RGB (1 << 20)
+# define R200_YUV_TEMPERATURE_COOL (0 << 21)
+# define R200_YUV_TEMPERATURE_HOT (1 << 21)
+# define R200_YUV_TEMPERATURE_MASK (1 << 21)
+# define R200_WRAPEN_S (1 << 22)
+# define R200_CLAMP_S_WRAP (0 << 23)
+# define R200_CLAMP_S_MIRROR (1 << 23)
+# define R200_CLAMP_S_CLAMP_LAST (2 << 23)
+# define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23)
+# define R200_CLAMP_S_CLAMP_BORDER (4 << 23)
+# define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23)
+# define R200_CLAMP_S_CLAMP_GL (6 << 23)
+# define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23)
+# define R200_CLAMP_S_MASK (7 << 23)
+# define R200_WRAPEN_T (1 << 26)
+# define R200_CLAMP_T_WRAP (0 << 27)
+# define R200_CLAMP_T_MIRROR (1 << 27)
+# define R200_CLAMP_T_CLAMP_LAST (2 << 27)
+# define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27)
+# define R200_CLAMP_T_CLAMP_BORDER (4 << 27)
+# define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27)
+# define R200_CLAMP_T_CLAMP_GL (6 << 27)
+# define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27)
+# define R200_CLAMP_T_MASK (7 << 27)
+# define R200_KILL_LT_ZERO (1 << 30)
+# define R200_BORDER_MODE_OGL (0 << 31)
+# define R200_BORDER_MODE_D3D (1 << 31)
+#define R200_PP_TXFORMAT_0 0x2c04
+# define R200_TXFORMAT_I8 (0 << 0)
+# define R200_TXFORMAT_AI88 (1 << 0)
+# define R200_TXFORMAT_RGB332 (2 << 0)
+# define R200_TXFORMAT_ARGB1555 (3 << 0)
+# define R200_TXFORMAT_RGB565 (4 << 0)
+# define R200_TXFORMAT_ARGB4444 (5 << 0)
+# define R200_TXFORMAT_ARGB8888 (6 << 0)
+# define R200_TXFORMAT_RGBA8888 (7 << 0)
+# define R200_TXFORMAT_Y8 (8 << 0)
+# define R200_TXFORMAT_AVYU4444 (9 << 0)
+# define R200_TXFORMAT_VYUY422 (10 << 0)
+# define R200_TXFORMAT_YVYU422 (11 << 0)
+# define R200_TXFORMAT_DXT1 (12 << 0)
+# define R200_TXFORMAT_DXT23 (14 << 0)
+# define R200_TXFORMAT_DXT45 (15 << 0)
+# define R200_TXFORMAT_FORMAT_MASK (31 << 0)
+# define R200_TXFORMAT_FORMAT_SHIFT 0
+# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6)
+# define R200_TXFORMAT_NON_POWER2 (1 << 7)
+# define R200_TXFORMAT_WIDTH_MASK (15 << 8)
+# define R200_TXFORMAT_WIDTH_SHIFT 8
+# define R200_TXFORMAT_HEIGHT_MASK (15 << 12)
+# define R200_TXFORMAT_HEIGHT_SHIFT 12
+# define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */
+# define R200_TXFORMAT_F5_WIDTH_SHIFT 16
+# define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20)
+# define R200_TXFORMAT_F5_HEIGHT_SHIFT 20
+# define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24)
+# define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24)
+# define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24)
+# define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24)
+# define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24)
+# define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24)
+# define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24)
+# define R200_TXFORMAT_ST_ROUTE_SHIFT 24
+# define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28)
+# define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29)
+# define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30)
+#define R200_PP_TXFORMAT_X_0 0x2c08
+#define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */
+#define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */
+#define R200_PP_TXOFFSET_0 0x2d00
+# define R200_TXO_ENDIAN_NO_SWAP (0 << 0)
+# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0)
+# define R200_TXO_ENDIAN_WORD_SWAP (2 << 0)
+# define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
+# define R200_TXO_OFFSET_MASK 0xffffffe0
+# define R200_TXO_OFFSET_SHIFT 5
+
+#define R200_PP_TFACTOR_0 0x2ee0
+#define R200_PP_TFACTOR_1 0x2ee4
+#define R200_PP_TFACTOR_2 0x2ee8
+#define R200_PP_TFACTOR_3 0x2eec
+#define R200_PP_TFACTOR_4 0x2ef0
+#define R200_PP_TFACTOR_5 0x2ef4
+
+#define R200_PP_TXCBLEND_0 0x2f00
+# define R200_TXC_ARG_A_ZERO (0)
+# define R200_TXC_ARG_A_CURRENT_COLOR (2)
+# define R200_TXC_ARG_A_CURRENT_ALPHA (3)
+# define R200_TXC_ARG_A_DIFFUSE_COLOR (4)
+# define R200_TXC_ARG_A_DIFFUSE_ALPHA (5)
+# define R200_TXC_ARG_A_SPECULAR_COLOR (6)
+# define R200_TXC_ARG_A_SPECULAR_ALPHA (7)
+# define R200_TXC_ARG_A_TFACTOR_COLOR (8)
+# define R200_TXC_ARG_A_TFACTOR_ALPHA (9)
+# define R200_TXC_ARG_A_R0_COLOR (10)
+# define R200_TXC_ARG_A_R0_ALPHA (11)
+# define R200_TXC_ARG_A_R1_COLOR (12)
+# define R200_TXC_ARG_A_R1_ALPHA (13)
+# define R200_TXC_ARG_A_R2_COLOR (14)
+# define R200_TXC_ARG_A_R2_ALPHA (15)
+# define R200_TXC_ARG_A_R3_COLOR (16)
+# define R200_TXC_ARG_A_R3_ALPHA (17)
+# define R200_TXC_ARG_A_R4_COLOR (18)
+# define R200_TXC_ARG_A_R4_ALPHA (19)
+# define R200_TXC_ARG_A_R5_COLOR (20)
+# define R200_TXC_ARG_A_R5_ALPHA (21)
+# define R200_TXC_ARG_A_TFACTOR1_COLOR (26)
+# define R200_TXC_ARG_A_TFACTOR1_ALPHA (27)
+# define R200_TXC_ARG_A_MASK (31 << 0)
+# define R200_TXC_ARG_A_SHIFT 0
+# define R200_TXC_ARG_B_ZERO (0 << 5)
+# define R200_TXC_ARG_B_CURRENT_COLOR (2 << 5)
+# define R200_TXC_ARG_B_CURRENT_ALPHA (3 << 5)
+# define R200_TXC_ARG_B_DIFFUSE_COLOR (4 << 5)
+# define R200_TXC_ARG_B_DIFFUSE_ALPHA (5 << 5)
+# define R200_TXC_ARG_B_SPECULAR_COLOR (6 << 5)
+# define R200_TXC_ARG_B_SPECULAR_ALPHA (7 << 5)
+# define R200_TXC_ARG_B_TFACTOR_COLOR (8 << 5)
+# define R200_TXC_ARG_B_TFACTOR_ALPHA (9 << 5)
+# define R200_TXC_ARG_B_R0_COLOR (10 << 5)
+# define R200_TXC_ARG_B_R0_ALPHA (11 << 5)
+# define R200_TXC_ARG_B_R1_COLOR (12 << 5)
+# define R200_TXC_ARG_B_R1_ALPHA (13 << 5)
+# define R200_TXC_ARG_B_R2_COLOR (14 << 5)
+# define R200_TXC_ARG_B_R2_ALPHA (15 << 5)
+# define R200_TXC_ARG_B_R3_COLOR (16 << 5)
+# define R200_TXC_ARG_B_R3_ALPHA (17 << 5)
+# define R200_TXC_ARG_B_R4_COLOR (18 << 5)
+# define R200_TXC_ARG_B_R4_ALPHA (19 << 5)
+# define R200_TXC_ARG_B_R5_COLOR (20 << 5)
+# define R200_TXC_ARG_B_R5_ALPHA (21 << 5)
+# define R200_TXC_ARG_B_TFACTOR1_COLOR (26 << 5)
+# define R200_TXC_ARG_B_TFACTOR1_ALPHA (27 << 5)
+# define R200_TXC_ARG_B_MASK (31 << 5)
+# define R200_TXC_ARG_B_SHIFT 5
+# define R200_TXC_ARG_C_ZERO (0 << 10)
+# define R200_TXC_ARG_C_CURRENT_COLOR (2 << 10)
+# define R200_TXC_ARG_C_CURRENT_ALPHA (3 << 10)
+# define R200_TXC_ARG_C_DIFFUSE_COLOR (4 << 10)
+# define R200_TXC_ARG_C_DIFFUSE_ALPHA (5 << 10)
+# define R200_TXC_ARG_C_SPECULAR_COLOR (6 << 10)
+# define R200_TXC_ARG_C_SPECULAR_ALPHA (7 << 10)
+# define R200_TXC_ARG_C_TFACTOR_COLOR (8 << 10)
+# define R200_TXC_ARG_C_TFACTOR_ALPHA (9 << 10)
+# define R200_TXC_ARG_C_R0_COLOR (10 << 10)
+# define R200_TXC_ARG_C_R0_ALPHA (11 << 10)
+# define R200_TXC_ARG_C_R1_COLOR (12 << 10)
+# define R200_TXC_ARG_C_R1_ALPHA (13 << 10)
+# define R200_TXC_ARG_C_R2_COLOR (14 << 10)
+# define R200_TXC_ARG_C_R2_ALPHA (15 << 10)
+# define R200_TXC_ARG_C_R3_COLOR (16 << 10)
+# define R200_TXC_ARG_C_R3_ALPHA (17 << 10)
+# define R200_TXC_ARG_C_R4_COLOR (18 << 10)
+# define R200_TXC_ARG_C_R4_ALPHA (19 << 10)
+# define R200_TXC_ARG_C_R5_COLOR (20 << 10)
+# define R200_TXC_ARG_C_R5_ALPHA (21 << 10)
+# define R200_TXC_ARG_C_TFACTOR1_COLOR (26 << 10)
+# define R200_TXC_ARG_C_TFACTOR1_ALPHA (27 << 10)
+# define R200_TXC_ARG_C_MASK (31 << 10)
+# define R200_TXC_ARG_C_SHIFT 10
+# define R200_TXC_COMP_ARG_A (1 << 16)
+# define R200_TXC_COMP_ARG_A_SHIFT (16)
+# define R200_TXC_BIAS_ARG_A (1 << 17)
+# define R200_TXC_SCALE_ARG_A (1 << 18)
+# define R200_TXC_NEG_ARG_A (1 << 19)
+# define R200_TXC_COMP_ARG_B (1 << 20)
+# define R200_TXC_COMP_ARG_B_SHIFT (20)
+# define R200_TXC_BIAS_ARG_B (1 << 21)
+# define R200_TXC_SCALE_ARG_B (1 << 22)
+# define R200_TXC_NEG_ARG_B (1 << 23)
+# define R200_TXC_COMP_ARG_C (1 << 24)
+# define R200_TXC_COMP_ARG_C_SHIFT (24)
+# define R200_TXC_BIAS_ARG_C (1 << 25)
+# define R200_TXC_SCALE_ARG_C (1 << 26)
+# define R200_TXC_NEG_ARG_C (1 << 27)
+# define R200_TXC_OP_MADD (0 << 28)
+# define R200_TXC_OP_CND0 (2 << 28)
+# define R200_TXC_OP_LERP (3 << 28)
+# define R200_TXC_OP_DOT3 (4 << 28)
+# define R200_TXC_OP_DOT4 (5 << 28)
+# define R200_TXC_OP_CONDITIONAL (6 << 28)
+# define R200_TXC_OP_DOT2_ADD (7 << 28)
+# define R200_TXC_OP_MASK (7 << 28)
+#define R200_PP_TXCBLEND2_0 0x2f04
+# define R200_TXC_TFACTOR_SEL_SHIFT 0
+# define R200_TXC_TFACTOR_SEL_MASK 0x7
+# define R200_TXC_TFACTOR1_SEL_SHIFT 4
+# define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4)
+# define R200_TXC_SCALE_SHIFT 8
+# define R200_TXC_SCALE_MASK (7 << 8)
+# define R200_TXC_SCALE_1X (0 << 8)
+# define R200_TXC_SCALE_2X (1 << 8)
+# define R200_TXC_SCALE_4X (2 << 8)
+# define R200_TXC_SCALE_8X (3 << 8)
+# define R200_TXC_SCALE_INV2 (5 << 8)
+# define R200_TXC_SCALE_INV4 (6 << 8)
+# define R200_TXC_SCALE_INV8 (7 << 8)
+# define R200_TXC_CLAMP_SHIFT 12
+# define R200_TXC_CLAMP_MASK (3 << 12)
+# define R200_TXC_CLAMP_WRAP (0 << 12)
+# define R200_TXC_CLAMP_0_1 (1 << 12)
+# define R200_TXC_CLAMP_8_8 (2 << 12)
+# define R200_TXC_OUTPUT_REG_MASK (7 << 16)
+# define R200_TXC_OUTPUT_REG_NONE (0 << 16)
+# define R200_TXC_OUTPUT_REG_R0 (1 << 16)
+# define R200_TXC_OUTPUT_REG_R1 (2 << 16)
+# define R200_TXC_OUTPUT_REG_R2 (3 << 16)
+# define R200_TXC_OUTPUT_REG_R3 (4 << 16)
+# define R200_TXC_OUTPUT_REG_R4 (5 << 16)
+# define R200_TXC_OUTPUT_REG_R5 (6 << 16)
+# define R200_TXC_OUTPUT_MASK_MASK (7 << 20)
+# define R200_TXC_OUTPUT_MASK_RGB (0 << 20)
+# define R200_TXC_OUTPUT_MASK_RG (1 << 20)
+# define R200_TXC_OUTPUT_MASK_RB (2 << 20)
+# define R200_TXC_OUTPUT_MASK_R (3 << 20)
+# define R200_TXC_OUTPUT_MASK_GB (4 << 20)
+# define R200_TXC_OUTPUT_MASK_G (5 << 20)
+# define R200_TXC_OUTPUT_MASK_B (6 << 20)
+# define R200_TXC_OUTPUT_MASK_NONE (7 << 20)
+# define R200_TXC_REPL_NORMAL 0
+# define R200_TXC_REPL_RED 1
+# define R200_TXC_REPL_GREEN 2
+# define R200_TXC_REPL_BLUE 3
+# define R200_TXC_REPL_ARG_A_SHIFT 26
+# define R200_TXC_REPL_ARG_A_MASK (3 << 26)
+# define R200_TXC_REPL_ARG_B_SHIFT 28
+# define R200_TXC_REPL_ARG_B_MASK (3 << 28)
+# define R200_TXC_REPL_ARG_C_SHIFT 30
+# define R200_TXC_REPL_ARG_C_MASK (3 << 30)
+#define R200_PP_TXABLEND_0 0x2f08
+# define R200_TXA_ARG_A_ZERO (0)
+# define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */
+# define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */
+# define R200_TXA_ARG_A_DIFFUSE_ALPHA (4)
+# define R200_TXA_ARG_A_DIFFUSE_BLUE (5)
+# define R200_TXA_ARG_A_SPECULAR_ALPHA (6)
+# define R200_TXA_ARG_A_SPECULAR_BLUE (7)
+# define R200_TXA_ARG_A_TFACTOR_ALPHA (8)
+# define R200_TXA_ARG_A_TFACTOR_BLUE (9)
+# define R200_TXA_ARG_A_R0_ALPHA (10)
+# define R200_TXA_ARG_A_R0_BLUE (11)
+# define R200_TXA_ARG_A_R1_ALPHA (12)
+# define R200_TXA_ARG_A_R1_BLUE (13)
+# define R200_TXA_ARG_A_R2_ALPHA (14)
+# define R200_TXA_ARG_A_R2_BLUE (15)
+# define R200_TXA_ARG_A_R3_ALPHA (16)
+# define R200_TXA_ARG_A_R3_BLUE (17)
+# define R200_TXA_ARG_A_R4_ALPHA (18)
+# define R200_TXA_ARG_A_R4_BLUE (19)
+# define R200_TXA_ARG_A_R5_ALPHA (20)
+# define R200_TXA_ARG_A_R5_BLUE (21)
+# define R200_TXA_ARG_A_TFACTOR1_ALPHA (26)
+# define R200_TXA_ARG_A_TFACTOR1_BLUE (27)
+# define R200_TXA_ARG_A_MASK (31 << 0)
+# define R200_TXA_ARG_A_SHIFT 0
+# define R200_TXA_ARG_B_ZERO (0 << 5)
+# define R200_TXA_ARG_B_CURRENT_ALPHA (2 << 5) /* guess */
+# define R200_TXA_ARG_B_CURRENT_BLUE (3 << 5) /* guess */
+# define R200_TXA_ARG_B_DIFFUSE_ALPHA (4 << 5)
+# define R200_TXA_ARG_B_DIFFUSE_BLUE (5 << 5)
+# define R200_TXA_ARG_B_SPECULAR_ALPHA (6 << 5)
+# define R200_TXA_ARG_B_SPECULAR_BLUE (7 << 5)
+# define R200_TXA_ARG_B_TFACTOR_ALPHA (8 << 5)
+# define R200_TXA_ARG_B_TFACTOR_BLUE (9 << 5)
+# define R200_TXA_ARG_B_R0_ALPHA (10 << 5)
+# define R200_TXA_ARG_B_R0_BLUE (11 << 5)
+# define R200_TXA_ARG_B_R1_ALPHA (12 << 5)
+# define R200_TXA_ARG_B_R1_BLUE (13 << 5)
+# define R200_TXA_ARG_B_R2_ALPHA (14 << 5)
+# define R200_TXA_ARG_B_R2_BLUE (15 << 5)
+# define R200_TXA_ARG_B_R3_ALPHA (16 << 5)
+# define R200_TXA_ARG_B_R3_BLUE (17 << 5)
+# define R200_TXA_ARG_B_R4_ALPHA (18 << 5)
+# define R200_TXA_ARG_B_R4_BLUE (19 << 5)
+# define R200_TXA_ARG_B_R5_ALPHA (20 << 5)
+# define R200_TXA_ARG_B_R5_BLUE (21 << 5)
+# define R200_TXA_ARG_B_TFACTOR1_ALPHA (26 << 5)
+# define R200_TXA_ARG_B_TFACTOR1_BLUE (27 << 5)
+# define R200_TXA_ARG_B_MASK (31 << 5)
+# define R200_TXA_ARG_B_SHIFT 5
+# define R200_TXA_ARG_C_ZERO (0 << 10)
+# define R200_TXA_ARG_C_CURRENT_ALPHA (2 << 10) /* guess */
+# define R200_TXA_ARG_C_CURRENT_BLUE (3 << 10) /* guess */
+# define R200_TXA_ARG_C_DIFFUSE_ALPHA (4 << 10)
+# define R200_TXA_ARG_C_DIFFUSE_BLUE (5 << 10)
+# define R200_TXA_ARG_C_SPECULAR_ALPHA (6 << 10)
+# define R200_TXA_ARG_C_SPECULAR_BLUE (7 << 10)
+# define R200_TXA_ARG_C_TFACTOR_ALPHA (8 << 10)
+# define R200_TXA_ARG_C_TFACTOR_BLUE (9 << 10)
+# define R200_TXA_ARG_C_R0_ALPHA (10 << 10)
+# define R200_TXA_ARG_C_R0_BLUE (11 << 10)
+# define R200_TXA_ARG_C_R1_ALPHA (12 << 10)
+# define R200_TXA_ARG_C_R1_BLUE (13 << 10)
+# define R200_TXA_ARG_C_R2_ALPHA (14 << 10)
+# define R200_TXA_ARG_C_R2_BLUE (15 << 10)
+# define R200_TXA_ARG_C_R3_ALPHA (16 << 10)
+# define R200_TXA_ARG_C_R3_BLUE (17 << 10)
+# define R200_TXA_ARG_C_R4_ALPHA (18 << 10)
+# define R200_TXA_ARG_C_R4_BLUE (19 << 10)
+# define R200_TXA_ARG_C_R5_ALPHA (20 << 10)
+# define R200_TXA_ARG_C_R5_BLUE (21 << 10)
+# define R200_TXA_ARG_C_TFACTOR1_ALPHA (26 << 10)
+# define R200_TXA_ARG_C_TFACTOR1_BLUE (27 << 10)
+# define R200_TXA_ARG_C_MASK (31 << 10)
+# define R200_TXA_ARG_C_SHIFT 10
+# define R200_TXA_COMP_ARG_A (1 << 16)
+# define R200_TXA_COMP_ARG_A_SHIFT (16)
+# define R200_TXA_BIAS_ARG_A (1 << 17)
+# define R200_TXA_SCALE_ARG_A (1 << 18)
+# define R200_TXA_NEG_ARG_A (1 << 19)
+# define R200_TXA_COMP_ARG_B (1 << 20)
+# define R200_TXA_COMP_ARG_B_SHIFT (20)
+# define R200_TXA_BIAS_ARG_B (1 << 21)
+# define R200_TXA_SCALE_ARG_B (1 << 22)
+# define R200_TXA_NEG_ARG_B (1 << 23)
+# define R200_TXA_COMP_ARG_C (1 << 24)
+# define R200_TXA_COMP_ARG_C_SHIFT (24)
+# define R200_TXA_BIAS_ARG_C (1 << 25)
+# define R200_TXA_SCALE_ARG_C (1 << 26)
+# define R200_TXA_NEG_ARG_C (1 << 27)
+# define R200_TXA_OP_MADD (0 << 28)
+# define R200_TXA_OP_CND0 (2 << 28)
+# define R200_TXA_OP_LERP (3 << 28)
+# define R200_TXA_OP_CONDITIONAL (6 << 28)
+# define R200_TXA_OP_MASK (7 << 28)
+#define R200_PP_TXABLEND2_0 0x2f0c
+# define R200_TXA_TFACTOR_SEL_SHIFT 0
+# define R200_TXA_TFACTOR_SEL_MASK 0x7
+# define R200_TXA_TFACTOR1_SEL_SHIFT 4
+# define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4)
+# define R200_TXA_SCALE_SHIFT 8
+# define R200_TXA_SCALE_MASK (7 << 8)
+# define R200_TXA_SCALE_1X (0 << 8)
+# define R200_TXA_SCALE_2X (1 << 8)
+# define R200_TXA_SCALE_4X (2 << 8)
+# define R200_TXA_SCALE_8X (3 << 8)
+# define R200_TXA_SCALE_INV2 (5 << 8)
+# define R200_TXA_SCALE_INV4 (6 << 8)
+# define R200_TXA_SCALE_INV8 (7 << 8)
+# define R200_TXA_CLAMP_SHIFT 12
+# define R200_TXA_CLAMP_MASK (3 << 12)
+# define R200_TXA_CLAMP_WRAP (0 << 12)
+# define R200_TXA_CLAMP_0_1 (1 << 12)
+# define R200_TXA_CLAMP_8_8 (2 << 12)
+# define R200_TXA_OUTPUT_REG_MASK (7 << 16)
+# define R200_TXA_OUTPUT_REG_NONE (0 << 16)
+# define R200_TXA_OUTPUT_REG_R0 (1 << 16)
+# define R200_TXA_OUTPUT_REG_R1 (2 << 16)
+# define R200_TXA_OUTPUT_REG_R2 (3 << 16)
+# define R200_TXA_OUTPUT_REG_R3 (4 << 16)
+# define R200_TXA_OUTPUT_REG_R4 (5 << 16)
+# define R200_TXA_OUTPUT_REG_R5 (6 << 16)
+# define R200_TXA_DOT_ALPHA (1 << 20)
+# define R200_TXA_REPL_NORMAL 0
+# define R200_TXA_REPL_RED 1
+# define R200_TXA_REPL_GREEN 2
+# define R200_TXA_REPL_ARG_A_SHIFT 26
+# define R200_TXA_REPL_ARG_A_MASK (3 << 26)
+# define R200_TXA_REPL_ARG_B_SHIFT 28
+# define R200_TXA_REPL_ARG_B_MASK (3 << 28)
+# define R200_TXA_REPL_ARG_C_SHIFT 30
+# define R200_TXA_REPL_ARG_C_MASK (3 << 30)
+
+#define R200_SE_VTX_FMT_0 0x2088
+# define R200_VTX_XY 0 /* always have xy */
+# define R200_VTX_Z0 (1<<0)
+# define R200_VTX_W0 (1<<1)
+# define R200_VTX_WEIGHT_COUNT_SHIFT (2)
+# define R200_VTX_PV_MATRIX_SEL (1<<5)
+# define R200_VTX_N0 (1<<6)
+# define R200_VTX_POINT_SIZE (1<<7)
+# define R200_VTX_DISCRETE_FOG (1<<8)
+# define R200_VTX_SHININESS_0 (1<<9)
+# define R200_VTX_SHININESS_1 (1<<10)
+# define R200_VTX_COLOR_NOT_PRESENT 0
+# define R200_VTX_PK_RGBA 1
+# define R200_VTX_FP_RGB 2
+# define R200_VTX_FP_RGBA 3
+# define R200_VTX_COLOR_MASK 3
+# define R200_VTX_COLOR_0_SHIFT 11
+# define R200_VTX_COLOR_1_SHIFT 13
+# define R200_VTX_COLOR_2_SHIFT 15
+# define R200_VTX_COLOR_3_SHIFT 17
+# define R200_VTX_COLOR_4_SHIFT 19
+# define R200_VTX_COLOR_5_SHIFT 21
+# define R200_VTX_COLOR_6_SHIFT 23
+# define R200_VTX_COLOR_7_SHIFT 25
+# define R200_VTX_XY1 (1<<28)
+# define R200_VTX_Z1 (1<<29)
+# define R200_VTX_W1 (1<<30)
+# define R200_VTX_N1 (1<<31)
+#define R200_SE_VTX_FMT_1 0x208c
+# define R200_VTX_TEX0_COMP_CNT_SHIFT 0
+# define R200_VTX_TEX1_COMP_CNT_SHIFT 3
+# define R200_VTX_TEX2_COMP_CNT_SHIFT 6
+# define R200_VTX_TEX3_COMP_CNT_SHIFT 9
+# define R200_VTX_TEX4_COMP_CNT_SHIFT 12
+# define R200_VTX_TEX5_COMP_CNT_SHIFT 15
+
+#define R200_SE_TCL_OUTPUT_VTX_FMT_0 0x2090
+#define R200_SE_TCL_OUTPUT_VTX_FMT_1 0x2094
+#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250
+# define R200_OUTPUT_XYZW (1<<0)
+# define R200_OUTPUT_COLOR_0 (1<<8)
+# define R200_OUTPUT_COLOR_1 (1<<9)
+# define R200_OUTPUT_TEX_0 (1<<16)
+# define R200_OUTPUT_TEX_1 (1<<17)
+# define R200_OUTPUT_TEX_2 (1<<18)
+# define R200_OUTPUT_TEX_3 (1<<19)
+# define R200_OUTPUT_TEX_4 (1<<20)
+# define R200_OUTPUT_TEX_5 (1<<21)
+# define R200_OUTPUT_TEX_MASK (0x3f<<16)
+# define R200_OUTPUT_DISCRETE_FOG (1<<24)
+# define R200_OUTPUT_PT_SIZE (1<<25)
+# define R200_FORCE_INORDER_PROC (1<<31)
+#define R200_PP_CNTL_X 0x2cc4
+#define R200_PP_TXMULTI_CTL_0 0x2c1c
+#define R200_SE_VTX_STATE_CNTL 0x2180
+# define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16)
/* Registers for CP and Microcode Engine */
#define RADEON_CP_ME_RAM_ADDR 0x07d4
@@ -2013,6 +2615,7 @@
#define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900
#define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00
#define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00
+#define R200_CP_PACKET3_3D_DRAW_IMMD_2 0xc0003500
#define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00
#define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100
#define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200
diff --git a/src/radeon_render.c b/src/radeon_render.c
new file mode 100644
index 00000000..145b6538
--- /dev/null
+++ b/src/radeon_render.c
@@ -0,0 +1,992 @@
+
+#include "dixstruct.h"
+
+#include "xaa.h"
+#include "xaalocal.h"
+
+#ifndef RENDER_GENERIC_HELPER
+#define RENDER_GENERIC_HELPER
+
+static void RadeonInit3DEngineMMIO(ScrnInfoPtr pScrn);
+#ifdef XF86DRI
+static void RadeonInit3DEngineCP(ScrnInfoPtr pScrn);
+#endif
+
+struct blendinfo {
+ Bool dst_alpha;
+ Bool src_alpha;
+ CARD32 blend_cntl;
+};
+
+/* The first part of blend_cntl corresponds to Fa from the render "protocol"
+ * document, and the second part to Fb.
+ */
+static const struct blendinfo RadeonBlendOp[] = {
+ /* Clear */
+ {0, 0, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* Src */
+ {0, 0, RADEON_SRC_BLEND_GL_ONE |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* Dst */
+ {0, 0, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_ONE},
+ /* Over */
+ {0, 1, RADEON_SRC_BLEND_GL_ONE |
+ RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA},
+ /* OverReverse */
+ {1, 0, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA |
+ RADEON_DST_BLEND_GL_ONE},
+ /* In */
+ {1, 0, RADEON_SRC_BLEND_GL_DST_ALPHA |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* InReverse */
+ {0, 1, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_SRC_ALPHA},
+ /* Out */
+ {1, 0, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* OutReverse */
+ {0, 1, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA},
+ /* Atop */
+ {1, 1, RADEON_SRC_BLEND_GL_DST_ALPHA |
+ RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA},
+ /* AtopReverse */
+ {1, 1, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA |
+ RADEON_DST_BLEND_GL_SRC_ALPHA},
+ /* Xor */
+ {1, 1, RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA |
+ RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA},
+ /* Add */
+ {0, 0, RADEON_SRC_BLEND_GL_ONE |
+ RADEON_DST_BLEND_GL_ONE},
+ /* Saturate */
+ {1, 1, RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE |
+ RADEON_DST_BLEND_GL_ONE},
+ {0, 0, 0},
+ {0, 0, 0},
+ /* DisjointClear */
+ {0, 0, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* DisjointSrc */
+ {0, 0, RADEON_SRC_BLEND_GL_ONE |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* DisjointDst */
+ {0, 0, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_ONE},
+ /* DisjointOver unsupported */
+ {0, 0, 0},
+ /* DisjointOverReverse */
+ {1, 1, RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE |
+ RADEON_DST_BLEND_GL_ONE},
+ /* DisjointIn unsupported */
+ {0, 0, 0},
+ /* DisjointInReverse unsupported */
+ {0, 0, 0},
+ /* DisjointOut unsupported */
+ {1, 1, RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* DisjointOutReverse unsupported */
+ {0, 0, 0},
+ /* DisjointAtop unsupported */
+ {0, 0, 0},
+ /* DisjointAtopReverse unsupported */
+ {0, 0, 0},
+ /* DisjointXor unsupported */
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ /* ConjointClear */
+ {0, 0, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* ConjointSrc */
+ {0, 0, RADEON_SRC_BLEND_GL_ONE |
+ RADEON_DST_BLEND_GL_ZERO},
+ /* ConjointDst */
+ {0, 0, RADEON_SRC_BLEND_GL_ZERO |
+ RADEON_DST_BLEND_GL_ONE},
+};
+#define RadeonOpMax (sizeof(RadeonBlendOp) / sizeof(RadeonBlendOp[0]))
+
+/* Note on texture formats:
+ * TXFORMAT_Y8 expands to (Y,Y,Y,1). TXFORMAT_I8 expands to (I,I,I,I)
+ * The RADEON and R200 TXFORMATS we use are the same on r100/r200.
+ */
+
+static CARD32 RADEONTextureFormats[] = {
+ PICT_a8r8g8b8,
+ PICT_a8,
+ PICT_x8r8g8b8,
+ PICT_r5g6b5,
+ PICT_a1r5g5b5,
+ PICT_x1r5g5b5,
+ 0
+};
+
+static CARD32 RADEONDstFormats[] = {
+ PICT_a8r8g8b8,
+ PICT_x8r8g8b8,
+ PICT_r5g6b5,
+ PICT_a1r5g5b5,
+ PICT_x1r5g5b5,
+ 0
+};
+
+static CARD32
+RadeonGetTextureFormat(CARD32 format)
+{
+ switch (format) {
+ case PICT_a8r8g8b8:
+ return RADEON_TXFORMAT_ARGB8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
+ case PICT_a8:
+ return RADEON_TXFORMAT_I8 | RADEON_TXFORMAT_ALPHA_IN_MAP;
+ case PICT_x8r8g8b8:
+ return RADEON_TXFORMAT_ARGB8888;
+ case PICT_r5g6b5:
+ return RADEON_TXFORMAT_RGB565;
+ case PICT_a1r5g5b5:
+ return RADEON_TXFORMAT_ARGB1555 | RADEON_TXFORMAT_ALPHA_IN_MAP;
+ case PICT_x1r5g5b5:
+ return RADEON_TXFORMAT_ARGB1555;
+ default:
+ return 0;
+ }
+}
+
+static CARD32
+RadeonGetColorFormat(CARD32 format)
+{
+ switch (format) {
+ case PICT_a8r8g8b8:
+ case PICT_x8r8g8b8:
+ return RADEON_COLOR_FORMAT_ARGB8888;
+ case PICT_r5g6b5:
+ return RADEON_COLOR_FORMAT_RGB565;
+ case PICT_a1r5g5b5:
+ case PICT_x1r5g5b5:
+ return RADEON_COLOR_FORMAT_ARGB1555;
+ default:
+ return 0;
+ }
+}
+
+/* Returns a RADEON_RB3D_BLENDCNTL value, or 0 if the operation is not
+ * supported
+ */
+static CARD32
+RadeonGetBlendCntl(CARD8 op, CARD32 dstFormat)
+{
+ CARD32 blend_cntl;
+
+ if (op >= RadeonOpMax || RadeonBlendOp[op].blend_cntl == 0)
+ return 0;
+
+ blend_cntl = RadeonBlendOp[op].blend_cntl;
+
+ if (RadeonBlendOp[op].dst_alpha && !PICT_FORMAT_A(dstFormat)) {
+ CARD32 srcblend = blend_cntl & RADEON_SRC_BLEND_MASK;
+
+ /* If there's no destination alpha channel, we need to wire the blending
+ * to treat the alpha channel as always 1.
+ */
+ if (srcblend == RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA ||
+ srcblend == RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE)
+ blend_cntl = (blend_cntl & ~RADEON_SRC_BLEND_MASK) |
+ RADEON_SRC_BLEND_GL_ZERO;
+ else if (srcblend == RADEON_SRC_BLEND_GL_DST_ALPHA)
+ blend_cntl = (blend_cntl & ~RADEON_SRC_BLEND_MASK) |
+ RADEON_SRC_BLEND_GL_ONE;
+ }
+
+ return blend_cntl;
+}
+
+static __inline__ CARD32 F_TO_DW(float val)
+{
+ union {
+ float f;
+ CARD32 l;
+ } tmp;
+ tmp.f = val;
+ return tmp.l;
+}
+
+/* Compute log base 2 of val. */
+static __inline__ int
+ATILog2(int val)
+{
+ int bits;
+
+ for (bits = 0; val != 0; val >>= 1, ++bits)
+ ;
+ return bits - 1;
+}
+
+static void RadeonInit3DEngine(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR (pScrn);
+
+#ifdef XF86DRI
+ if (info->directRenderingEnabled) {
+ RADEONSAREAPrivPtr pSAREAPriv;
+
+ pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+ pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
+ RadeonInit3DEngineCP(pScrn);
+ } else
+#endif
+ RadeonInit3DEngineMMIO(pScrn);
+
+ info->RenderInited3D = TRUE;
+}
+
+static void
+RemoveLinear (FBLinearPtr linear)
+{
+ RADEONInfoPtr info = (RADEONInfoPtr)(linear->devPrivate.ptr);
+
+ info->RenderTex = NULL;
+}
+
+static void
+RenderCallback (ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if ((currentTime.milliseconds > info->RenderTimeout) && info->RenderTex) {
+ xf86FreeOffscreenLinear(info->RenderTex);
+ info->RenderTex = NULL;
+ }
+
+ if (!info->RenderTex)
+ info->RenderCallback = NULL;
+}
+
+static Bool
+AllocateLinear (
+ ScrnInfoPtr pScrn,
+ int sizeNeeded
+){
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ info->RenderTimeout = currentTime.milliseconds + 30000;
+ info->RenderCallback = RenderCallback;
+
+ if (info->RenderTex) {
+ if (info->RenderTex->size >= sizeNeeded)
+ return TRUE;
+ else {
+ if (xf86ResizeOffscreenLinear(info->RenderTex, sizeNeeded))
+ return TRUE;
+
+ xf86FreeOffscreenLinear(info->RenderTex);
+ info->RenderTex = NULL;
+ }
+ }
+
+ info->RenderTex = xf86AllocateOffscreenLinear(pScrn->pScreen, sizeNeeded, 32,
+ NULL, RemoveLinear, info);
+
+ return (info->RenderTex != NULL);
+}
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+static Bool RADEONSetupRenderByteswap(ScrnInfoPtr pScrn, int tex_bytepp)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ /* Set up byte swapping for the framebuffer aperture as needed */
+ switch (tex_bytepp) {
+ case 1:
+ OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl &
+ ~(RADEON_NONSURF_AP0_SWP_32BPP
+ | RADEON_NONSURF_AP0_SWP_16BPP));
+ break;
+ case 2:
+ OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl &
+ ~RADEON_NONSURF_AP0_SWP_32BPP)
+ | RADEON_NONSURF_AP0_SWP_16BPP);
+ break;
+ case 4:
+ OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl &
+ ~RADEON_NONSURF_AP0_SWP_16BPP)
+ | RADEON_NONSURF_AP0_SWP_32BPP);
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: Don't know what to do for "
+ "tex_bytepp == %d!\n", __func__, tex_bytepp);
+ return FALSE;
+ }
+}
+
+static void RADEONRestoreByteswap(RADEONInfoPtr info)
+{
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl);
+}
+#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */
+
+#endif /* RENDER_GENERIC_HELPER */
+
+#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
+#error Cannot define both MMIO and CP acceleration!
+#endif
+
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
+#else
+#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix
+#endif
+
+#ifdef ACCEL_MMIO
+#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
+#else
+#ifdef ACCEL_CP
+#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
+#else
+#error No accel type defined!
+#endif
+#endif
+
+
+static void FUNC_NAME(RadeonInit3DEngine)(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ ACCEL_PREAMBLE();
+
+ if (info->ChipFamily >= CHIP_FAMILY_R300) {
+ /* Unimplemented */
+ } else if ((info->ChipFamily == CHIP_FAMILY_RV250) ||
+ (info->ChipFamily == CHIP_FAMILY_RV280) ||
+ (info->ChipFamily == CHIP_FAMILY_RS300) ||
+ (info->ChipFamily == CHIP_FAMILY_R200)) {
+
+ BEGIN_ACCEL(7);
+ if (info->ChipFamily == CHIP_FAMILY_RS300) {
+ OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS);
+ } else {
+ OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, 0);
+ }
+ OUT_ACCEL_REG(R200_PP_CNTL_X, 0);
+ OUT_ACCEL_REG(R200_PP_TXMULTI_CTL_0, 0);
+ OUT_ACCEL_REG(R200_SE_VTX_STATE_CNTL, 0);
+ OUT_ACCEL_REG(R200_RE_CNTL, 0x0);
+ /* XXX: correct? Want it to be like RADEON_VTX_ST?_NONPARAMETRIC */
+ OUT_ACCEL_REG(R200_SE_VTE_CNTL, R200_VTX_ST_DENORMALIZED);
+ OUT_ACCEL_REG(R200_SE_VAP_CNTL, R200_VAP_FORCE_W_TO_ONE |
+ R200_VAP_VF_MAX_VTX_NUM);
+ FINISH_ACCEL();
+ } else {
+ BEGIN_ACCEL(2);
+ if ((info->ChipFamily == CHIP_FAMILY_RADEON) ||
+ (info->ChipFamily == CHIP_FAMILY_RV200))
+ OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, 0);
+ else
+ OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS);
+ OUT_ACCEL_REG(RADEON_SE_COORD_FMT,
+ RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
+ RADEON_VTX_ST0_NONPARAMETRIC |
+ RADEON_VTX_ST1_NONPARAMETRIC |
+ RADEON_TEX1_W_ROUTING_USE_W0);
+ FINISH_ACCEL();
+ }
+
+ BEGIN_ACCEL(3);
+ OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0);
+ OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, 0x07ff07ff);
+ OUT_ACCEL_REG(RADEON_SE_CNTL, RADEON_DIFFUSE_SHADE_GOURAUD |
+ RADEON_BFACE_SOLID |
+ RADEON_FFACE_SOLID |
+ RADEON_VTX_PIX_CENTER_OGL |
+ RADEON_ROUND_MODE_ROUND |
+ RADEON_ROUND_PREC_4TH_PIX);
+ FINISH_ACCEL();
+}
+
+static Bool FUNC_NAME(R100SetupTexture)(
+ ScrnInfoPtr pScrn,
+ CARD32 format,
+ CARD8 *src,
+ int src_pitch,
+ int width,
+ int height,
+ int flags)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD8 *dst;
+ CARD32 tex_size = 0, txformat;
+ int dst_pitch, offset, size, i, tex_bytepp;
+ ACCEL_PREAMBLE();
+
+ if ((width > 2048) || (height > 2048))
+ return FALSE;
+
+ txformat = RadeonGetTextureFormat(format);
+ tex_bytepp = PICT_FORMAT_BPP(format) >> 3;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ if (!RADEONSetupRenderByteswap(pScrn, tex_bytepp)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: RADEONSetupRenderByteswap() "
+ "failed!\n", __func__);
+ return FALSE;
+ }
+#endif
+
+ dst_pitch = (width * tex_bytepp + 31) & ~31;
+ size = dst_pitch * height;
+
+ if (!AllocateLinear(pScrn, size))
+ return FALSE;
+
+ if (flags & XAA_RENDER_REPEAT) {
+ txformat |= ATILog2(width) << RADEON_TXFORMAT_WIDTH_SHIFT;
+ txformat |= ATILog2(height) << RADEON_TXFORMAT_HEIGHT_SHIFT;
+ } else {
+ tex_size = ((height - 1) << 16) | (width - 1);
+ txformat |= RADEON_TXFORMAT_NON_POWER2;
+ }
+
+ offset = info->RenderTex->offset * pScrn->bitsPerPixel / 8;
+
+ /* Upload texture to card. Should use ImageWrite to avoid syncing. */
+ i = height;
+ dst = (CARD8*)(info->FB + offset);
+
+ if (info->accel->NeedToSync)
+ info->accel->Sync(pScrn);
+
+ while(i--) {
+ memcpy(dst, src, width * tex_bytepp);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ RADEONRestoreByteswap(info);
+#endif
+
+ BEGIN_ACCEL(5);
+ OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat);
+ OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_0, tex_size);
+ OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_0, dst_pitch - 32);
+ OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, offset + info->fbLocation +
+ pScrn->fbOffset);
+ OUT_ACCEL_REG(RADEON_PP_TXFILTER_0, RADEON_MAG_FILTER_LINEAR |
+ RADEON_MIN_FILTER_LINEAR |
+ RADEON_CLAMP_S_WRAP |
+ RADEON_CLAMP_T_WRAP);
+ FINISH_ACCEL();
+
+ return TRUE;
+}
+
+static Bool
+FUNC_NAME(R100SetupForCPUToScreenAlphaTexture) (
+ ScrnInfoPtr pScrn,
+ int op,
+ CARD16 red,
+ CARD16 green,
+ CARD16 blue,
+ CARD16 alpha,
+ CARD32 maskFormat,
+ CARD32 dstFormat,
+ CARD8 *alphaPtr,
+ int alphaPitch,
+ int width,
+ int height,
+ int flags
+)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 colorformat, srccolor, blend_cntl;
+ ACCEL_PREAMBLE();
+
+ blend_cntl = RadeonGetBlendCntl(op, dstFormat);
+ if (blend_cntl == 0)
+ return FALSE;
+
+ if (!info->RenderInited3D)
+ RadeonInit3DEngine(pScrn);
+
+ if (!FUNC_NAME(R100SetupTexture)(pScrn, maskFormat, alphaPtr, alphaPitch,
+ width, height, flags))
+ return FALSE;
+
+ colorformat = RadeonGetColorFormat(dstFormat);
+
+ srccolor = ((alpha & 0xff00) << 16) | ((red & 0xff00) << 8) | (blue >> 8) |
+ (green & 0xff00);
+
+ BEGIN_ACCEL(8);
+ OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE);
+ OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth);
+ OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE |
+ RADEON_TEX_BLEND_0_ENABLE);
+ OUT_ACCEL_REG(RADEON_PP_TFACTOR_0, srccolor);
+ OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0, RADEON_COLOR_ARG_A_TFACTOR_COLOR |
+ RADEON_COLOR_ARG_B_T0_ALPHA);
+ OUT_ACCEL_REG(RADEON_PP_TXABLEND_0, RADEON_ALPHA_ARG_A_TFACTOR_ALPHA |
+ RADEON_ALPHA_ARG_B_T0_ALPHA);
+ OUT_ACCEL_REG(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY |
+ RADEON_SE_VTX_FMT_ST0);
+ OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blend_cntl);
+ FINISH_ACCEL();
+
+ return TRUE;
+}
+
+
+static Bool
+FUNC_NAME(R100SetupForCPUToScreenTexture) (
+ ScrnInfoPtr pScrn,
+ int op,
+ CARD32 srcFormat,
+ CARD32 dstFormat,
+ CARD8 *texPtr,
+ int texPitch,
+ int width,
+ int height,
+ int flags
+)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 colorformat, blend_cntl;
+ ACCEL_PREAMBLE();
+
+ blend_cntl = RadeonGetBlendCntl(op, dstFormat);
+ if (blend_cntl == 0)
+ return FALSE;
+
+ if (!info->RenderInited3D)
+ RadeonInit3DEngine(pScrn);
+
+ if (!FUNC_NAME(R100SetupTexture)(pScrn, srcFormat, texPtr, texPitch, width,
+ height, flags))
+ return FALSE;
+
+ colorformat = RadeonGetColorFormat(dstFormat);
+
+ BEGIN_ACCEL(7);
+ OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE);
+ OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth);
+ OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE |
+ RADEON_TEX_BLEND_0_ENABLE);
+ if (srcFormat != PICT_a8)
+ OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0, RADEON_COLOR_ARG_C_T0_COLOR);
+ else
+ OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0, RADEON_COLOR_ARG_C_ZERO);
+ OUT_ACCEL_REG(RADEON_PP_TXABLEND_0, RADEON_ALPHA_ARG_C_T0_ALPHA);
+ OUT_ACCEL_REG(RADEON_SE_VTX_FMT, RADEON_SE_VTX_FMT_XY |
+ RADEON_SE_VTX_FMT_ST0);
+ OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blend_cntl);
+ FINISH_ACCEL();
+
+ return TRUE;
+}
+
+
+static void
+FUNC_NAME(R100SubsequentCPUToScreenTexture) (
+ ScrnInfoPtr pScrn,
+ int dstx,
+ int dsty,
+ int srcx,
+ int srcy,
+ int width,
+ int height
+)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int byteshift;
+ CARD32 fboffset;
+ float l, t, r, b, fl, fr, ft, fb;
+
+ ACCEL_PREAMBLE();
+
+ /* Note: we can't simply set up the 3D surface at the same location as the
+ * front buffer, because the 2048x2048 limit on coordinates may be smaller
+ * than the (MergedFB) screen.
+ */
+ byteshift = (pScrn->bitsPerPixel >> 4);
+ fboffset = (info->fbLocation + pScrn->fbOffset +
+ ((pScrn->displayWidth * dsty + dstx) << byteshift)) & ~15;
+ l = ((dstx << byteshift) % 16) >> byteshift;
+ t = 0.0;
+ r = width + l;
+ b = height;
+ fl = srcx;
+ fr = srcx + width;
+ ft = srcy;
+ fb = srcy + height;
+
+#ifdef ACCEL_CP
+ BEGIN_RING(23);
+
+ OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset);
+
+ OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, 17));
+ /* RADEON_SE_VTX_FMT */
+ OUT_RING(RADEON_CP_VC_FRMT_XY |
+ RADEON_CP_VC_FRMT_ST0);
+ /* SE_VF_CNTL */
+ OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+ RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+ RADEON_CP_VC_CNTL_MAOS_ENABLE |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+ (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(t));
+ OUT_RING(F_TO_DW(fl));
+ OUT_RING(F_TO_DW(ft));
+
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(t));
+ OUT_RING(F_TO_DW(fr));
+ OUT_RING(F_TO_DW(ft));
+
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(b));
+ OUT_RING(F_TO_DW(fr));
+ OUT_RING(F_TO_DW(fb));
+
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(b));
+ OUT_RING(F_TO_DW(fl));
+ OUT_RING(F_TO_DW(fb));
+
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+
+ ADVANCE_RING();
+#else
+ BEGIN_ACCEL(19);
+
+ OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset);
+
+ OUT_ACCEL_REG(RADEON_SE_VF_CNTL, RADEON_VF_PRIM_TYPE_TRIANGLE_FAN |
+ RADEON_VF_PRIM_WALK_DATA |
+ RADEON_VF_RADEON_MODE |
+ (4 << RADEON_VF_NUM_VERTICES_SHIFT));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fl));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(ft));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fr));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(ft));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fr));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fb));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fl));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fb));
+
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+ FINISH_ACCEL();
+#endif
+
+}
+
+static Bool FUNC_NAME(R200SetupTexture)(
+ ScrnInfoPtr pScrn,
+ CARD32 format,
+ CARD8 *src,
+ int src_pitch,
+ int width,
+ int height,
+ int flags)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD8 *dst;
+ CARD32 tex_size = 0, txformat;
+ int dst_pitch, offset, size, i, tex_bytepp;
+ ACCEL_PREAMBLE();
+
+ if ((width > 2048) || (height > 2048))
+ return FALSE;
+
+ txformat = RadeonGetTextureFormat(format);
+ tex_bytepp = PICT_FORMAT_BPP(format) >> 3;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ if (!RADEONSetupRenderByteswap(pScrn, tex_bytepp)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: RADEONSetupRenderByteswap() "
+ "failed!\n", __func__);
+ return FALSE;
+ }
+#endif
+
+ dst_pitch = (width * tex_bytepp + 31) & ~31;
+ size = dst_pitch * height;
+
+ if (!AllocateLinear(pScrn, size))
+ return FALSE;
+
+ if (flags & XAA_RENDER_REPEAT) {
+ txformat |= ATILog2(width) << R200_TXFORMAT_WIDTH_SHIFT;
+ txformat |= ATILog2(height) << R200_TXFORMAT_HEIGHT_SHIFT;
+ } else {
+ tex_size = ((height - 1) << 16) | (width - 1);
+ txformat |= RADEON_TXFORMAT_NON_POWER2;
+ }
+
+ offset = info->RenderTex->offset * pScrn->bitsPerPixel / 8;
+
+ /* Upload texture to card. Should use ImageWrite to avoid syncing. */
+ i = height;
+ dst = (CARD8*)(info->FB + offset);
+ if (info->accel->NeedToSync)
+ info->accel->Sync(pScrn);
+
+ while(i--) {
+ memcpy(dst, src, width * tex_bytepp);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ RADEONRestoreByteswap(info);
+#endif
+
+ BEGIN_ACCEL(6);
+ OUT_ACCEL_REG(R200_PP_TXFORMAT_0, txformat);
+ OUT_ACCEL_REG(R200_PP_TXFORMAT_X_0, 0);
+ OUT_ACCEL_REG(R200_PP_TXSIZE_0, tex_size);
+ OUT_ACCEL_REG(R200_PP_TXPITCH_0, dst_pitch - 32);
+ OUT_ACCEL_REG(R200_PP_TXOFFSET_0, offset + info->fbLocation +
+ pScrn->fbOffset);
+ OUT_ACCEL_REG(R200_PP_TXFILTER_0, R200_MAG_FILTER_NEAREST |
+ R200_MIN_FILTER_NEAREST |
+ R200_CLAMP_S_WRAP |
+ R200_CLAMP_T_WRAP);
+ FINISH_ACCEL();
+
+ return TRUE;
+}
+
+static Bool
+FUNC_NAME(R200SetupForCPUToScreenAlphaTexture) (
+ ScrnInfoPtr pScrn,
+ int op,
+ CARD16 red,
+ CARD16 green,
+ CARD16 blue,
+ CARD16 alpha,
+ CARD32 maskFormat,
+ CARD32 dstFormat,
+ CARD8 *alphaPtr,
+ int alphaPitch,
+ int width,
+ int height,
+ int flags
+)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 colorformat, srccolor, blend_cntl;
+ ACCEL_PREAMBLE();
+
+ blend_cntl = RadeonGetBlendCntl(op, dstFormat);
+ if (blend_cntl == 0)
+ return FALSE;
+
+ if (!info->RenderInited3D)
+ RadeonInit3DEngine(pScrn);
+
+ if (!FUNC_NAME(R200SetupTexture)(pScrn, maskFormat, alphaPtr, alphaPitch,
+ width, height, flags))
+ return FALSE;
+
+ colorformat = RadeonGetColorFormat(dstFormat);
+
+ srccolor = ((alpha & 0xff00) << 16) | ((red & 0xff00) << 8) | (blue >> 8) |
+ (green & 0xff00);
+
+ BEGIN_ACCEL(11);
+ OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE);
+ OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth);
+ OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE |
+ RADEON_TEX_BLEND_0_ENABLE);
+ OUT_ACCEL_REG(R200_PP_TFACTOR_0, srccolor);
+ OUT_ACCEL_REG(R200_PP_TXCBLEND_0, R200_TXC_ARG_A_TFACTOR_COLOR |
+ R200_TXC_ARG_B_R0_ALPHA);
+ OUT_ACCEL_REG(R200_PP_TXCBLEND2_0, R200_TXC_OUTPUT_REG_R0);
+ OUT_ACCEL_REG(R200_PP_TXABLEND_0, R200_TXA_ARG_A_TFACTOR_ALPHA |
+ R200_TXA_ARG_B_R0_ALPHA);
+ OUT_ACCEL_REG(R200_PP_TXABLEND2_0, R200_TXA_OUTPUT_REG_R0);
+ OUT_ACCEL_REG(R200_SE_VTX_FMT_0, 0);
+ OUT_ACCEL_REG(R200_SE_VTX_FMT_1, (2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
+ OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blend_cntl);
+ FINISH_ACCEL();
+
+ return TRUE;
+}
+
+static Bool
+FUNC_NAME(R200SetupForCPUToScreenTexture) (
+ ScrnInfoPtr pScrn,
+ int op,
+ CARD32 srcFormat,
+ CARD32 dstFormat,
+ CARD8 *texPtr,
+ int texPitch,
+ int width,
+ int height,
+ int flags
+)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ CARD32 colorformat, blend_cntl;
+ ACCEL_PREAMBLE();
+
+ blend_cntl = RadeonGetBlendCntl(op, dstFormat);
+ if (blend_cntl == 0)
+ return FALSE;
+
+ if (!info->RenderInited3D)
+ RadeonInit3DEngine(pScrn);
+
+ if (!FUNC_NAME(R200SetupTexture)(pScrn, srcFormat, texPtr, texPitch, width,
+ height, flags))
+ return FALSE;
+
+ colorformat = RadeonGetColorFormat(dstFormat);
+
+ BEGIN_ACCEL(10);
+ OUT_ACCEL_REG(RADEON_RB3D_CNTL, colorformat | RADEON_ALPHA_BLEND_ENABLE);
+ OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, pScrn->displayWidth);
+ OUT_ACCEL_REG(RADEON_PP_CNTL, RADEON_TEX_0_ENABLE |
+ RADEON_TEX_BLEND_0_ENABLE);
+ if (srcFormat != PICT_a8)
+ OUT_ACCEL_REG(R200_PP_TXCBLEND_0, R200_TXC_ARG_C_R0_COLOR);
+ else
+ OUT_ACCEL_REG(R200_PP_TXCBLEND_0, R200_TXC_ARG_C_ZERO);
+ OUT_ACCEL_REG(R200_PP_TXCBLEND2_0, R200_TXC_OUTPUT_REG_R0);
+ OUT_ACCEL_REG(R200_PP_TXABLEND_0, R200_TXA_ARG_C_R0_ALPHA);
+ OUT_ACCEL_REG(R200_PP_TXABLEND2_0, R200_TXA_OUTPUT_REG_R0);
+ OUT_ACCEL_REG(R200_SE_VTX_FMT_0, 0);
+ OUT_ACCEL_REG(R200_SE_VTX_FMT_1, (2 << R200_VTX_TEX0_COMP_CNT_SHIFT));
+ OUT_ACCEL_REG(RADEON_RB3D_BLENDCNTL, blend_cntl);
+ FINISH_ACCEL();
+
+ return TRUE;
+}
+
+static void
+FUNC_NAME(R200SubsequentCPUToScreenTexture) (
+ ScrnInfoPtr pScrn,
+ int dstx,
+ int dsty,
+ int srcx,
+ int srcy,
+ int width,
+ int height
+)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int byteshift;
+ CARD32 fboffset;
+ float l, t, r, b, fl, fr, ft, fb;
+ ACCEL_PREAMBLE();
+
+ /* Note: we can't simply set up the 3D surface at the same location as the
+ * front buffer, because the 2048x2048 limit on coordinates may be smaller
+ * than the (MergedFB) screen.
+ */
+ byteshift = (pScrn->bitsPerPixel >> 4);
+ fboffset = (info->fbLocation + pScrn->fbOffset + ((pScrn->displayWidth *
+ dsty + dstx) << byteshift)) & ~15;
+ l = ((dstx << byteshift) % 16) >> byteshift;
+ t = 0.0;
+ r = width + l;
+ b = height;
+ fl = srcx;
+ fr = srcx + width;
+ ft = srcy;
+ fb = srcy + height;
+
+#ifdef ACCEL_CP
+ BEGIN_RING(24);
+
+ OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset);
+
+ OUT_RING(CP_PACKET3(R200_CP_PACKET3_3D_DRAW_IMMD_2, 16));
+ /* RADEON_SE_VF_CNTL */
+ OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+ RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+ (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(t));
+ OUT_RING(F_TO_DW(fl));
+ OUT_RING(F_TO_DW(ft));
+
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(t));
+ OUT_RING(F_TO_DW(fr));
+ OUT_RING(F_TO_DW(ft));
+
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(b));
+ OUT_RING(F_TO_DW(fr));
+ OUT_RING(F_TO_DW(fb));
+
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(b));
+ OUT_RING(F_TO_DW(fl));
+ OUT_RING(F_TO_DW(fb));
+
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+
+ ADVANCE_RING();
+#else
+ BEGIN_ACCEL(19);
+
+ /* Note: we can't simply setup 3D surface at the same location as the front buffer,
+ some apps may draw offscreen pictures out of the limitation of radeon 3D surface.
+ */
+ OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset);
+
+ OUT_ACCEL_REG(RADEON_SE_VF_CNTL, (RADEON_VF_PRIM_TYPE_QUAD_LIST |
+ RADEON_VF_PRIM_WALK_DATA |
+ 4 << RADEON_VF_NUM_VERTICES_SHIFT));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fl));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(ft));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fr));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(ft));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fr));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fb));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fl));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(fb));
+
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+
+ FINISH_ACCEL();
+#endif
+}
+
+#undef FUNC_NAME
+
diff --git a/src/radeon_sarea.h b/src/radeon_sarea.h
index 95db1f37..556fca6f 100644
--- a/src/radeon_sarea.h
+++ b/src/radeon_sarea.h
@@ -195,7 +195,7 @@ typedef struct {
unsigned int vc_format;
/* The current cliprects, or a subset thereof */
- XF86DRIClipRectRec boxes[RADEON_NR_SAREA_CLIPRECTS];
+ drm_clip_rect_t boxes[RADEON_NR_SAREA_CLIPRECTS];
unsigned int nbox;
/* Counters for throttling of rendering clients */
diff --git a/src/radeon_video.c b/src/radeon_video.c
index d551ccc0..548b6084 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"
@@ -20,8 +21,6 @@
#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
-extern int gRADEONEntityIndex;
-
static void RADEONInitOffscreenImages(ScreenPtr);
static XF86VideoAdaptorPtr RADEONSetupImageVideo(ScreenPtr);
@@ -38,14 +37,19 @@ static int RADEONQueryImageAttributes(ScrnInfoPtr, int, unsigned short *,
static void RADEONVideoTimerCallback(ScrnInfoPtr pScrn, Time now);
+
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
static Atom xvBrightness, xvColorKey, xvSaturation, xvDoubleBuffer;
static Atom xvRedIntensity, xvGreenIntensity, xvBlueIntensity;
static Atom xvContrast, xvHue, xvColor, xvAutopaintColorkey, xvSetDefaults;
+static Atom xvGamma, xvColorspace;
+static Atom xvSwitchCRT;
typedef struct {
CARD32 transform_index;
+ CARD32 gamma; /* gamma value x 1000 */
int brightness;
int saturation;
int hue;
@@ -63,12 +67,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 +130,7 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] =
};
-#define NUM_ATTRIBUTES 9+3
+#define NUM_ATTRIBUTES 9+6
static XF86AttributeRec Attributes[NUM_ATTRIBUTES] =
{
@@ -140,6 +146,9 @@ 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"},
+ {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"},
+ {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"},
};
#define NUM_IMAGES 4
@@ -172,37 +181,390 @@ REF_TRANSFORM trans[2] =
};
-/* Gamma curve definition */
-typedef struct
+/* Gamma curve definition for preset gammas */
+typedef struct tagGAMMA_CURVE_R100
{
- unsigned int gammaReg;
- unsigned int gammaSlope;
- unsigned int gammaOffset;
-} GAMMA_SETTINGS;
-
-/* Recommended gamma curve parameters */
-GAMMA_SETTINGS def_gamma[18] =
+ CARD32 GAMMA_0_F_SLOPE;
+ CARD32 GAMMA_0_F_OFFSET;
+ CARD32 GAMMA_10_1F_SLOPE;
+ CARD32 GAMMA_10_1F_OFFSET;
+ CARD32 GAMMA_20_3F_SLOPE;
+ CARD32 GAMMA_20_3F_OFFSET;
+ CARD32 GAMMA_40_7F_SLOPE;
+ CARD32 GAMMA_40_7F_OFFSET;
+ CARD32 GAMMA_380_3BF_SLOPE;
+ CARD32 GAMMA_380_3BF_OFFSET;
+ CARD32 GAMMA_3C0_3FF_SLOPE;
+ CARD32 GAMMA_3C0_3FF_OFFSET;
+ float OvGammaCont;
+} GAMMA_CURVE_R100;
+
+typedef struct tagGAMMA_CURVE_R200
+{
+ CARD32 GAMMA_0_F_SLOPE;
+ CARD32 GAMMA_0_F_OFFSET;
+ CARD32 GAMMA_10_1F_SLOPE;
+ CARD32 GAMMA_10_1F_OFFSET;
+ CARD32 GAMMA_20_3F_SLOPE;
+ CARD32 GAMMA_20_3F_OFFSET;
+ CARD32 GAMMA_40_7F_SLOPE;
+ CARD32 GAMMA_40_7F_OFFSET;
+ CARD32 GAMMA_80_BF_SLOPE;
+ CARD32 GAMMA_80_BF_OFFSET;
+ CARD32 GAMMA_C0_FF_SLOPE;
+ CARD32 GAMMA_C0_FF_OFFSET;
+ CARD32 GAMMA_100_13F_SLOPE;
+ CARD32 GAMMA_100_13F_OFFSET;
+ CARD32 GAMMA_140_17F_SLOPE;
+ CARD32 GAMMA_140_17F_OFFSET;
+ CARD32 GAMMA_180_1BF_SLOPE;
+ CARD32 GAMMA_180_1BF_OFFSET;
+ CARD32 GAMMA_1C0_1FF_SLOPE;
+ CARD32 GAMMA_1C0_1FF_OFFSET;
+ CARD32 GAMMA_200_23F_SLOPE;
+ CARD32 GAMMA_200_23F_OFFSET;
+ CARD32 GAMMA_240_27F_SLOPE;
+ CARD32 GAMMA_240_27F_OFFSET;
+ CARD32 GAMMA_280_2BF_SLOPE;
+ CARD32 GAMMA_280_2BF_OFFSET;
+ CARD32 GAMMA_2C0_2FF_SLOPE;
+ CARD32 GAMMA_2C0_2FF_OFFSET;
+ CARD32 GAMMA_300_33F_SLOPE;
+ CARD32 GAMMA_300_33F_OFFSET;
+ CARD32 GAMMA_340_37F_SLOPE;
+ CARD32 GAMMA_340_37F_OFFSET;
+ CARD32 GAMMA_380_3BF_SLOPE;
+ CARD32 GAMMA_380_3BF_OFFSET;
+ CARD32 GAMMA_3C0_3FF_SLOPE;
+ CARD32 GAMMA_3C0_3FF_OFFSET;
+ float OvGammaCont;
+} GAMMA_CURVE_R200;
+
+
+/* Preset gammas */
+GAMMA_CURVE_R100 gamma_curve_r100[8] =
{
- {RADEON_OV0_GAMMA_000_00F, 0x100, 0x0000},
- {RADEON_OV0_GAMMA_010_01F, 0x100, 0x0020},
- {RADEON_OV0_GAMMA_020_03F, 0x100, 0x0040},
- {RADEON_OV0_GAMMA_040_07F, 0x100, 0x0080},
- {RADEON_OV0_GAMMA_080_0BF, 0x100, 0x0100},
- {RADEON_OV0_GAMMA_0C0_0FF, 0x100, 0x0100},
- {RADEON_OV0_GAMMA_100_13F, 0x100, 0x0200},
- {RADEON_OV0_GAMMA_140_17F, 0x100, 0x0200},
- {RADEON_OV0_GAMMA_180_1BF, 0x100, 0x0300},
- {RADEON_OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
- {RADEON_OV0_GAMMA_200_23F, 0x100, 0x0400},
- {RADEON_OV0_GAMMA_240_27F, 0x100, 0x0400},
- {RADEON_OV0_GAMMA_280_2BF, 0x100, 0x0500},
- {RADEON_OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
- {RADEON_OV0_GAMMA_300_33F, 0x100, 0x0600},
- {RADEON_OV0_GAMMA_340_37F, 0x100, 0x0600},
- {RADEON_OV0_GAMMA_380_3BF, 0x100, 0x0700},
- {RADEON_OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
+ /* Gamma 1.0 */
+ {0x100, 0x0,
+ 0x100, 0x20,
+ 0x100, 0x40,
+ 0x100, 0x80,
+ 0x100, 0x100,
+ 0x100, 0x100,
+ 1.0},
+ /* Gamma 0.85 */
+ {0x75, 0x0,
+ 0xA2, 0xF,
+ 0xAC, 0x23,
+ 0xC6, 0x4E,
+ 0x129, 0xD6,
+ 0x12B, 0xD5,
+ 1.0},
+ /* Gamma 1.1 */
+ {0x180, 0x0,
+ 0x13C, 0x30,
+ 0x13C, 0x57,
+ 0x123, 0xA5,
+ 0xEA, 0x116,
+ 0xEA, 0x116,
+ 0.9913},
+ /* Gamma 1.2 */
+ {0x21B, 0x0,
+ 0x16D, 0x43,
+ 0x172, 0x71,
+ 0x13D, 0xCD,
+ 0xD9, 0x128,
+ 0xD6, 0x12A,
+ 0.9827},
+ /* Gamma 1.45 */
+ {0x404, 0x0,
+ 0x1B9, 0x81,
+ 0x1EE, 0xB8,
+ 0x16A, 0x133,
+ 0xB7, 0x14B,
+ 0xB2, 0x14E,
+ 0.9567},
+ /* Gamma 1.7 */
+ {0x658, 0x0,
+ 0x1B5, 0xCB,
+ 0x25F, 0x102,
+ 0x181, 0x199,
+ 0x9C, 0x165,
+ 0x98, 0x167,
+ 0.9394},
+ /* Gamma 2.2 */
+ {0x7FF, 0x0,
+ 0x625, 0x100,
+ 0x1E4, 0x1C4,
+ 0x1BD, 0x23D,
+ 0x79, 0x187,
+ 0x76, 0x188,
+ 0.9135},
+ /* Gamma 2.5 */
+ {0x7FF, 0x0,
+ 0x7FF, 0x100,
+ 0x2AD, 0x200,
+ 0x1A2, 0x2AB,
+ 0x6E, 0x194,
+ 0x67, 0x197,
+ 0.9135}
};
+GAMMA_CURVE_R200 gamma_curve_r200[8] =
+ {
+ /* Gamma 1.0 */
+ {0x00000040, 0x00000000,
+ 0x00000040, 0x00000020,
+ 0x00000080, 0x00000040,
+ 0x00000100, 0x00000080,
+ 0x00000100, 0x00000100,
+ 0x00000100, 0x00000100,
+ 0x00000100, 0x00000200,
+ 0x00000100, 0x00000200,
+ 0x00000100, 0x00000300,
+ 0x00000100, 0x00000300,
+ 0x00000100, 0x00000400,
+ 0x00000100, 0x00000400,
+ 0x00000100, 0x00000500,
+ 0x00000100, 0x00000500,
+ 0x00000100, 0x00000600,
+ 0x00000100, 0x00000600,
+ 0x00000100, 0x00000700,
+ 0x00000100, 0x00000700,
+ 1.0},
+ /* Gamma 0.85 */
+ {0x0000001D, 0x00000000,
+ 0x00000028, 0x0000000F,
+ 0x00000056, 0x00000023,
+ 0x000000C5, 0x0000004E,
+ 0x000000DA, 0x000000B0,
+ 0x000000E6, 0x000000AA,
+ 0x000000F1, 0x00000190,
+ 0x000000F9, 0x0000018C,
+ 0x00000101, 0x00000286,
+ 0x00000108, 0x00000282,
+ 0x0000010D, 0x0000038A,
+ 0x00000113, 0x00000387,
+ 0x00000118, 0x0000049A,
+ 0x0000011C, 0x00000498,
+ 0x00000120, 0x000005B4,
+ 0x00000124, 0x000005B2,
+ 0x00000128, 0x000006D6,
+ 0x0000012C, 0x000006D5,
+ 1.0},
+ /* Gamma 1.1 */
+ {0x00000060, 0x00000000,
+ 0x0000004F, 0x00000030,
+ 0x0000009C, 0x00000057,
+ 0x00000121, 0x000000A5,
+ 0x00000113, 0x00000136,
+ 0x0000010B, 0x0000013A,
+ 0x00000105, 0x00000245,
+ 0x00000100, 0x00000247,
+ 0x000000FD, 0x00000348,
+ 0x000000F9, 0x00000349,
+ 0x000000F6, 0x00000443,
+ 0x000000F4, 0x00000444,
+ 0x000000F2, 0x00000538,
+ 0x000000F0, 0x00000539,
+ 0x000000EE, 0x00000629,
+ 0x000000EC, 0x00000629,
+ 0x000000EB, 0x00000716,
+ 0x000000E9, 0x00000717,
+ 0.9913},
+ /* Gamma 1.2 */
+ {0x00000087, 0x00000000,
+ 0x0000005B, 0x00000043,
+ 0x000000B7, 0x00000071,
+ 0x0000013D, 0x000000CD,
+ 0x00000121, 0x0000016B,
+ 0x00000113, 0x00000172,
+ 0x00000107, 0x00000286,
+ 0x000000FF, 0x0000028A,
+ 0x000000F8, 0x00000389,
+ 0x000000F2, 0x0000038B,
+ 0x000000ED, 0x0000047D,
+ 0x000000E9, 0x00000480,
+ 0x000000E5, 0x00000568,
+ 0x000000E1, 0x0000056A,
+ 0x000000DE, 0x0000064B,
+ 0x000000DB, 0x0000064D,
+ 0x000000D9, 0x00000728,
+ 0x000000D6, 0x00000729,
+ 0.9827},
+ /* Gamma 1.45 */
+ {0x00000101, 0x00000000,
+ 0x0000006E, 0x00000081,
+ 0x000000F7, 0x000000B8,
+ 0x0000016E, 0x00000133,
+ 0x00000139, 0x000001EA,
+ 0x0000011B, 0x000001F9,
+ 0x00000105, 0x00000314,
+ 0x000000F6, 0x0000031C,
+ 0x000000E9, 0x00000411,
+ 0x000000DF, 0x00000417,
+ 0x000000D7, 0x000004F6,
+ 0x000000CF, 0x000004F9,
+ 0x000000C9, 0x000005C9,
+ 0x000000C4, 0x000005CC,
+ 0x000000BF, 0x0000068F,
+ 0x000000BA, 0x00000691,
+ 0x000000B6, 0x0000074B,
+ 0x000000B2, 0x0000074D,
+ 0.9567},
+ /* Gamma 1.7 */
+ {0x00000196, 0x00000000,
+ 0x0000006D, 0x000000CB,
+ 0x0000012F, 0x00000102,
+ 0x00000187, 0x00000199,
+ 0x00000144, 0x0000025b,
+ 0x00000118, 0x00000273,
+ 0x000000FE, 0x0000038B,
+ 0x000000E9, 0x00000395,
+ 0x000000DA, 0x0000047E,
+ 0x000000CE, 0x00000485,
+ 0x000000C3, 0x00000552,
+ 0x000000BB, 0x00000556,
+ 0x000000B3, 0x00000611,
+ 0x000000AC, 0x00000614,
+ 0x000000A7, 0x000006C1,
+ 0x000000A1, 0x000006C3,
+ 0x0000009D, 0x00000765,
+ 0x00000098, 0x00000767,
+ 0.9394},
+ /* Gamma 2.2 */
+ {0x000001FF, 0x00000000,
+ 0x0000018A, 0x00000100,
+ 0x000000F1, 0x000001C5,
+ 0x000001D6, 0x0000023D,
+ 0x00000124, 0x00000328,
+ 0x00000116, 0x0000032F,
+ 0x000000E2, 0x00000446,
+ 0x000000D3, 0x0000044D,
+ 0x000000BC, 0x00000520,
+ 0x000000B0, 0x00000526,
+ 0x000000A4, 0x000005D6,
+ 0x0000009B, 0x000005DB,
+ 0x00000092, 0x00000676,
+ 0x0000008B, 0x00000679,
+ 0x00000085, 0x00000704,
+ 0x00000080, 0x00000707,
+ 0x0000007B, 0x00000787,
+ 0x00000076, 0x00000789,
+ 0.9135},
+ /* Gamma 2.5 */
+ {0x000001FF, 0x00000000,
+ 0x000001FF, 0x00000100,
+ 0x00000159, 0x000001FF,
+ 0x000001AC, 0x000002AB,
+ 0x0000012F, 0x00000381,
+ 0x00000101, 0x00000399,
+ 0x000000D9, 0x0000049A,
+ 0x000000C3, 0x000004A5,
+ 0x000000AF, 0x00000567,
+ 0x000000A1, 0x0000056E,
+ 0x00000095, 0x00000610,
+ 0x0000008C, 0x00000614,
+ 0x00000084, 0x000006A0,
+ 0x0000007D, 0x000006A4,
+ 0x00000077, 0x00000721,
+ 0x00000071, 0x00000723,
+ 0x0000006D, 0x00000795,
+ 0x00000068, 0x00000797,
+ 0.9135}
+};
+
+static void
+RADEONSetOverlayGamma(ScrnInfoPtr pScrn, CARD32 gamma)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 ov0_scale_cntl;
+
+ /* Set gamma */
+ ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL) & ~RADEON_SCALER_GAMMA_SEL_MASK;
+ OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl | (gamma << 0x00000005));
+
+ /* Load gamma curve adjustments */
+ if (info->ChipFamily >= CHIP_FAMILY_R200) {
+ OUTREG(RADEON_OV0_GAMMA_000_00F,
+ (gamma_curve_r200[gamma].GAMMA_0_F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_0_F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_010_01F,
+ (gamma_curve_r200[gamma].GAMMA_10_1F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_10_1F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_020_03F,
+ (gamma_curve_r200[gamma].GAMMA_20_3F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_20_3F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_040_07F,
+ (gamma_curve_r200[gamma].GAMMA_40_7F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_40_7F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_080_0BF,
+ (gamma_curve_r200[gamma].GAMMA_80_BF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_80_BF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_0C0_0FF,
+ (gamma_curve_r200[gamma].GAMMA_C0_FF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_C0_FF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_100_13F,
+ (gamma_curve_r200[gamma].GAMMA_100_13F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_100_13F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_140_17F,
+ (gamma_curve_r200[gamma].GAMMA_140_17F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_140_17F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_180_1BF,
+ (gamma_curve_r200[gamma].GAMMA_180_1BF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_180_1BF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_1C0_1FF,
+ (gamma_curve_r200[gamma].GAMMA_1C0_1FF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_1C0_1FF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_200_23F,
+ (gamma_curve_r200[gamma].GAMMA_200_23F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_200_23F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_240_27F,
+ (gamma_curve_r200[gamma].GAMMA_240_27F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_240_27F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_280_2BF,
+ (gamma_curve_r200[gamma].GAMMA_280_2BF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_280_2BF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_2C0_2FF,
+ (gamma_curve_r200[gamma].GAMMA_2C0_2FF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_2C0_2FF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_300_33F,
+ (gamma_curve_r200[gamma].GAMMA_300_33F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_300_33F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_340_37F,
+ (gamma_curve_r200[gamma].GAMMA_340_37F_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_340_37F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_380_3BF,
+ (gamma_curve_r200[gamma].GAMMA_380_3BF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_380_3BF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_3C0_3FF,
+ (gamma_curve_r200[gamma].GAMMA_3C0_3FF_OFFSET << 0x00000000) |
+ (gamma_curve_r200[gamma].GAMMA_3C0_3FF_SLOPE << 0x00000010));
+ } else {
+ OUTREG(RADEON_OV0_GAMMA_000_00F,
+ (gamma_curve_r100[gamma].GAMMA_0_F_OFFSET << 0x00000000) |
+ (gamma_curve_r100[gamma].GAMMA_0_F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_010_01F,
+ (gamma_curve_r100[gamma].GAMMA_10_1F_OFFSET << 0x00000000) |
+ (gamma_curve_r100[gamma].GAMMA_10_1F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_020_03F,
+ (gamma_curve_r100[gamma].GAMMA_20_3F_OFFSET << 0x00000000) |
+ (gamma_curve_r100[gamma].GAMMA_20_3F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_040_07F,
+ (gamma_curve_r100[gamma].GAMMA_40_7F_OFFSET << 0x00000000) |
+ (gamma_curve_r100[gamma].GAMMA_40_7F_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_380_3BF,
+ (gamma_curve_r100[gamma].GAMMA_380_3BF_OFFSET << 0x00000000) |
+ (gamma_curve_r100[gamma].GAMMA_380_3BF_SLOPE << 0x00000010));
+ OUTREG(RADEON_OV0_GAMMA_3C0_3FF,
+ (gamma_curve_r100[gamma].GAMMA_3C0_3FF_OFFSET << 0x00000000) |
+ (gamma_curve_r100[gamma].GAMMA_3C0_3FF_SLOPE << 0x00000010));
+ }
+
+}
+
+
/****************************************************************************
* SetTransform *
* Function: Calculates and sets color space transform from supplied *
@@ -216,6 +578,7 @@ GAMMA_SETTINGS def_gamma[18] =
* green_intensity - intensity of green component *
* blue_intensity - intensity of blue component *
* ref - index to the table of refernce transforms *
+ * user_gamma - gamma value x 1000 (e.g., 1200 = gamma of 1.2) *
* Outputs: NONE *
****************************************************************************/
@@ -227,7 +590,8 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn,
float red_intensity,
float green_intensity,
float blue_intensity,
- CARD32 ref)
+ CARD32 ref,
+ CARD32 user_gamma)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
@@ -248,10 +612,32 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn,
CARD32 dwOvRCb, dwOvRCr;
CARD32 dwOvGCb, dwOvGCr;
CARD32 dwOvBCb, dwOvBCr;
+ CARD32 gamma = 0;
if (ref >= 2)
return;
+ /* translate from user_gamma (gamma x 1000) to radeon gamma table index value */
+ if (user_gamma <= 925) /* 0.85 */
+ gamma = 1;
+ else if (user_gamma <= 1050) /* 1.0 */
+ gamma = 0;
+ else if (user_gamma <= 1150) /* 1.1 */
+ gamma = 2;
+ else if (user_gamma <= 1325) /* 1.2 */
+ gamma = 3;
+ else if (user_gamma <= 1575) /* 1.45 */
+ gamma = 4;
+ else if (user_gamma <= 1950) /* 1.7 */
+ gamma = 5;
+ else if (user_gamma <= 2350) /* 2.2 */
+ gamma = 6;
+ else if (user_gamma > 2350) /* 2.5 */
+ gamma = 7;
+
+ if (gamma >= 8)
+ return;
+
OvHueSin = sin(hue);
OvHueCos = cos(hue);
@@ -278,34 +664,34 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn,
CAdjBCb = 2.01708984375;
CAdjBCr = 0;
#endif
- OvLuma = CAdjLuma;
- OvRCb = CAdjRCb;
- OvRCr = CAdjRCr;
- OvGCb = CAdjGCb;
- OvGCr = CAdjGCr;
- OvBCb = CAdjBCb;
- OvBCr = CAdjBCr;
- OvROff = RedAdj + CAdjOff -
- OvLuma * Loff - (OvRCb + OvRCr) * Coff;
- OvGOff = GreenAdj + CAdjOff -
- OvLuma * Loff - (OvGCb + OvGCr) * Coff;
- OvBOff = BlueAdj + CAdjOff -
- OvLuma * Loff - (OvBCb + OvBCr) * Coff;
+
+ OvLuma = CAdjLuma * gamma_curve_r100[gamma].OvGammaCont;
+ OvRCb = CAdjRCb * gamma_curve_r100[gamma].OvGammaCont;
+ OvRCr = CAdjRCr * gamma_curve_r100[gamma].OvGammaCont;
+ OvGCb = CAdjGCb * gamma_curve_r100[gamma].OvGammaCont;
+ OvGCr = CAdjGCr * gamma_curve_r100[gamma].OvGammaCont;
+ OvBCb = CAdjBCb * gamma_curve_r100[gamma].OvGammaCont;
+ OvBCr = CAdjBCr * gamma_curve_r100[gamma].OvGammaCont;
+ OvROff = CAdjOff * gamma_curve_r100[gamma].OvGammaCont -
+ OvLuma * Loff - (OvRCb + OvRCr) * Coff;
+ OvGOff = CAdjOff * gamma_curve_r100[gamma].OvGammaCont -
+ OvLuma * Loff - (OvGCb + OvGCr) * Coff;
+ OvBOff = CAdjOff * gamma_curve_r100[gamma].OvGammaCont -
+ OvLuma * Loff - (OvBCb + OvBCr) * Coff;
#if 0 /* default constants */
OvROff = -888.5;
OvGOff = 545;
OvBOff = -1104;
#endif
+ OvROff = ClipValue(OvROff, -2048.0, 2047.5);
+ OvGOff = ClipValue(OvGOff, -2048.0, 2047.5);
+ OvBOff = ClipValue(OvBOff, -2048.0, 2047.5);
dwOvROff = ((INT32)(OvROff * 2.0)) & 0x1fff;
dwOvGOff = ((INT32)(OvGOff * 2.0)) & 0x1fff;
dwOvBOff = ((INT32)(OvBOff * 2.0)) & 0x1fff;
- /*
- * Whatever docs say about R200 having 3.8 format instead of 3.11
- * as in Radeon is a lie
- * Or more precisely the location of bit fields is a lie
- */
- if(1 || info->ChipFamily < CHIP_FAMILY_R200)
+
+ if(info->ChipFamily < CHIP_FAMILY_RADEON)
{
dwOvLuma =(((INT32)(OvLuma * 2048.0))&0x7fff)<<17;
dwOvRCb = (((INT32)(OvRCb * 2048.0))&0x7fff)<<1;
@@ -317,14 +703,19 @@ static void RADEONSetTransform (ScrnInfoPtr pScrn,
}
else
{
- dwOvLuma = (((INT32)(OvLuma * 256.0))&0x7ff)<<20;
- dwOvRCb = (((INT32)(OvRCb * 256.0))&0x7ff)<<4;
- dwOvRCr = (((INT32)(OvRCr * 256.0))&0x7ff)<<20;
- dwOvGCb = (((INT32)(OvGCb * 256.0))&0x7ff)<<4;
- dwOvGCr = (((INT32)(OvGCr * 256.0))&0x7ff)<<20;
- dwOvBCb = (((INT32)(OvBCb * 256.0))&0x7ff)<<4;
- dwOvBCr = (((INT32)(OvBCr * 256.0))&0x7ff)<<20;
+ dwOvLuma = (((INT32)(OvLuma * 256.0))&0xfff)<<20;
+ dwOvRCb = (((INT32)(OvRCb * 256.0))&0xfff)<<4;
+ dwOvRCr = (((INT32)(OvRCr * 256.0))&0xfff)<<20;
+ dwOvGCb = (((INT32)(OvGCb * 256.0))&0xfff)<<4;
+ dwOvGCr = (((INT32)(OvGCr * 256.0))&0xfff)<<20;
+ dwOvBCb = (((INT32)(OvBCb * 256.0))&0xfff)<<4;
+ dwOvBCr = (((INT32)(OvBCr * 256.0))&0xfff)<<20;
}
+
+ /* set gamma */
+ RADEONSetOverlayGamma(pScrn, gamma);
+
+ /* color transforms */
OUTREG(RADEON_OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
OUTREG(RADEON_OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
OUTREG(RADEON_OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
@@ -376,9 +767,11 @@ RADEONResetVideo(ScrnInfoPtr pScrn)
unsigned char *RADEONMMIO = info->MMIO;
RADEONPortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr;
- if (info->accelOn) info->accel->Sync(pScrn);
+ /* this function is called from ScreenInit. pScreen is used
+ by XAA internally, but not valid until ScreenInit finishs.
+ */
+ if (info->accelOn && pScrn->pScreen) info->accel->Sync(pScrn);
- RADEONWaitForIdleMMIO(pScrn);
OUTREG(RADEON_OV0_SCALE_CNTL, 0x80000000);
OUTREG(RADEON_OV0_AUTO_FLIP_CNTL, 0); /* maybe */
OUTREG(RADEON_OV0_EXCLUSIVE_HORZ, 0);
@@ -391,12 +784,16 @@ RADEONResetVideo(ScrnInfoPtr pScrn)
OUTREG(RADEON_CAP0_TRIG_CNTL, 0);
RADEONSetColorKey(pScrn, pPriv->colorKey);
- if ((info->ChipFamily == CHIP_FAMILY_R300) ||
- (info->ChipFamily == CHIP_FAMILY_R350) ||
- (info->ChipFamily == CHIP_FAMILY_RV350) ||
- (info->ChipFamily == CHIP_FAMILY_R200) ||
- (info->ChipFamily == CHIP_FAMILY_RADEON)) {
- int i;
+ if (info->ChipFamily == CHIP_FAMILY_RADEON) {
+
+ OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000);
+ OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e);
+ OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0);
+ OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442);
+ OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040);
+ OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
+
+ } else {
OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a20000);
OUTREG(RADEON_OV0_LIN_TRANS_B, 0x198a190e);
@@ -404,7 +801,7 @@ RADEONResetVideo(ScrnInfoPtr pScrn)
OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf2fe0442);
OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a22046);
OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
-
+ }
/*
* Set default Gamma ramp:
*
@@ -412,18 +809,9 @@ RADEONResetVideo(ScrnInfoPtr pScrn)
* newer) are programmable, while only lower 4 and upper 2
* segments are programmable in the older Radeons.
*/
- for (i = 0; i < 18; i++) {
- OUTREG(def_gamma[i].gammaReg,
- (def_gamma[i].gammaSlope<<16) | def_gamma[i].gammaOffset);
- }
- } else {
- OUTREG(RADEON_OV0_LIN_TRANS_A, 0x12a00000);
- OUTREG(RADEON_OV0_LIN_TRANS_B, 0x1990190e);
- OUTREG(RADEON_OV0_LIN_TRANS_C, 0x12a0f9c0);
- OUTREG(RADEON_OV0_LIN_TRANS_D, 0xf3000442);
- OUTREG(RADEON_OV0_LIN_TRANS_E, 0x12a02040);
- OUTREG(RADEON_OV0_LIN_TRANS_F, 0x175f);
- }
+
+ RADEONSetOverlayGamma(pScrn, 0); /* gamma = 1.0 */
+
}
@@ -434,6 +822,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 +849,29 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn)
pPriv->hue = 0;
pPriv->currentBuffer = 0;
pPriv->autopaint_colorkey = TRUE;
+ pPriv->gamma = 1000;
+ 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,7 +880,12 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn)
OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) &
0xfffffCff) | (pPriv->ecp_div << 8));
- if ((info->ChipFamily == CHIP_FAMILY_RS100) ||
+ /* 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)) {
/* Force the overlay clock on for integrated chips
@@ -537,10 +944,13 @@ RADEONSetupImageVideo(ScreenPtr pScreen)
xvRedIntensity = MAKE_ATOM("XV_RED_INTENSITY");
xvGreenIntensity = MAKE_ATOM("XV_GREEN_INTENSITY");
xvBlueIntensity = MAKE_ATOM("XV_BLUE_INTENSITY");
+ xvGamma = MAKE_ATOM("XV_GAMMA");
+ xvColorspace = MAKE_ATOM("XV_COLORSPACE");
xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
-
+ xvSwitchCRT = MAKE_ATOM("XV_SWITCHCRT");
+
RADEONResetVideo(pScrn);
return adapt;
@@ -590,7 +1000,6 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn,
#define RTFIntensity(a) (((a)*1.0)/2000.0)
#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
#define RTFHue(a) (((a)*3.1416)/1000.0)
-#define ClipValue(v,min,max) ((v) < (min) ? (min) : (v) > (max) ? (max) : (v))
if(attribute == xvAutopaintColorkey)
{
@@ -606,6 +1015,8 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn,
pPriv->red_intensity = 0;
pPriv->green_intensity = 0;
pPriv->blue_intensity = 0;
+ pPriv->gamma = 1000;
+ pPriv->transform_index = 0;
pPriv->doubleBuffer = FALSE;
setTransform = TRUE;
}
@@ -644,6 +1055,16 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn,
pPriv->blue_intensity = ClipValue (value, -1000, 1000);
setTransform = TRUE;
}
+ else if(attribute == xvGamma)
+ {
+ pPriv->gamma = ClipValue (value, 100, 10000);
+ setTransform = TRUE;
+ }
+ else if(attribute == xvColorspace)
+ {
+ pPriv->transform_index = ClipValue (value, 0, 1);
+ setTransform = TRUE;
+ }
else if(attribute == xvDoubleBuffer)
{
pPriv->doubleBuffer = ClipValue (value, 0, 1);
@@ -654,8 +1075,17 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn,
pPriv->colorKey = value;
RADEONSetColorKey (pScrn, pPriv->colorKey);
REGION_EMPTY(pScrn->pScreen, &pPriv->clip);
- }
- else
+ }
+ 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;
if (setTransform)
@@ -668,7 +1098,8 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn,
RTFIntensity(pPriv->red_intensity),
RTFIntensity(pPriv->green_intensity),
RTFIntensity(pPriv->blue_intensity),
- pPriv->transform_index);
+ pPriv->transform_index,
+ pPriv->gamma);
}
return Success;
@@ -701,11 +1132,17 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn,
*value = pPriv->green_intensity;
else if(attribute == xvBlueIntensity)
*value = pPriv->blue_intensity;
+ else if(attribute == xvGamma)
+ *value = pPriv->gamma;
+ else if(attribute == xvColorspace)
+ *value = pPriv->transform_index;
else if(attribute == xvDoubleBuffer)
*value = pPriv->doubleBuffer ? 1 : 0;
else if(attribute == xvColorKey)
*value = pPriv->colorKey;
- else
+ else if(attribute == xvSwitchCRT)
+ *value = pPriv->crt2 ? 1 : 0;
+ else
return BadMatch;
return Success;
@@ -854,28 +1291,64 @@ 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,45 +1390,47 @@ 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) ||
- (info->ChipFamily == CHIP_FAMILY_RV350) ||
+ if (IS_R300_VARIANT ||
(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;
}
@@ -1028,10 +1503,6 @@ RADEONPutImage(
CARD32 tmp;
#if X_BYTE_ORDER == X_BIG_ENDIAN
unsigned char *RADEONMMIO = info->MMIO;
- CARD32 surface_cntl = INREG(RADEON_SURFACE_CNTL);
-
- OUTREG(RADEON_SURFACE_CNTL, (surface_cntl |
- RADEON_NONSURF_AP0_SWP_32BPP) & ~RADEON_NONSURF_AP0_SWP_16BPP);
#endif
/*
@@ -1064,14 +1535,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;
@@ -1128,7 +1609,8 @@ RADEONPutImage(
}
nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top;
#if X_BYTE_ORDER == X_BIG_ENDIAN
- OUTREG(RADEON_SURFACE_CNTL, (surface_cntl | RADEON_NONSURF_AP0_SWP_32BPP)
+ OUTREG(RADEON_SURFACE_CNTL, (info->ModeReg.surface_cntl |
+ RADEON_NONSURF_AP0_SWP_32BPP)
& ~RADEON_NONSURF_AP0_SWP_16BPP);
#endif
RADEONCopyMungedData(buf + (top * srcPitch) + left, buf + s2offset,
@@ -1143,8 +1625,9 @@ RADEONPutImage(
nlines = ((yb + 0xffff) >> 16) - top;
dst_start += left;
#if X_BYTE_ORDER == X_BIG_ENDIAN
- OUTREG(RADEON_SURFACE_CNTL, surface_cntl & ~(RADEON_NONSURF_AP0_SWP_32BPP
- | RADEON_NONSURF_AP0_SWP_16BPP));
+ OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl &
+ ~(RADEON_NONSURF_AP0_SWP_32BPP
+ | RADEON_NONSURF_AP0_SWP_16BPP));
#endif
RADEONCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
break;
@@ -1152,7 +1635,7 @@ RADEONPutImage(
#if X_BYTE_ORDER == X_BIG_ENDIAN
/* restore byte swapping */
- OUTREG(RADEON_SURFACE_CNTL, surface_cntl);
+ OUTREG(RADEON_SURFACE_CNTL, info->ModeReg.surface_cntl);
#endif
/* update cliplist */
@@ -1390,17 +1873,29 @@ RADEONDisplaySurface(
dstBox.y1 = drw_y;
dstBox.y2 = drw_y + drw_h;
- if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
+ 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;
+ }
+#if 0
+ /* this isn't needed */
RADEONResetVideo(pScrn);
-
+#endif
RADEONDisplayVideo(pScrn, surface->id,
surface->offsets[0], surface->offsets[0],
surface->width, surface->height, surface->pitches[0],
@@ -1443,8 +1938,8 @@ RADEONInitOffscreenImages(ScreenPtr pScreen)
offscreenImages[0].stop = RADEONStopSurface;
offscreenImages[0].setAttribute = RADEONSetSurfaceAttribute;
offscreenImages[0].getAttribute = RADEONGetSurfaceAttribute;
- offscreenImages[0].max_width = 1024;
- offscreenImages[0].max_height = 1024;
+ offscreenImages[0].max_width = 2048;
+ offscreenImages[0].max_height = 2048;
offscreenImages[0].num_attributes = NUM_ATTRIBUTES;
offscreenImages[0].attributes = Attributes;