diff options
author | George Sapountzis <gsap7@yahoo.gr> | 2007-08-28 16:01:12 +0300 |
---|---|---|
committer | George Sapountzis <gsap7@yahoo.gr> | 2007-08-28 16:01:12 +0300 |
commit | 7b38d9a1209f87255e5bb0aefe46a363ce4fb6ef (patch) | |
tree | 981bce7b10ffe6dc3940cada74d558213208b51b | |
parent | 2e3d43af1e5077cc61dd8668551a6291368d9ed2 (diff) | |
parent | 673f799729824f4439dd5f681f75dd5aab50947f (diff) |
Merge branch 'master' into pci-rework
Conflicts:
src/ati.c
56 files changed, 9183 insertions, 9055 deletions
@@ -31,3 +31,4 @@ r128.4x radeon.4 radeon.4x stamp-h1 +*cscope* diff --git a/configure.ac b/configure.ac index 16b93e12..0c413c80 100644 --- a/configure.ac +++ b/configure.ac @@ -22,7 +22,7 @@ AC_PREREQ(2.57) AC_INIT([xf86-video-ati], - 6.6.99, + 6.7.192, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-video-ati) @@ -39,6 +39,10 @@ AC_DISABLE_STATIC AC_PROG_LIBTOOL AC_PROG_CC +if test "x$GCC" = "xyes"; then + CFLAGS="$CFLAGS -Wall" +fi + AH_TOP([#include "xorg-server.h"]) AC_ARG_WITH(xorg-module-dir, @@ -67,7 +71,7 @@ XORG_DRIVER_CHECK_EXT(XF86MISC, xf86miscproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) # Checks for pkg-config packages -PKG_CHECK_MODULES(XORG, [xorg-server xproto fontsproto $REQUIRED_MODULES]) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.3 xproto fontsproto $REQUIRED_MODULES]) sdkdir=$(pkg-config --variable=sdkdir xorg-server) # Checks for libraries. diff --git a/man/ati.man b/man/ati.man index bc33610d..c6c7d01c 100644 --- a/man/ati.man +++ b/man/ati.man @@ -17,7 +17,7 @@ ati \- ATI video driver is an __xservername__ wrapper driver for ATI video cards. It autodetects whether your hardware has a Radeon, Rage 128, or Mach64 or earlier class of chipset, and loads the radeon(__drivermansuffix__), -r128(__drivermansuffix__), or atimisc(__drivermansuffix__) driver as +r128(__drivermansuffix__), or atimisc driver as appropriate. .SH SUPPORTED HARDWARE The @@ -29,6 +29,6 @@ Please refer to __xconfigfile__(__filemansuffix__) for general configuration details, and the specific card driver for driver configuration details. driver. .SH "SEE ALSO" -__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) +__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), r128(__drivermansuffix__), radeon(__drivermansuffix__) .SH AUTHORS See the individual driver pages for authors. diff --git a/man/radeon.man b/man/radeon.man index 447dcbee..88665bf0 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -150,14 +150,6 @@ affects the "true" overlay via xv, it won't affect things like textured video. .br The default value is either 1536 (for most chips) or 1920. .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). MergedFB does not work when this -option is in use. See fbdevhw(__drivermansuffix__) for further information. -.br -The default is -.B off. -.TP .BI "Option \*qAGPMode\*q \*q" integer \*q Set AGP data transfer rate. (used only when DRI is enabled) @@ -223,227 +215,6 @@ HIGH \-\- Force to the highest priority. The default value is .B AUTO. .TP -.BI "Option \*qMonitorLayout\*q \*q" string \*q -.br -This option is used to overwrite the detected monitor types. -This is only required when driver makes a false detection. -The possible monitor types are: -.br -NONE \-\- Not connected -.br -CRT \-\- Analog CRT monitor -.br -TMDS \-\- Desktop flat panel -.br -LVDS \-\- Laptop flat panel -.br -This option can be used in following format: -.br -Option "MonitorLayout" "[type on primary], [type on secondary]" -.br -For example, Option "MonitorLayout" "CRT, TMDS" - -Primary/Secondary head for dual\-head cards: -.br -(when only one port is used, it will be treated as the primary regardless) -.br -.B Primary head: -.br -DVI port on DVI+VGA cards -.br -LCD output on laptops -.br -Internal TMDS port on DVI+DVI cards -.br -.B Secondary head: -.br -VGA port on DVI+VGA cards -.br -VGA port on laptops -.br -External TMDS port on DVI+DVI cards - -The default value is -.B undefined. -.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 __xconfigfile__ 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 inaccessible. 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 \*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 "CRT2HSync" "30.0-86.0" -.br -The default value is -.B undefined. -.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 "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 -This option also supports an offset. This is most useful when -.B MergedNonRectangular -is enabled. For example if you want CRT2 to be offset 100 pixels down from -the start of CRT1, you'd type: -.br -Option "CRT2Position" "LeftOf 100" -.br -The offset is vertical for LeftOf and RightOf and horizontal for Above and -Below. Offsets can be positive or negative. -.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. If you want to add clone modes -of different refreshes or sizes to the mix, they are defined as CRT1Mode+CRT2Mode -(800x600+1024x768). -.br -Note: Any mode you use in the MetaModes must be defined in the -.B Screen -section of your __xconfigfile__ file. Modes not defined there will be ignored when -the MetaModes are parsed since the driver uses them to make sure the monitors can -handle those modes. If you do not define a MetaMode the driver will create -one based on the orientation of the heads and size of the largest defined mode in -the display section that is supported on each head. -.br -.B Modes "1024x768" "800x600" "640x480" -.br -For example, Option "MetaModes" "1024x768-1024x768 800x600-1024x768 640x480-800x600 800x600" -.br -The default value is -.B undefined. -.TP -.BI "Option \*qMergedXinerama\*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 TRUE. -.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 \*qMergedNonRectangular\*q \*q" boolean \*q -If you are using MergedFB with two modes of different sizes, turn this option on to -keep the smaller head from scrolling within the larger virtual desktop and to keep -the mouse from moving into that area. Applications that are not Xinerama aware can -potentially end up stranded in this area. -.br -The default value is -.B FALSE. -.TP .BI "Option \*qColorTiling\*q \*q" "boolean" \*q Frame buffer can be addressed either in linear or tiled mode. Tiled mode can provide significant performance benefits with 3D applications, for 2D it shouldn't matter @@ -478,12 +249,6 @@ For example, Option "PanelSize" "1400x1050" .br The default value is .B none. -.TP -.BI "Option \*qPanelOff\*q \*q" boolean \*q -Disable panel output. -.br -The default value is -.B off. .TP .BI "Option \*qEnablePageFlip\*q \*q" boolean \*q Enable page flipping for 3D acceleration. This will increase performance @@ -535,7 +300,7 @@ remainder of video RAM is reserved for EXA offscreen management. Specifying 0 results in all offscreen video RAM being reserved for EXA and only GART memory being available for OpenGL textures. This may improve EXA performance, but beware that it may cause problems with OpenGL drivers from Mesa versions older -than 6.4. With XAA, specifiying lower percentage than what gets reserved without +than 6.4. With XAA, specifying lower percentage than what gets reserved without this option has no effect, but the driver tries to increase the video RAM reserved for textures to the amount specified roughly. Default: @@ -590,13 +355,6 @@ life by reducing power usage. Some users report reduced 3D performance with this enabled. The default is .B off. .TP -.BI "Option \*qBIOSHotkeys\*q \*q" boolean \*q -Enable BIOS hotkey output switching. This allows the BIOS to toggle outputs -using hotkeys (e.g., fn-f7, etc.). Since the driver does not support ACPI, -there is no way to validate modes on an output switch and the BIOS can -potentially change things behind the driver's back. The default is -.B off. -.TP .BI "Option \*qVGAAccess\*q \*q" boolean \*q Tell the driver if it can do legacy VGA IOs to the card. This is necessary for properly resuming consoles when in VGA text mode, but @@ -633,6 +391,12 @@ for RN50/ES1000 and .B on for others. .TP +.BI "Option \*qDefaultConnectorTable\*q \*q" boolean \*q +Enable this option to skip the BIOS connector table parsing and use the +driver defaults for each chip. +The default is +.B off +.TP .SH SEE ALSO __xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) @@ -644,7 +408,7 @@ Kevin E. Martin \fIkem@freedesktop.org\fP Alan Hourihane \fIalanh@fairlite.demon.co.uk\fP Marc Aurele La France \fItsi@xfree86.org\fP Benjamin Herrenschmidt \fIbenh@kernel.crashing.org\fP -Michel Dänzer \fImichel@tungstengraphics.com\fP +Michel D\(:anzer \fImichel@tungstengraphics.com\fP Alex Deucher \fIalexdeucher@gmail.com\fP Bogdan D. \fIbogdand@users.sourceforge.net\fP Eric Anholt \fIeric@anholt.net\fP diff --git a/src/Makefile.am b/src/Makefile.am index 2528d2a7..dd7007e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,36 +51,37 @@ ati_drv_la_LTLIBRARIES = ati_drv.la ati_drv_la_LDFLAGS = -module -avoid-version ati_drv_ladir = @moduledir@/drivers ati_drv_la_SOURCES = \ - ati.c atichip.c atimodule.c atimach64probe.c \ - radeon_probe.c r128_probe.c + ati.c atimodule.c atimisc_drv_la_LTLIBRARIES = atimisc_drv.la atimisc_drv_la_LDFLAGS = -module -avoid-version atimisc_drv_ladir = @moduledir@/drivers atimisc_drv_la_SOURCES = \ - atibus.c atiprobe.c atividmem.c \ + atibus.c atichip.c atiprobe.c atividmem.c \ atiadjust.c atiaudio.c aticlock.c aticonfig.c aticonsole.c \ - atidac.c atidecoder.c atidsp.c atifillin.c atii2c.c \ + atidac.c atidecoder.c atidsp.c atii2c.c \ atilock.c atimach64.c atimach64accel.c atimach64cursor.c \ atimach64i2c.c atimach64io.c atimach64xv.c atimode.c atipreinit.c \ atiprint.c atirgb514.c atiscreen.c atituner.c atiutil.c ativalid.c \ - atiload.c atimisc.c $(ATIMISC_DRI_SRCS) $(ATIMISC_DGA_SOURCES) \ - $(ATIMISC_CPIO_SOURCES) $(ATIMISC_EXA_SOURCES) + atiload.c atimisc.c atimach64probe.c $(ATIMISC_CPIO_SOURCES) \ + $(ATIMISC_DGA_SOURCES) $(ATIMISC_DRI_SRCS) $(ATIMISC_EXA_SOURCES) r128_drv_la_LTLIBRARIES = r128_drv.la r128_drv_la_LDFLAGS = -module -avoid-version r128_drv_ladir = @moduledir@/drivers r128_drv_la_SOURCES = \ r128_accel.c r128_cursor.c r128_dga.c r128_driver.c \ - r128_video.c r128_misc.c $(R128_DRI_SRCS) + r128_video.c r128_misc.c r128_probe.c $(R128_DRI_SRCS) radeon_drv_la_LTLIBRARIES = radeon_drv.la radeon_drv_la_LDFLAGS = -module -avoid-version radeon_drv_ladir = @moduledir@/drivers radeon_drv_la_SOURCES = \ - radeon_accel.c radeon_mergedfb.c radeon_cursor.c radeon_dga.c \ + radeon_accel.c radeon_cursor.c radeon_dga.c \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ - radeon_vip.c radeon_misc.c radeon_display.c radeon_modes.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) + radeon_vip.c radeon_misc.c radeon_probe.c radeon_display.c \ + radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \ + $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) theatre_detect_drv_la_LTLIBRARIES = theatre_detect_drv.la theatre_detect_drv_la_LDFLAGS = -module -avoid-version @@ -123,7 +124,6 @@ EXTRA_DIST = \ atidri.h \ atidripriv.h \ atidsp.h \ - atifillin.h \ ati.h \ atii2c.h \ atiload.h \ @@ -176,12 +176,12 @@ EXTRA_DIST = \ radeon_exa_funcs.c \ radeon.h \ radeon_macros.h \ - radeon_mergedfb.h \ radeon_probe.h \ radeon_reg.h \ radeon_sarea.h \ radeon_version.h \ radeon_video.h \ + radeon_tv.h \ theatre200.h \ theatre_detect.h \ theatre.h \ @@ -60,14 +60,12 @@ #include "atipcirename.h" #include "ati.h" -#include "atichip.h" +#include "atimodule.h" #include "ativersion.h" #include "atimach64probe.h" #include "radeon_probe.h" -#include "radeon_version.h" #include "r128_probe.h" -#include "r128_version.h" /* * ATIIdentify -- @@ -80,10 +78,13 @@ ATIIdentify int flags ) { + /* + * Only print chip families here, chip lists are printed when a subdriver + * is loaded. + */ xf86Msg(X_INFO, "%s: %s\n", ATI_NAME, - "ATI driver (version " ATI_VERSION_NAME ") for chipset: mach64"); - R128Identify(flags); - RADEONIdentify(flags); + "ATI driver wrapper (version " ATI_VERSION_NAME ") for chipsets: " + "mach64, rage128, radeon"); } /* @@ -99,61 +100,100 @@ ATIProbe int flags ) { - pciVideoPtr pVideo, *xf86PciVideoInfo = xf86GetPciVideoInfo(); - Bool ProbeSuccess = FALSE; + pciVideoPtr pVideo; + pciVideoPtr *xf86PciVideoInfo; Bool DoMach64 = FALSE; Bool DoRage128 = FALSE, DoRadeon = FALSE; - int i; ATIChipType Chip; - if (!(flags & PROBE_DETECT)) + xf86PciVideoInfo = xf86GetPciVideoInfo(); + + if (xf86PciVideoInfo == NULL) + return FALSE; + + while ((pVideo = *xf86PciVideoInfo++) != NULL) { - if (xf86MatchDevice(ATI_NAME, NULL) > 0) + if ((PCI_DEV_VENDOR_ID(pVideo) != PCI_VENDOR_ATI) || + (PCI_DEV_DEVICE_ID(pVideo) == PCI_CHIP_MACH32)) + continue; + + /* Check for Rage128's, Radeon's and later adapters */ + Chip = ATIChipID(PCI_DEV_DEVICE_ID(pVideo), PCI_DEV_REVISION(pVideo)); + if (Chip <= ATI_CHIP_Mach64) DoMach64 = TRUE; - if (xf86MatchDevice(R128_NAME, NULL) > 0) + else if (Chip <= ATI_CHIP_Rage128) DoRage128 = TRUE; - if (xf86MatchDevice(RADEON_NAME, NULL) > 0) + else if (Chip <= ATI_CHIP_Radeon) DoRadeon = TRUE; } - if (xf86PciVideoInfo) + /* Call Radeon driver probe */ + if (DoRadeon) { - for (i = 0; (pVideo = xf86PciVideoInfo[i++]); ) + pointer radeon = xf86LoadDrvSubModule(pDriver, "radeon"); + + if (!radeon) { - if ((PCI_DEV_VENDOR_ID(pVideo) != PCI_VENDOR_ATI) || - (PCI_DEV_DEVICE_ID(pVideo) == PCI_CHIP_MACH32)) - continue; + xf86Msg(X_ERROR, + ATI_NAME ": Failed to load \"radeon\" module.\n"); + return FALSE; + } - /* Check for Rage128's, Radeon's and later adapters */ - Chip = ATIChipID(PCI_DEV_DEVICE_ID(pVideo), PCI_DEV_REVISION(pVideo)); + xf86LoaderReqSymLists(RADEONSymbols, NULL); - if (Chip > ATI_CHIP_Mach64) - { - if (Chip <= ATI_CHIP_Rage128) - DoRage128 = TRUE; - else if (Chip <= ATI_CHIP_Radeon) - DoRadeon = TRUE; + RADEONIdentify(flags); - continue; - } + if (RADEONProbe(pDriver, flags)) + return TRUE; - DoMach64 = TRUE; + xf86UnloadSubModule(radeon); + } + + /* Call Rage 128 driver probe */ + if (DoRage128) + { + pointer r128 = xf86LoadDrvSubModule(pDriver, "r128"); + + if (!r128) + { + xf86Msg(X_ERROR, + ATI_NAME ": Failed to load \"r128\" module.\n"); + return FALSE; } + + xf86LoaderReqSymLists(R128Symbols, NULL); + + R128Identify(flags); + + if (R128Probe(pDriver, flags)) + return TRUE; + + xf86UnloadSubModule(r128); } /* Call Mach64 driver probe */ - if (DoMach64 && Mach64Probe(pDriver, flags)) - ProbeSuccess = TRUE; + if (DoMach64) + { + pointer atimisc = xf86LoadDrvSubModule(pDriver, "atimisc"); - /* Call Rage 128 driver probe */ - if (DoRage128 && R128Probe(pDriver, flags)) - ProbeSuccess = TRUE; + if (!atimisc) + { + xf86Msg(X_ERROR, + ATI_NAME ": Failed to load \"atimisc\" module.\n"); + return FALSE; + } - /* Call Radeon driver probe */ - if (DoRadeon && RADEONProbe(pDriver, flags)) - ProbeSuccess = TRUE; + xf86LoaderReqSymLists(ATISymbols, NULL); + + Mach64Identify(flags); + + if (Mach64Probe(pDriver, flags)) + return TRUE; - return ProbeSuccess; + xf86UnloadSubModule(atimisc); + } + + return FALSE; } /* @@ -161,22 +201,27 @@ ATIProbe * * Return recognised options that are intended for public consumption. */ -const OptionInfoRec * +static const OptionInfoRec * ATIAvailableOptions ( int ChipId, int BusId ) { - const OptionInfoRec *pOptions; + CARD16 ChipType = ChipId & 0xffff; + ATIChipType Chip; - if ((pOptions = R128AvailableOptions(ChipId, BusId))) - return pOptions; + /* Probe should have loaded the appropriate subdriver by this point */ - if ((pOptions = RADEONAvailableOptions(ChipId, BusId))) - return pOptions; + Chip = ATIChipID(ChipType, 0x0); /* chip revision is don't care */ + if (Chip <= ATI_CHIP_Mach64) + return Mach64AvailableOptions(ChipId, BusId); + else if (Chip <= ATI_CHIP_Rage128) + return R128AvailableOptions(ChipId, BusId); + else if (Chip <= ATI_CHIP_Radeon) + return RADEONAvailableOptions(ChipId, BusId); - return Mach64AvailableOptions(ChipId, BusId); + return NULL; } /* The root of all evil... */ @@ -190,3 +235,469 @@ _X_EXPORT DriverRec ATI = NULL, 0 }; + +/* + * Chip-related definitions. + */ +const char *ATIChipNames[] = +{ + "Unknown", + "ATI 88800GX-C", + "ATI 88800GX-D", + "ATI 88800GX-E", + "ATI 88800GX-F", + "ATI 88800GX", + "ATI 88800CX", + "ATI 264CT", + "ATI 264ET", + "ATI 264VT", + "ATI 3D Rage", + "ATI 264VT-B", + "ATI 3D Rage II", + "ATI 264VT3", + "ATI 3D Rage II+DVD", + "ATI 3D Rage LT", + "ATI 264VT4", + "ATI 3D Rage IIc", + "ATI 3D Rage Pro", + "ATI 3D Rage LT Pro", + "ATI 3D Rage XL or XC", + "ATI 3D Rage Mobility", + "ATI unknown Mach64", + "ATI Rage 128 GL", + "ATI Rage 128 VR", + "ATI Rage 128 Pro GL", + "ATI Rage 128 Pro VR", + "ATI Rage 128 Pro ULTRA", + "ATI Rage 128 Mobility M3", + "ATI Rage 128 Mobility M4", + "ATI unknown Rage 128" + "ATI Radeon 7200", + "ATI Radeon 7000 (VE)", + "ATI Radeon Mobility M6", + "ATI Radeon IGP320", + "ATI Radeon IGP330/340/350", + "ATI Radeon 7000 IGP", + "ATI Radeon 7500", + "ATI Radeon Mobility M7", + "ATI Radeon 8500/9100", + "ATI Radeon 9000", + "ATI Radeon Mobility M9", + "ATI Radeon 9100 IGP", + "ATI Radeon 9200 IGP", + "ATI Radeon 9200", + "ATI Radeon Mobility M9+", + "ATI Radeon 9700/9500", + "ATI Radeon 9600/9550", + "ATI Radeon 9800", + "ATI Radeon 9800XT", + "ATI Radeon X300/X550/M22", + "ATI Radeon X600/X550/M24", + "ATI Radeon X800/M18 AGP", + "ATI Radeon X800/M28 PCIE", + "ATI Radeon X800XL PCIE", + "ATI Radeon X850 PCIE", + "ATI Radeon X850 AGP", + "ATI Radeon X700", + "ATI Xpress 200" + "ATI unknown Radeon", + "ATI Rage HDTV" +}; + +#include "atichip.h" + +/* + * ATIChipID -- + * + * This returns the ATI_CHIP_* value (generally) associated with a particular + * ChipID/ChipRev combination. + */ +ATIChipType +ATIChipID +( + const CARD16 ChipID, + const CARD8 ChipRev +) +{ + switch (ChipID) + { + case OldChipID('G', 'X'): case NewChipID('G', 'X'): + switch (ChipRev) + { + case 0x00U: + return ATI_CHIP_88800GXC; + + case 0x01U: + return ATI_CHIP_88800GXD; + + case 0x02U: + return ATI_CHIP_88800GXE; + + case 0x03U: + return ATI_CHIP_88800GXF; + + default: + return ATI_CHIP_88800GX; + } + + case OldChipID('C', 'X'): case NewChipID('C', 'X'): + return ATI_CHIP_88800CX; + + case OldChipID('C', 'T'): case NewChipID('C', 'T'): + return ATI_CHIP_264CT; + + case OldChipID('E', 'T'): case NewChipID('E', 'T'): + return ATI_CHIP_264ET; + + case OldChipID('V', 'T'): case NewChipID('V', 'T'): + /* For simplicity, ignore ChipID discrepancy that can occur here */ + if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) + return ATI_CHIP_264VT; + return ATI_CHIP_264VTB; + + case OldChipID('G', 'T'): case NewChipID('G', 'T'): + if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) + return ATI_CHIP_264GT; + return ATI_CHIP_264GTB; + + case OldChipID('V', 'U'): case NewChipID('V', 'U'): + return ATI_CHIP_264VT3; + + case OldChipID('G', 'U'): case NewChipID('G', 'U'): + return ATI_CHIP_264GTDVD; + + case OldChipID('L', 'G'): case NewChipID('L', 'G'): + return ATI_CHIP_264LT; + + case OldChipID('V', 'V'): case NewChipID('V', 'V'): + return ATI_CHIP_264VT4; + + case OldChipID('G', 'V'): case NewChipID('G', 'V'): + case OldChipID('G', 'W'): case NewChipID('G', 'W'): + case OldChipID('G', 'Y'): case NewChipID('G', 'Y'): + case OldChipID('G', 'Z'): case NewChipID('G', 'Z'): + return ATI_CHIP_264GT2C; + + case OldChipID('G', 'B'): case NewChipID('G', 'B'): + case OldChipID('G', 'D'): case NewChipID('G', 'D'): + case OldChipID('G', 'I'): case NewChipID('G', 'I'): + case OldChipID('G', 'P'): case NewChipID('G', 'P'): + case OldChipID('G', 'Q'): case NewChipID('G', 'Q'): + return ATI_CHIP_264GTPRO; + + case OldChipID('L', 'B'): case NewChipID('L', 'B'): + case OldChipID('L', 'D'): case NewChipID('L', 'D'): + case OldChipID('L', 'I'): case NewChipID('L', 'I'): + case OldChipID('L', 'P'): case NewChipID('L', 'P'): + case OldChipID('L', 'Q'): case NewChipID('L', 'Q'): + return ATI_CHIP_264LTPRO; + + case OldChipID('G', 'L'): case NewChipID('G', 'L'): + case OldChipID('G', 'M'): case NewChipID('G', 'M'): + case OldChipID('G', 'N'): case NewChipID('G', 'N'): + case OldChipID('G', 'O'): case NewChipID('G', 'O'): + case OldChipID('G', 'R'): case NewChipID('G', 'R'): + case OldChipID('G', 'S'): case NewChipID('G', 'S'): + return ATI_CHIP_264XL; + + case OldChipID('L', 'M'): case NewChipID('L', 'M'): + case OldChipID('L', 'N'): case NewChipID('L', 'N'): + case OldChipID('L', 'R'): case NewChipID('L', 'R'): + case OldChipID('L', 'S'): case NewChipID('L', 'S'): + return ATI_CHIP_MOBILITY; + + case NewChipID('R', 'E'): + case NewChipID('R', 'F'): + case NewChipID('R', 'G'): + case NewChipID('S', 'K'): + case NewChipID('S', 'L'): + case NewChipID('S', 'M'): + /* "SN" is listed as ATI_CHIP_RAGE128_4X in ATI docs */ + case NewChipID('S', 'N'): + return ATI_CHIP_RAGE128GL; + + case NewChipID('R', 'K'): + case NewChipID('R', 'L'): + /* + * ATI documentation lists SE/SF/SG under both ATI_CHIP_RAGE128VR + * and ATI_CHIP_RAGE128_4X, and lists SH/SK/SL under Rage 128 4X only. + * I'm stuffing them here for now until this can be clarified as ATI + * documentation doesn't mention their details. <mharris@redhat.com> + */ + case NewChipID('S', 'E'): + case NewChipID('S', 'F'): + case NewChipID('S', 'G'): + case NewChipID('S', 'H'): + return ATI_CHIP_RAGE128VR; + + /* case NewChipID('S', 'H'): */ + /* case NewChipID('S', 'K'): */ + /* case NewChipID('S', 'L'): */ + /* case NewChipID('S', 'N'): */ + /* return ATI_CHIP_RAGE128_4X; */ + + case NewChipID('P', 'A'): + case NewChipID('P', 'B'): + case NewChipID('P', 'C'): + case NewChipID('P', 'D'): + case NewChipID('P', 'E'): + case NewChipID('P', 'F'): + return ATI_CHIP_RAGE128PROGL; + + case NewChipID('P', 'G'): + case NewChipID('P', 'H'): + case NewChipID('P', 'I'): + case NewChipID('P', 'J'): + case NewChipID('P', 'K'): + case NewChipID('P', 'L'): + case NewChipID('P', 'M'): + case NewChipID('P', 'N'): + case NewChipID('P', 'O'): + case NewChipID('P', 'P'): + case NewChipID('P', 'Q'): + case NewChipID('P', 'R'): + case NewChipID('P', 'S'): + case NewChipID('P', 'T'): + case NewChipID('P', 'U'): + case NewChipID('P', 'V'): + case NewChipID('P', 'W'): + case NewChipID('P', 'X'): + return ATI_CHIP_RAGE128PROVR; + + case NewChipID('T', 'F'): + case NewChipID('T', 'L'): + case NewChipID('T', 'R'): + case NewChipID('T', 'S'): + case NewChipID('T', 'T'): + case NewChipID('T', 'U'): + return ATI_CHIP_RAGE128PROULTRA; + + case NewChipID('L', 'E'): + case NewChipID('L', 'F'): + /* + * "LK" and "LL" are not in any ATI documentation I can find + * - mharris + */ + case NewChipID('L', 'K'): + case NewChipID('L', 'L'): + return ATI_CHIP_RAGE128MOBILITY3; + + case NewChipID('M', 'F'): + case NewChipID('M', 'L'): + return ATI_CHIP_RAGE128MOBILITY4; + + case NewChipID('Q', 'D'): + case NewChipID('Q', 'E'): + case NewChipID('Q', 'F'): + case NewChipID('Q', 'G'): + return ATI_CHIP_RADEON; + + case NewChipID('Q', 'Y'): + case NewChipID('Q', 'Z'): + case NewChipID('Q', '^'): + return ATI_CHIP_RADEONVE; + + case NewChipID('L', 'Y'): + case NewChipID('L', 'Z'): + return ATI_CHIP_RADEONMOBILITY6; + + case NewChipID('A', '6'): + case NewChipID('C', '6'): + return ATI_CHIP_RS100; + + case NewChipID('A', '7'): + case NewChipID('C', '7'): + return ATI_CHIP_RS200; + + case NewChipID('D', '7'): + case NewChipID('B', '7'): + return ATI_CHIP_RS250; + + case NewChipID('L', 'W'): + case NewChipID('L', 'X'): + return ATI_CHIP_RADEONMOBILITY7; + + case NewChipID('Q', 'H'): + case NewChipID('Q', 'I'): + case NewChipID('Q', 'J'): + case NewChipID('Q', 'K'): + case NewChipID('Q', 'L'): + case NewChipID('Q', 'M'): + case NewChipID('Q', 'N'): + case NewChipID('Q', 'O'): + case NewChipID('Q', 'h'): + case NewChipID('Q', 'i'): + case NewChipID('Q', 'j'): + case NewChipID('Q', 'k'): + case NewChipID('Q', 'l'): + case NewChipID('B', 'B'): + return ATI_CHIP_R200; + + case NewChipID('Q', 'W'): + case NewChipID('Q', 'X'): + return ATI_CHIP_RV200; + + case NewChipID('I', 'f'): + case NewChipID('I', 'g'): + return ATI_CHIP_RV250; + + case NewChipID('L', 'd'): + case NewChipID('L', 'f'): + case NewChipID('L', 'g'): + return ATI_CHIP_RADEONMOBILITY9; + + case NewChipID('X', '4'): + 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'): + case NewChipID('Y', 'd'): + case NewChipID('Y', 'e'): + return ATI_CHIP_RV280; + + case NewChipID('\\', 'a'): + case NewChipID('\\', 'c'): + return ATI_CHIP_RADEONMOBILITY9PLUS; + + case NewChipID('A', 'D'): + case NewChipID('A', 'E'): + case NewChipID('A', 'F'): + case NewChipID('A', 'G'): + case NewChipID('N', 'D'): + case NewChipID('N', 'E'): + case NewChipID('N', 'F'): + case NewChipID('N', 'G'): + return ATI_CHIP_R300; + + case NewChipID('A', 'H'): + case NewChipID('A', 'I'): + case NewChipID('A', 'J'): + case NewChipID('A', 'K'): + case NewChipID('N', 'H'): + case NewChipID('N', 'I'): + case NewChipID('N', 'K'): + return ATI_CHIP_R350; + + case NewChipID('A', 'P'): + case NewChipID('A', 'Q'): + case NewChipID('A', 'R'): + case NewChipID('A', 'S'): + case NewChipID('A', 'T'): + case NewChipID('A', 'U'): + case NewChipID('A', 'V'): + case NewChipID('N', 'P'): + case NewChipID('N', 'Q'): + case NewChipID('N', 'R'): + case NewChipID('N', 'S'): + case NewChipID('N', 'T'): + case NewChipID('N', 'V'): + return ATI_CHIP_RV350; + + case NewChipID('N', 'J'): + return ATI_CHIP_R360; + + case NewChipID('[', '\''): + case NewChipID('[', 'b'): + case NewChipID('[', 'c'): + case NewChipID('[', 'd'): + case NewChipID('[', 'e'): + case NewChipID('T', '\''): + case NewChipID('T', 'b'): + case NewChipID('T', 'd'): + return ATI_CHIP_RV370; + + case NewChipID('>', 'P'): + case NewChipID('>', 'T'): + case NewChipID('1', 'P'): + case NewChipID('1', 'R'): + 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', 'O'): + case NewChipID('J', 'P'): + case NewChipID('J', 'T'): + return ATI_CHIP_R420; + + case NewChipID('U', 'H'): + case NewChipID('U', 'I'): + case NewChipID('U', 'J'): + case NewChipID('U', 'K'): + case NewChipID('U', 'P'): + case NewChipID('U', 'Q'): + case NewChipID('U', 'R'): + case NewChipID('U', 'T'): + case NewChipID(']', 'W'): + /* those are m28, not 100% certain they are r423 could + be r480 but not r430 as their pci id names indicate... */ + case NewChipID(']', 'H'): + case NewChipID(']', 'I'): + case NewChipID(']', 'J'): + return ATI_CHIP_R423; + + case NewChipID('U', 'L'): + case NewChipID('U', 'M'): + case NewChipID('U', 'N'): + case NewChipID('U', 'O'): + return ATI_CHIP_R430; + + case NewChipID(']', 'L'): + case NewChipID(']', 'M'): + case NewChipID(']', 'N'): + case NewChipID(']', 'O'): + case NewChipID(']', 'P'): + case NewChipID(']', 'R'): + return ATI_CHIP_R480; + + case NewChipID('K', 'I'): + case NewChipID('K', 'J'): + case NewChipID('K', 'K'): + case NewChipID('K', 'L'): + return ATI_CHIP_R481; + + case NewChipID('^', 'H'): + case NewChipID('^', 'J'): + case NewChipID('^', 'K'): + case NewChipID('^', 'L'): + case NewChipID('^', 'M'): + case NewChipID('^', 'O'): + case NewChipID('V', 'J'): + case NewChipID('V', 'K'): + case NewChipID('V', 'O'): + case NewChipID('V', 'R'): + case NewChipID('V', 'S'): + return ATI_CHIP_RV410; + + case NewChipID('Z', 'A'): + case NewChipID('Z', 'B'): + case NewChipID('Z', 'a'): + case NewChipID('Z', 'b'): + case NewChipID('Y', 'T'): + case NewChipID('Y', 'U'): + case NewChipID('Y', 't'): + case NewChipID('Y', 'u'): + return ATI_CHIP_RS400; + + case NewChipID('H', 'D'): + return ATI_CHIP_HDTV; + + default: + /* + * Treat anything else as an unknown Radeon. Please keep the above + * up-to-date however, as it serves as a central chip list. + */ + return ATI_CHIP_Radeon; + } +} @@ -33,4 +33,76 @@ extern DriverRec ATI; +/* + * Chip-related definitions. + */ +typedef enum +{ + ATI_CHIP_NONE = 0, + ATI_CHIP_88800GXC, /* Mach64 */ + ATI_CHIP_88800GXD, /* Mach64 */ + ATI_CHIP_88800GXE, /* Mach64 */ + ATI_CHIP_88800GXF, /* Mach64 */ + ATI_CHIP_88800GX, /* Mach64 */ + ATI_CHIP_88800CX, /* Mach64 */ + ATI_CHIP_264CT, /* Mach64 */ + ATI_CHIP_264ET, /* Mach64 */ + ATI_CHIP_264VT, /* Mach64 */ + ATI_CHIP_264GT, /* Mach64 */ + ATI_CHIP_264VTB, /* Mach64 */ + ATI_CHIP_264GTB, /* Mach64 */ + ATI_CHIP_264VT3, /* Mach64 */ + ATI_CHIP_264GTDVD, /* Mach64 */ + ATI_CHIP_264LT, /* Mach64 */ + ATI_CHIP_264VT4, /* Mach64 */ + ATI_CHIP_264GT2C, /* Mach64 */ + ATI_CHIP_264GTPRO, /* Mach64 */ + ATI_CHIP_264LTPRO, /* Mach64 */ + ATI_CHIP_264XL, /* Mach64 */ + ATI_CHIP_MOBILITY, /* Mach64 */ + ATI_CHIP_Mach64, /* Last among Mach64's */ + ATI_CHIP_RAGE128GL, /* Rage128 */ + ATI_CHIP_RAGE128VR, /* Rage128 */ + ATI_CHIP_RAGE128PROGL, /* Rage128 */ + ATI_CHIP_RAGE128PROVR, /* Rage128 */ + ATI_CHIP_RAGE128PROULTRA, /* Rage128 */ + ATI_CHIP_RAGE128MOBILITY3, /* Rage128 */ + ATI_CHIP_RAGE128MOBILITY4, /* Rage128 */ + ATI_CHIP_Rage128, /* Last among Rage128's */ + ATI_CHIP_RADEON, /* Radeon */ + ATI_CHIP_RADEONVE, /* Radeon VE */ + ATI_CHIP_RADEONMOBILITY6, /* Radeon M6 */ + ATI_CHIP_RS100, /* IGP320 */ + ATI_CHIP_RS200, /* IGP340 */ + ATI_CHIP_RS250, /* Radoen 7000 IGP */ + ATI_CHIP_RV200, /* RV200 */ + ATI_CHIP_RADEONMOBILITY7, /* Radeon M7 */ + ATI_CHIP_R200, /* R200 */ + ATI_CHIP_RV250, /* RV250 */ + ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */ + 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/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/M28? */ + ATI_CHIP_R430, /* R430 */ + ATI_CHIP_R480, /* R480/M28? */ + ATI_CHIP_R481, /* R481 */ + ATI_CHIP_RV410, /* RV410, M26 */ + ATI_CHIP_RS400, /* RS400, RS410, RS480, RS482, ... */ + ATI_CHIP_Radeon, /* Last among Radeon's */ + ATI_CHIP_HDTV /* HDTV */ +} ATIChipType; + +extern const char *ATIChipNames[]; + +extern ATIChipType ATIChipID(const CARD16, const CARD8); + #endif /* ___ATI_H___ */ diff --git a/src/atiadjust.c b/src/atiadjust.c index f01fee69..267186f4 100644 --- a/src/atiadjust.c +++ b/src/atiadjust.c @@ -82,7 +82,7 @@ ATIAdjustPreInit * displayed location in video memory. This is used to implement the virtual * window. */ -_X_EXPORT void +void ATIAdjustFrame ( int scrnIndex, diff --git a/src/atichip.c b/src/atichip.c index ddc7e0a7..5f8a2216 100644 --- a/src/atichip.c +++ b/src/atichip.c @@ -30,74 +30,6 @@ #include "atimach64io.h" #include "ativersion.h" -/* - * Chip-related definitions. - */ -const char *ATIChipNames[] = -{ - "Unknown", - "ATI 88800GX-C", - "ATI 88800GX-D", - "ATI 88800GX-E", - "ATI 88800GX-F", - "ATI 88800GX", - "ATI 88800CX", - "ATI 264CT", - "ATI 264ET", - "ATI 264VT", - "ATI 3D Rage", - "ATI 264VT-B", - "ATI 3D Rage II", - "ATI 264VT3", - "ATI 3D Rage II+DVD", - "ATI 3D Rage LT", - "ATI 264VT4", - "ATI 3D Rage IIc", - "ATI 3D Rage Pro", - "ATI 3D Rage LT Pro", - "ATI 3D Rage XL or XC", - "ATI 3D Rage Mobility", - "ATI unknown Mach64", - "ATI Rage 128 GL", - "ATI Rage 128 VR", - "ATI Rage 128 Pro GL", - "ATI Rage 128 Pro VR", - "ATI Rage 128 Pro ULTRA", - "ATI Rage 128 Mobility M3", - "ATI Rage 128 Mobility M4", - "ATI unknown Rage 128" - "ATI Radeon 7200", - "ATI Radeon 7000 (VE)", - "ATI Radeon Mobility M6", - "ATI Radeon IGP320", - "ATI Radeon IGP330/340/350", - "ATI Radeon 7000 IGP", - "ATI Radeon 7500", - "ATI Radeon Mobility M7", - "ATI Radeon 8500/9100", - "ATI Radeon 9000", - "ATI Radeon Mobility M9", - "ATI Radeon 9100 IGP", - "ATI Radeon 9200 IGP", - "ATI Radeon 9200", - "ATI Radeon Mobility M9+", - "ATI Radeon 9700/9500", - "ATI Radeon 9600/9550", - "ATI Radeon 9800", - "ATI Radeon 9800XT", - "ATI Radeon X300/X550/M22", - "ATI Radeon X600/X550/M24", - "ATI Radeon X800/M18 AGP", - "ATI Radeon X800/M28 PCIE", - "ATI Radeon X800XL PCIE", - "ATI Radeon X850 PCIE", - "ATI Radeon X850 AGP", - "ATI Radeon X700", - "ATI Xpress 200" - "ATI unknown Radeon", - "ATI Rage HDTV" -}; - const char *ATIFoundryNames[] = { "SGS", "NEC", "KCS", "UMC", "TSMC", "5", "6", "UMC" }; @@ -115,18 +47,18 @@ ATIMach64ChipID ) { pATI->config_chip_id = inr(CONFIG_CHIP_ID); - pATI->ChipType = GetBits(pATI->config_chip_id, 0xFFFFU); + pATI->ChipType = GetBits(pATI->config_chip_id, CFG_CHIP_TYPE); pATI->ChipClass = GetBits(pATI->config_chip_id, CFG_CHIP_CLASS); - pATI->ChipRevision = GetBits(pATI->config_chip_id, CFG_CHIP_REV); + pATI->ChipRev = GetBits(pATI->config_chip_id, CFG_CHIP_REV); pATI->ChipVersion = GetBits(pATI->config_chip_id, CFG_CHIP_VERSION); pATI->ChipFoundry = GetBits(pATI->config_chip_id, CFG_CHIP_FOUNDRY); - pATI->ChipRev = pATI->ChipRevision; + pATI->ChipRevision = GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); switch (pATI->ChipType) { case OldChipID('G', 'X'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'X'): - switch (pATI->ChipRevision) + switch (pATI->ChipRev) { case 0x00U: pATI->Chip = ATI_CHIP_88800GXC; @@ -159,8 +91,6 @@ ATIMach64ChipID case OldChipID('C', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('C', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264CT; pATI->BusType = ATI_BUS_PCI; break; @@ -168,8 +98,6 @@ ATIMach64ChipID case OldChipID('E', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('E', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264ET; pATI->BusType = ATI_BUS_PCI; break; @@ -177,8 +105,6 @@ ATIMach64ChipID case OldChipID('V', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('V', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264VT; pATI->BusType = ATI_BUS_PCI; /* Some early GT's are detected as VT's */ @@ -199,8 +125,6 @@ ATIMach64ChipID case OldChipID('G', 'T'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'T'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->BusType = ATI_BUS_PCI; if (!pATI->ChipVersion) pATI->Chip = ATI_CHIP_264GT; @@ -211,8 +135,6 @@ ATIMach64ChipID case OldChipID('V', 'U'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('V', 'U'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264VT3; pATI->BusType = ATI_BUS_PCI; break; @@ -220,8 +142,6 @@ ATIMach64ChipID case OldChipID('G', 'U'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'U'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GTDVD; pATI->BusType = ATI_BUS_PCI; break; @@ -229,8 +149,6 @@ ATIMach64ChipID case OldChipID('L', 'G'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'G'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264LT; pATI->BusType = ATI_BUS_PCI; break; @@ -238,8 +156,6 @@ ATIMach64ChipID case OldChipID('V', 'V'): pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('V', 'V'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264VT4; pATI->BusType = ATI_BUS_PCI; break; @@ -249,8 +165,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'V'): case NewChipID('G', 'Y'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GT2C; pATI->BusType = ATI_BUS_PCI; break; @@ -260,8 +174,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'W'): case NewChipID('G', 'Z'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GT2C; pATI->BusType = ATI_BUS_AGP; break; @@ -273,8 +185,6 @@ ATIMach64ChipID case NewChipID('G', 'I'): case NewChipID('G', 'P'): case NewChipID('G', 'Q'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GTPRO; pATI->BusType = ATI_BUS_PCI; break; @@ -284,8 +194,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'B'): case NewChipID('G', 'D'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264GTPRO; pATI->BusType = ATI_BUS_AGP; break; @@ -297,8 +205,6 @@ ATIMach64ChipID case NewChipID('L', 'I'): case NewChipID('L', 'P'): case NewChipID('L', 'Q'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264LTPRO; pATI->BusType = ATI_BUS_PCI; pATI->LCDVBlendFIFOSize = 800; @@ -309,8 +215,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'B'): case NewChipID('L', 'D'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264LTPRO; pATI->BusType = ATI_BUS_AGP; pATI->LCDVBlendFIFOSize = 800; @@ -325,8 +229,6 @@ ATIMach64ChipID case NewChipID('G', 'O'): case NewChipID('G', 'R'): case NewChipID('G', 'S'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264XL; pATI->BusType = ATI_BUS_PCI; pATI->LCDVBlendFIFOSize = 1024; @@ -337,8 +239,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('G', 'M'): case NewChipID('G', 'N'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_264XL; pATI->BusType = ATI_BUS_AGP; pATI->LCDVBlendFIFOSize = 1024; @@ -349,8 +249,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'R'): case NewChipID('L', 'S'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_MOBILITY; pATI->BusType = ATI_BUS_PCI; pATI->LCDVBlendFIFOSize = 1024; @@ -361,8 +259,6 @@ ATIMach64ChipID pATI->ChipType = OldToNewChipID(pATI->ChipType); case NewChipID('L', 'M'): case NewChipID('L', 'N'): - pATI->ChipRevision = - GetBits(pATI->config_chip_id, CFG_CHIP_REVISION); pATI->Chip = ATI_CHIP_MOBILITY; pATI->BusType = ATI_BUS_AGP; pATI->LCDVBlendFIFOSize = 1024; @@ -373,399 +269,3 @@ ATIMach64ChipID break; } } - -/* - * ATIChipID -- - * - * This returns the ATI_CHIP_* value (generally) associated with a particular - * ChipID/ChipRev combination. - */ -ATIChipType -ATIChipID -( - const CARD16 ChipID, - const CARD8 ChipRev -) -{ - switch (ChipID) - { - case OldChipID('G', 'X'): case NewChipID('G', 'X'): - switch (ChipRev) - { - case 0x00U: - return ATI_CHIP_88800GXC; - - case 0x01U: - return ATI_CHIP_88800GXD; - - case 0x02U: - return ATI_CHIP_88800GXE; - - case 0x03U: - return ATI_CHIP_88800GXF; - - default: - return ATI_CHIP_88800GX; - } - - case OldChipID('C', 'X'): case NewChipID('C', 'X'): - return ATI_CHIP_88800CX; - - case OldChipID('C', 'T'): case NewChipID('C', 'T'): - return ATI_CHIP_264CT; - - case OldChipID('E', 'T'): case NewChipID('E', 'T'): - return ATI_CHIP_264ET; - - case OldChipID('V', 'T'): case NewChipID('V', 'T'): - /* For simplicity, ignore ChipID discrepancy that can occur here */ - if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) - return ATI_CHIP_264VT; - return ATI_CHIP_264VTB; - - case OldChipID('G', 'T'): case NewChipID('G', 'T'): - if (!(ChipRev & GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV))) - return ATI_CHIP_264GT; - return ATI_CHIP_264GTB; - - case OldChipID('V', 'U'): case NewChipID('V', 'U'): - return ATI_CHIP_264VT3; - - case OldChipID('G', 'U'): case NewChipID('G', 'U'): - return ATI_CHIP_264GTDVD; - - case OldChipID('L', 'G'): case NewChipID('L', 'G'): - return ATI_CHIP_264LT; - - case OldChipID('V', 'V'): case NewChipID('V', 'V'): - return ATI_CHIP_264VT4; - - case OldChipID('G', 'V'): case NewChipID('G', 'V'): - case OldChipID('G', 'W'): case NewChipID('G', 'W'): - case OldChipID('G', 'Y'): case NewChipID('G', 'Y'): - case OldChipID('G', 'Z'): case NewChipID('G', 'Z'): - return ATI_CHIP_264GT2C; - - case OldChipID('G', 'B'): case NewChipID('G', 'B'): - case OldChipID('G', 'D'): case NewChipID('G', 'D'): - case OldChipID('G', 'I'): case NewChipID('G', 'I'): - case OldChipID('G', 'P'): case NewChipID('G', 'P'): - case OldChipID('G', 'Q'): case NewChipID('G', 'Q'): - return ATI_CHIP_264GTPRO; - - case OldChipID('L', 'B'): case NewChipID('L', 'B'): - case OldChipID('L', 'D'): case NewChipID('L', 'D'): - case OldChipID('L', 'I'): case NewChipID('L', 'I'): - case OldChipID('L', 'P'): case NewChipID('L', 'P'): - case OldChipID('L', 'Q'): case NewChipID('L', 'Q'): - return ATI_CHIP_264LTPRO; - - case OldChipID('G', 'L'): case NewChipID('G', 'L'): - case OldChipID('G', 'M'): case NewChipID('G', 'M'): - case OldChipID('G', 'N'): case NewChipID('G', 'N'): - case OldChipID('G', 'O'): case NewChipID('G', 'O'): - case OldChipID('G', 'R'): case NewChipID('G', 'R'): - case OldChipID('G', 'S'): case NewChipID('G', 'S'): - return ATI_CHIP_264XL; - - case OldChipID('L', 'M'): case NewChipID('L', 'M'): - case OldChipID('L', 'N'): case NewChipID('L', 'N'): - case OldChipID('L', 'R'): case NewChipID('L', 'R'): - case OldChipID('L', 'S'): case NewChipID('L', 'S'): - return ATI_CHIP_MOBILITY; - - case NewChipID('R', 'E'): - case NewChipID('R', 'F'): - case NewChipID('R', 'G'): - case NewChipID('S', 'K'): - case NewChipID('S', 'L'): - case NewChipID('S', 'M'): - /* "SN" is listed as ATI_CHIP_RAGE128_4X in ATI docs */ - case NewChipID('S', 'N'): - return ATI_CHIP_RAGE128GL; - - case NewChipID('R', 'K'): - case NewChipID('R', 'L'): - /* - * ATI documentation lists SE/SF/SG under both ATI_CHIP_RAGE128VR - * and ATI_CHIP_RAGE128_4X, and lists SH/SK/SL under Rage 128 4X only. - * I'm stuffing them here for now until this can be clarified as ATI - * documentation doesn't mention their details. <mharris@redhat.com> - */ - case NewChipID('S', 'E'): - case NewChipID('S', 'F'): - case NewChipID('S', 'G'): - case NewChipID('S', 'H'): - return ATI_CHIP_RAGE128VR; - - /* case NewChipID('S', 'H'): */ - /* case NewChipID('S', 'K'): */ - /* case NewChipID('S', 'L'): */ - /* case NewChipID('S', 'N'): */ - /* return ATI_CHIP_RAGE128_4X; */ - - case NewChipID('P', 'A'): - case NewChipID('P', 'B'): - case NewChipID('P', 'C'): - case NewChipID('P', 'D'): - case NewChipID('P', 'E'): - case NewChipID('P', 'F'): - return ATI_CHIP_RAGE128PROGL; - - case NewChipID('P', 'G'): - case NewChipID('P', 'H'): - case NewChipID('P', 'I'): - case NewChipID('P', 'J'): - case NewChipID('P', 'K'): - case NewChipID('P', 'L'): - case NewChipID('P', 'M'): - case NewChipID('P', 'N'): - case NewChipID('P', 'O'): - case NewChipID('P', 'P'): - case NewChipID('P', 'Q'): - case NewChipID('P', 'R'): - case NewChipID('P', 'S'): - case NewChipID('P', 'T'): - case NewChipID('P', 'U'): - case NewChipID('P', 'V'): - case NewChipID('P', 'W'): - case NewChipID('P', 'X'): - return ATI_CHIP_RAGE128PROVR; - - case NewChipID('T', 'F'): - case NewChipID('T', 'L'): - case NewChipID('T', 'R'): - case NewChipID('T', 'S'): - case NewChipID('T', 'T'): - case NewChipID('T', 'U'): - return ATI_CHIP_RAGE128PROULTRA; - - case NewChipID('L', 'E'): - case NewChipID('L', 'F'): - /* - * "LK" and "LL" are not in any ATI documentation I can find - * - mharris - */ - case NewChipID('L', 'K'): - case NewChipID('L', 'L'): - return ATI_CHIP_RAGE128MOBILITY3; - - case NewChipID('M', 'F'): - case NewChipID('M', 'L'): - return ATI_CHIP_RAGE128MOBILITY4; - - case NewChipID('Q', 'D'): - case NewChipID('Q', 'E'): - case NewChipID('Q', 'F'): - case NewChipID('Q', 'G'): - return ATI_CHIP_RADEON; - - case NewChipID('Q', 'Y'): - case NewChipID('Q', 'Z'): - case NewChipID('Q', '^'): - return ATI_CHIP_RADEONVE; - - case NewChipID('L', 'Y'): - case NewChipID('L', 'Z'): - return ATI_CHIP_RADEONMOBILITY6; - - case NewChipID('A', '6'): - case NewChipID('C', '6'): - return ATI_CHIP_RS100; - - case NewChipID('A', '7'): - case NewChipID('C', '7'): - return ATI_CHIP_RS200; - - case NewChipID('D', '7'): - case NewChipID('B', '7'): - return ATI_CHIP_RS250; - - case NewChipID('L', 'W'): - case NewChipID('L', 'X'): - return ATI_CHIP_RADEONMOBILITY7; - - case NewChipID('Q', 'H'): - case NewChipID('Q', 'I'): - case NewChipID('Q', 'J'): - case NewChipID('Q', 'K'): - case NewChipID('Q', 'L'): - case NewChipID('Q', 'M'): - case NewChipID('Q', 'N'): - case NewChipID('Q', 'O'): - case NewChipID('Q', 'h'): - case NewChipID('Q', 'i'): - case NewChipID('Q', 'j'): - case NewChipID('Q', 'k'): - case NewChipID('Q', 'l'): - case NewChipID('B', 'B'): - return ATI_CHIP_R200; - - case NewChipID('Q', 'W'): - case NewChipID('Q', 'X'): - return ATI_CHIP_RV200; - - case NewChipID('I', 'f'): - case NewChipID('I', 'g'): - return ATI_CHIP_RV250; - - case NewChipID('L', 'd'): - case NewChipID('L', 'f'): - case NewChipID('L', 'g'): - return ATI_CHIP_RADEONMOBILITY9; - - case NewChipID('X', '4'): - 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'): - case NewChipID('Y', 'd'): - case NewChipID('Y', 'e'): - return ATI_CHIP_RV280; - - case NewChipID('\\', 'a'): - case NewChipID('\\', 'c'): - return ATI_CHIP_RADEONMOBILITY9PLUS; - - case NewChipID('A', 'D'): - case NewChipID('A', 'E'): - case NewChipID('A', 'F'): - case NewChipID('A', 'G'): - case NewChipID('N', 'D'): - case NewChipID('N', 'E'): - case NewChipID('N', 'F'): - case NewChipID('N', 'G'): - return ATI_CHIP_R300; - - case NewChipID('A', 'H'): - case NewChipID('A', 'I'): - case NewChipID('A', 'J'): - case NewChipID('A', 'K'): - case NewChipID('N', 'H'): - case NewChipID('N', 'I'): - case NewChipID('N', 'K'): - return ATI_CHIP_R350; - - case NewChipID('A', 'P'): - case NewChipID('A', 'Q'): - case NewChipID('A', 'R'): - case NewChipID('A', 'S'): - case NewChipID('A', 'T'): - case NewChipID('A', 'U'): - case NewChipID('A', 'V'): - case NewChipID('N', 'P'): - case NewChipID('N', 'Q'): - case NewChipID('N', 'R'): - case NewChipID('N', 'S'): - case NewChipID('N', 'T'): - case NewChipID('N', 'V'): - return ATI_CHIP_RV350; - - case NewChipID('N', 'J'): - return ATI_CHIP_R360; - - case NewChipID('[', '\''): - case NewChipID('[', 'b'): - case NewChipID('[', 'c'): - case NewChipID('[', 'd'): - case NewChipID('[', 'e'): - case NewChipID('T', '\''): - case NewChipID('T', 'b'): - case NewChipID('T', 'd'): - return ATI_CHIP_RV370; - - case NewChipID('>', 'P'): - case NewChipID('>', 'T'): - case NewChipID('1', 'P'): - case NewChipID('1', 'R'): - 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', 'O'): - case NewChipID('J', 'P'): - case NewChipID('J', 'T'): - return ATI_CHIP_R420; - - case NewChipID('U', 'H'): - case NewChipID('U', 'I'): - case NewChipID('U', 'J'): - case NewChipID('U', 'K'): - case NewChipID('U', 'P'): - case NewChipID('U', 'Q'): - case NewChipID('U', 'R'): - case NewChipID('U', 'T'): - case NewChipID(']', 'W'): - /* those are m28, not 100% certain they are r423 could - be r480 but not r430 as their pci id names indicate... */ - case NewChipID(']', 'H'): - case NewChipID(']', 'I'): - case NewChipID(']', 'J'): - return ATI_CHIP_R423; - - case NewChipID('U', 'L'): - case NewChipID('U', 'M'): - case NewChipID('U', 'N'): - case NewChipID('U', 'O'): - return ATI_CHIP_R430; - - case NewChipID(']', 'L'): - case NewChipID(']', 'M'): - case NewChipID(']', 'N'): - case NewChipID(']', 'O'): - case NewChipID(']', 'P'): - case NewChipID(']', 'R'): - return ATI_CHIP_R480; - - case NewChipID('K', 'I'): - case NewChipID('K', 'J'): - case NewChipID('K', 'K'): - case NewChipID('K', 'L'): - return ATI_CHIP_R481; - - case NewChipID('^', 'H'): - case NewChipID('^', 'J'): - case NewChipID('^', 'K'): - case NewChipID('^', 'L'): - case NewChipID('^', 'M'): - case NewChipID('^', 'O'): - case NewChipID('V', 'J'): - case NewChipID('V', 'K'): - case NewChipID('V', 'O'): - case NewChipID('V', 'R'): - case NewChipID('V', 'S'): - return ATI_CHIP_RV410; - - case NewChipID('Z', 'A'): - case NewChipID('Z', 'B'): - case NewChipID('Z', 'a'): - case NewChipID('Z', 'b'): - case NewChipID('Y', 'T'): - case NewChipID('Y', 'U'): - case NewChipID('Y', 't'): - case NewChipID('Y', 'u'): - return ATI_CHIP_RS400; - - case NewChipID('H', 'D'): - return ATI_CHIP_HDTV; - - default: - /* - * Treat anything else as an unknown Radeon. Please keep the above - * up-to-date however, as it serves as a central chip list. - */ - return ATI_CHIP_Radeon; - } -} diff --git a/src/atichip.h b/src/atichip.h index 733c7b1f..44cd1888 100644 --- a/src/atichip.h +++ b/src/atichip.h @@ -29,76 +29,6 @@ #include <X11/Xmd.h> /* - * Chip-related definitions. - */ -typedef enum -{ - ATI_CHIP_NONE = 0, - ATI_CHIP_88800GXC, /* Mach64 */ - ATI_CHIP_88800GXD, /* Mach64 */ - ATI_CHIP_88800GXE, /* Mach64 */ - ATI_CHIP_88800GXF, /* Mach64 */ - ATI_CHIP_88800GX, /* Mach64 */ - ATI_CHIP_88800CX, /* Mach64 */ - ATI_CHIP_264CT, /* Mach64 */ - ATI_CHIP_264ET, /* Mach64 */ - ATI_CHIP_264VT, /* Mach64 */ - ATI_CHIP_264GT, /* Mach64 */ - ATI_CHIP_264VTB, /* Mach64 */ - ATI_CHIP_264GTB, /* Mach64 */ - ATI_CHIP_264VT3, /* Mach64 */ - ATI_CHIP_264GTDVD, /* Mach64 */ - ATI_CHIP_264LT, /* Mach64 */ - ATI_CHIP_264VT4, /* Mach64 */ - ATI_CHIP_264GT2C, /* Mach64 */ - ATI_CHIP_264GTPRO, /* Mach64 */ - ATI_CHIP_264LTPRO, /* Mach64 */ - ATI_CHIP_264XL, /* Mach64 */ - ATI_CHIP_MOBILITY, /* Mach64 */ - ATI_CHIP_Mach64, /* Last among Mach64's */ - ATI_CHIP_RAGE128GL, /* Rage128 */ - ATI_CHIP_RAGE128VR, /* Rage128 */ - ATI_CHIP_RAGE128PROGL, /* Rage128 */ - ATI_CHIP_RAGE128PROVR, /* Rage128 */ - ATI_CHIP_RAGE128PROULTRA, /* Rage128 */ - ATI_CHIP_RAGE128MOBILITY3, /* Rage128 */ - ATI_CHIP_RAGE128MOBILITY4, /* Rage128 */ - ATI_CHIP_Rage128, /* Last among Rage128's */ - ATI_CHIP_RADEON, /* Radeon */ - ATI_CHIP_RADEONVE, /* Radeon VE */ - ATI_CHIP_RADEONMOBILITY6, /* Radeon M6 */ - ATI_CHIP_RS100, /* IGP320 */ - ATI_CHIP_RS200, /* IGP340 */ - ATI_CHIP_RS250, /* Radoen 7000 IGP */ - ATI_CHIP_RV200, /* RV200 */ - ATI_CHIP_RADEONMOBILITY7, /* Radeon M7 */ - ATI_CHIP_R200, /* R200 */ - ATI_CHIP_RV250, /* RV250 */ - ATI_CHIP_RADEONMOBILITY9, /* Radeon M9 */ - 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/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/M28? */ - ATI_CHIP_R430, /* R430 */ - ATI_CHIP_R480, /* R480/M28? */ - ATI_CHIP_R481, /* R481 */ - ATI_CHIP_RV410, /* RV410, M26 */ - ATI_CHIP_RS400, /* RS400, RS410, RS480, RS482, ... */ - ATI_CHIP_Radeon, /* Last among Radeon's */ - ATI_CHIP_HDTV /* HDTV */ -} ATIChipType; - -extern const char *ATIChipNames[]; - -/* * Foundry codes for 264xT's. */ typedef enum @@ -116,7 +46,6 @@ typedef enum extern const char *ATIFoundryNames[]; extern void ATIMach64ChipID(ATIPtr, const CARD16); -extern ATIChipType ATIChipID(const CARD16, const CARD8); #define OldChipID(_1, _0) \ (SetBits(_0 - 'A', CHIP_CODE_0) | SetBits(_1 - 'A', CHIP_CODE_1)) diff --git a/src/aticonfig.c b/src/aticonfig.c index a4ceddfc..1e119e00 100644 --- a/src/aticonfig.c +++ b/src/aticonfig.c @@ -234,7 +234,7 @@ static const OptionInfoRec ATIPublicOptions[] = static const unsigned long ATIPublicOptionSize = SizeOf(ATIPublicOptions); -_X_EXPORT const OptionInfoRec * +const OptionInfoRec * ATIOptionsWeak(void) { return ATIPublicOptions; } /* diff --git a/src/aticonsole.c b/src/aticonsole.c index 6d0c662a..bd5ec9c5 100644 --- a/src/aticonsole.c +++ b/src/aticonsole.c @@ -628,7 +628,7 @@ ATILeaveGraphics * * This function switches to another graphics video state. */ -_X_EXPORT Bool +Bool ATISwitchMode ( int iScreen, @@ -681,7 +681,7 @@ ATISwitchMode * * This function sets the server's virtual console to a graphics video state. */ -_X_EXPORT Bool +Bool ATIEnterVT ( int iScreen, @@ -751,7 +751,7 @@ ATIEnterVT * This function restores the server's virtual console to its state on server * entry. */ -_X_EXPORT void +void ATILeaveVT ( int iScreen, @@ -780,7 +780,7 @@ ATILeaveVT * * This function frees all driver data related to a screen. */ -_X_EXPORT void +void ATIFreeScreen ( int iScreen, diff --git a/src/atidri.c b/src/atidri.c index d017040c..bc862a89 100644 --- a/src/atidri.c +++ b/src/atidri.c @@ -1194,13 +1194,13 @@ Bool ATIDRIScreenInit( ScreenPtr pScreen ) /* Check the DRI version */ DRIQueryVersion( &major, &minor, &patch ); - if ( major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION ) { + if ( major != DRIINFO_MAJOR_VERSION || 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 %d.%d.x is needed.\n" "[dri] Disabling the DRI.\n", major, minor, patch, - DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION ); + DRIINFO_MAJOR_VERSION, 0 ); return FALSE; } @@ -1266,9 +1266,10 @@ Bool ATIDRIScreenInit( ScreenPtr pScreen ) 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) ); + xf86DrvMsg( pScreenInfo->scrnIndex, X_INFO, "[drm] SAREA %u+%u: %u\n", + (unsigned)sizeof(XF86DRISAREARec), + (unsigned)sizeof(ATISAREAPrivRec), + (unsigned)(sizeof(XF86DRISAREARec) + sizeof(ATISAREAPrivRec)) ); pDRIInfo->SAREASize = SAREA_MAX; pATIDRI = (ATIDRIPtr) xnfcalloc( sizeof(ATIDRIRec), 1 ); diff --git a/src/atifillin.c b/src/atifillin.c deleted file mode 100644 index dcbcb3c8..00000000 --- a/src/atifillin.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2004 Adam Jackson. - * - * 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, sub - * license, 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 - * THE AUTHORS 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. - */ - -/* - * atifillin.c: fill in a ScrnInfoPtr with the relevant information for - * atimisc. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "atifillin.h" - -_X_EXPORT void ATIFillInScreenInfo(ScrnInfoPtr pScreenInfo) -{ - pScreenInfo->driverVersion = ATI_VERSION_CURRENT; - pScreenInfo->driverName = ATI_DRIVER_NAME; - pScreenInfo->name = ATI_NAME; - 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 deleted file mode 100644 index 7d5e54da..00000000 --- a/src/atifillin.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2004 Adam Jackson. - * - * 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, sub - * license, 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 - * THE AUTHORS 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. - */ - -/* - * atifillin.h: header for atifillin.c. - */ - -#ifndef ATI_FILLIN_H -#define ATI_FILLIN_H - -/* include headers corresponding to fields touched by ATIFillInScreenInfo() */ - -#include "ativersion.h" -#include "atipreinit.h" -#include "atiscreen.h" -#include "aticonsole.h" -#include "atiadjust.h" -#include "ativalid.h" - -extern void ATIFillInScreenInfo(ScrnInfoPtr); - -#endif diff --git a/src/atimach64probe.c b/src/atimach64probe.c index 47340a56..c5330cc7 100644 --- a/src/atimach64probe.c +++ b/src/atimach64probe.c @@ -26,14 +26,19 @@ #include "ati.h" #include "atichip.h" -#include "atifillin.h" -#include "atimodule.h" #include "atimach64io.h" #include "atimach64probe.h" #include "atioption.h" #include "ativersion.h" -static SymTabRec +/* include headers corresponding to ScrnInfoPtr fields */ +#include "atipreinit.h" +#include "atiscreen.h" +#include "aticonsole.h" +#include "atiadjust.h" +#include "ativalid.h" + +SymTabRec Mach64Chipsets[] = { {ATI_CHIP_88800GXC, "ATI 88800GX-C"}, {ATI_CHIP_88800GXD, "ATI 88800GX-D"}, @@ -101,7 +106,7 @@ Mach64PciChipsets[] = { {-1, -1, RES_UNDEFINED} }; -const OptionInfoRec * +_X_EXPORT const OptionInfoRec * Mach64AvailableOptions(int chipid, int busid) { /* @@ -112,24 +117,39 @@ Mach64AvailableOptions(int chipid, int busid) } /* + * Mach64Identify -- + * + * Print the driver's list of chipset names. + */ +_X_EXPORT void +Mach64Identify +( + int flags +) +{ + xf86Msg(X_INFO, "%s: %s\n", ATI_NAME, + "Driver for ATI Mach64 chipsets"); +} + +/* * Mach64Probe -- * * This function is called once, at the start of the first server generation to * do a minimal probe for supported hardware. */ -Bool +_X_EXPORT Bool Mach64Probe(DriverPtr pDriver, int flags) { - GDevPtr *devSections; - int *usedChips; - int numDevSections; - int numUsed; - Bool ProbeSuccess = FALSE; + GDevPtr *devSections; + int *usedChips; + int numDevSections; + int numUsed; + Bool ProbeSuccess = FALSE; - if ((numDevSections = xf86MatchDevice(ATI_DRIVER_NAME, &devSections)) <= 0) + if (xf86GetPciVideoInfo() == NULL) return FALSE; - if (xf86GetPciVideoInfo() == NULL) + if ((numDevSections = xf86MatchDevice(ATI_DRIVER_NAME, &devSections)) <= 0) return FALSE; numUsed = xf86MatchPciInstances(ATI_DRIVER_NAME, PCI_VENDOR_ATI, @@ -148,8 +168,6 @@ Mach64Probe(DriverPtr pDriver, int flags) for (i = 0; i < numUsed; i++) { ScrnInfoPtr pScrn; - EntityInfoPtr pEnt; - pciVideoPtr pVideo; pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i], Mach64PciChipsets, 0, 0, 0, 0, NULL); @@ -157,30 +175,24 @@ Mach64Probe(DriverPtr pDriver, int flags) if (!pScrn) continue; - pEnt = xf86GetEntityInfo(usedChips[i]); - pVideo = xf86GetPciInfoForEntity(usedChips[i]); - -#ifdef XFree86LOADER - - if (!xf86LoadSubModule(pScrn, "atimisc")) - { - xf86Msg(X_ERROR, - ATI_NAME ": Failed to load \"atimisc\" module.\n"); - xf86DeleteScreen(pScrn->scrnIndex, 0); - continue; - } - - xf86LoaderReqSymLists(ATISymbols, NULL); - -#endif - - ATIFillInScreenInfo(pScrn); - - pScrn->Probe = Mach64Probe; + pScrn->driverVersion = ATI_VERSION_CURRENT; + pScrn->driverName = ATI_DRIVER_NAME; + pScrn->name = ATI_NAME; + pScrn->Probe = Mach64Probe; + pScrn->PreInit = ATIPreInit; + pScrn->ScreenInit = ATIScreenInit; + pScrn->SwitchMode = ATISwitchMode; + pScrn->AdjustFrame = ATIAdjustFrame; + pScrn->EnterVT = ATIEnterVT; + pScrn->LeaveVT = ATILeaveVT; + pScrn->FreeScreen = ATIFreeScreen; + pScrn->ValidMode = ATIValidMode; ProbeSuccess = TRUE; } } + xfree(usedChips); + return ProbeSuccess; } diff --git a/src/atimach64probe.h b/src/atimach64probe.h index 4e474ca3..65ced985 100644 --- a/src/atimach64probe.h +++ b/src/atimach64probe.h @@ -25,7 +25,10 @@ #include "xf86str.h" +extern SymTabRec Mach64Chipsets[]; + extern const OptionInfoRec * Mach64AvailableOptions(int, int); +extern void Mach64Identify(int); extern Bool Mach64Probe(DriverPtr, int); #endif /* ___ATIMACH64PROBE_H___ */ diff --git a/src/atimach64xv.c b/src/atimach64xv.c index 997fa699..67bececf 100644 --- a/src/atimach64xv.c +++ b/src/atimach64xv.c @@ -979,6 +979,9 @@ ATIMach64PutImage if (pATI->ActiveSurface) return Success; + if (DstH < 16) + return Success; + if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID, SrcX, SrcY, SrcW, SrcH, DstX, DstY, &DstW, &DstH, diff --git a/src/atimodule.c b/src/atimodule.c index 05456e7c..6aa9a2e7 100644 --- a/src/atimodule.c +++ b/src/atimodule.c @@ -34,47 +34,25 @@ const char *ATISymbols[] = { - "ATIPreInit", - "ATIScreenInit", - "ATISwitchMode", - "ATIAdjustFrame", - "ATIEnterVT", - "ATILeaveVT", - "ATIFreeScreen", - "ATIValidMode", - "ATIOptionsWeak", - "ATIFillInScreenInfo", + "Mach64Identify", + "Mach64Probe", + "Mach64AvailableOptions", NULL }; const char *R128Symbols[] = { - "R128PreInit", - "R128ScreenInit", - "R128SwitchMode", - "R128AdjustFrame", - "R128EnterVT", - "R128LeaveVT", - "R128FreeScreen", - "R128ValidMode", - "R128OptionsWeak", - "R128FillInScreenInfo", + "R128Identify", + "R128Probe", + "R128AvailableOptions", NULL }; const char *RADEONSymbols[] = { - "RADEONPreInit", - "RADEONScreenInit", - "RADEONSwitchMode", - "RADEONAdjustFrame", - "RADEONEnterVT", - "RADEONLeaveVT", - "RADEONFreeScreen", - "RADEONValidMode", - "RADEONOptionsWeak", - "RADEONHandleMessage", - "RADEONFillInScreenInfo", + "RADEONIdentify", + "RADEONProbe", + "RADEONAvailableOptions", NULL }; diff --git a/src/atipreinit.c b/src/atipreinit.c index 018f2fb1..8114f512 100644 --- a/src/atipreinit.c +++ b/src/atipreinit.c @@ -41,6 +41,7 @@ #include "atimach64.h" #include "atimach64accel.h" #include "atimach64io.h" +#include "atimach64probe.h" #include "atimode.h" #include "atioption.h" #include "atipreinit.h" @@ -128,7 +129,7 @@ ATIPrintNoiseIfRequested * This function is only called once per screen at the start of the first * server generation. */ -_X_EXPORT Bool +Bool ATIPreInit ( ScrnInfoPtr pScreenInfo, @@ -955,7 +956,8 @@ ATIPreInit /* Report what was found */ xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, - "%s graphics controller detected.\n", ATIChipNames[pATI->Chip]); + "%s graphics controller detected.\n", + xf86TokenToString(Mach64Chipsets, pATI->Chip)); { Message = Buffer + snprintf(Buffer, SizeOf(Buffer), "Chip type %04X", diff --git a/src/atiprobe.c b/src/atiprobe.c index b82ea5f8..cddcc613 100644 --- a/src/atiprobe.c +++ b/src/atiprobe.c @@ -31,7 +31,6 @@ #include "atibus.h" #include "atichip.h" #include "atimach64io.h" -#include "atimodule.h" #include "atiprobe.h" #include "ativersion.h" #include "atividmem.h" diff --git a/src/atiscreen.c b/src/atiscreen.c index 58b0bdaa..bc579347 100644 --- a/src/atiscreen.c +++ b/src/atiscreen.c @@ -349,7 +349,7 @@ ATIMach64SetupMemXAA * * This function is called by DIX to initialise the screen. */ -_X_EXPORT Bool +Bool ATIScreenInit ( int iScreen, diff --git a/src/ativalid.c b/src/ativalid.c index 8a92e82e..51cf5ae8 100644 --- a/src/ativalid.c +++ b/src/ativalid.c @@ -35,7 +35,7 @@ * * This checks for hardware-related limits on mode timings. */ -_X_EXPORT ModeStatus +ModeStatus ATIValidMode ( int iScreen, diff --git a/src/local_xf86Rename.h b/src/local_xf86Rename.h new file mode 100644 index 00000000..51021709 --- /dev/null +++ b/src/local_xf86Rename.h @@ -0,0 +1,23 @@ +/* + * Copyright © 2006 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * 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. + */ + +#define XF86NAME(x) radeon_##x diff --git a/src/r128_dri.c b/src/r128_dri.c index 21a13c17..fc91421d 100644 --- a/src/r128_dri.c +++ b/src/r128_dri.c @@ -988,13 +988,13 @@ Bool R128DRIScreenInit(ScreenPtr pScreen) /* Check the DRI version */ DRIQueryVersion(&major, &minor, &patch); - if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { + if (major != DRIINFO_MAJOR_VERSION || minor < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] R128DRIScreenInit failed because of a version mismatch.\n" "[dri] libdri version is %d.%d.%d but version %d.%d.x is needed.\n" "[dri] Disabling the DRI.\n", major, minor, patch, - DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); + DRIINFO_MAJOR_VERSION, 0); return FALSE; } diff --git a/src/r128_driver.c b/src/r128_driver.c index 81c9015c..6e26a6ef 100644 --- a/src/r128_driver.c +++ b/src/r128_driver.c @@ -182,7 +182,7 @@ static const OptionInfoRec R128Options[] = { { -1, NULL, OPTV_NONE, {0}, FALSE } }; -_X_EXPORT const OptionInfoRec *R128OptionsWeak(void) { return R128Options; } +const OptionInfoRec *R128OptionsWeak(void) { return R128Options; } R128RAMRec R128RAM[] = { /* Memory Specifications From RAGE 128 Software Development @@ -2044,7 +2044,7 @@ R128ProbeDDC(ScrnInfoPtr pScrn, int indx) } /* R128PreInit is called once at server startup. */ -_X_EXPORT Bool R128PreInit(ScrnInfoPtr pScrn, int flags) +Bool R128PreInit(ScrnInfoPtr pScrn, int flags) { R128InfoPtr info; xf86Int10InfoPtr pInt10 = NULL; @@ -2334,7 +2334,7 @@ R128BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) } /* Called at the start of each server generation. */ -_X_EXPORT Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, +Bool R128ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -4238,7 +4238,7 @@ static Bool R128SaveScreen(ScreenPtr pScreen, int mode) * The workaround is to switch the mode, then switch to another VT, then * switch back. --AGD */ -_X_EXPORT Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4251,12 +4251,15 @@ _X_EXPORT Bool R128SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } /* Used to disallow modes that are not supported by the hardware. */ -_X_EXPORT ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, +ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); + if (info->BIOSDisplay == R128_BIOS_DISPLAY_CRT) + return MODE_OK; + if(info->isDFP) { if(info->PanelXRes < mode->CrtcHDisplay || info->PanelYRes < mode->CrtcVDisplay) @@ -4327,7 +4330,7 @@ _X_EXPORT ModeStatus R128ValidMode(int scrnIndex, DisplayModePtr mode, /* Adjust viewport into virtual desktop such that (0,0) in viewport space is (x,y) in virtual space. */ -_X_EXPORT void R128AdjustFrame(int scrnIndex, int x, int y, int flags) +void R128AdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4363,7 +4366,7 @@ _X_EXPORT void R128AdjustFrame(int scrnIndex, int x, int y, int flags) /* Called when VT switching back to the X server. Reinitialize the video mode. */ -_X_EXPORT Bool R128EnterVT(int scrnIndex, int flags) +Bool R128EnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4396,7 +4399,7 @@ _X_EXPORT Bool R128EnterVT(int scrnIndex, int flags) /* Called when VT switching away from the X server. Restore the original text mode. */ -_X_EXPORT void R128LeaveVT(int scrnIndex, int flags) +void R128LeaveVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4466,7 +4469,7 @@ static Bool R128CloseScreen(int scrnIndex, ScreenPtr pScreen) return (*pScreen->CloseScreen)(scrnIndex, pScreen); } -_X_EXPORT void R128FreeScreen(int scrnIndex, int flags) +void R128FreeScreen(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; R128InfoPtr info = R128PTR(pScrn); @@ -4605,18 +4608,3 @@ static int r128_set_backlight_enable(ScrnInfoPtr pScrn, int on) return 0; } - -_X_EXPORT 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_probe.c b/src/r128_probe.c index 96e78974..81ff663a 100644 --- a/src/r128_probe.c +++ b/src/r128_probe.c @@ -41,7 +41,6 @@ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge. */ -#include "atimodule.h" #include "ativersion.h" #include "r128_probe.h" @@ -107,7 +106,7 @@ PciChipsets R128PciChipsets[] = { int gR128EntityIndex = -1; /* Return the options for supported chipset 'n'; NULL otherwise */ -const OptionInfoRec * +_X_EXPORT const OptionInfoRec * R128AvailableOptions(int chipid, int busid) { int i; @@ -126,7 +125,7 @@ R128AvailableOptions(int chipid, int busid) } /* Return the string name for supported chipset 'n'; NULL otherwise. */ -void +_X_EXPORT void R128Identify(int flags) { xf86PrintChipsets(R128_NAME, @@ -135,7 +134,7 @@ R128Identify(int flags) } /* Return TRUE if chipset is present; FALSE otherwise. */ -Bool +_X_EXPORT Bool R128Probe(DriverPtr drv, int flags) { int numUsed; @@ -194,22 +193,18 @@ R128Probe(DriverPtr drv, int flags) if((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], R128PciChipsets, 0, 0, 0, 0, 0))) { - -#ifdef XFree86LOADER - - if (!xf86LoadSubModule(pScrn, "r128")) { - xf86Msg(X_ERROR, - R128_NAME ": Failed to load \"r128\" module.\n"); - xf86DeleteScreen(pScrn->scrnIndex, 0); - continue; - } - - xf86LoaderReqSymLists(R128Symbols, NULL); - -#endif - + pScrn->driverVersion = R128_VERSION_CURRENT; + pScrn->driverName = R128_DRIVER_NAME; + pScrn->name = R128_NAME; pScrn->Probe = R128Probe; - R128FillInScreenInfo(pScrn); + pScrn->PreInit = R128PreInit; + pScrn->ScreenInit = R128ScreenInit; + pScrn->SwitchMode = R128SwitchMode; + pScrn->AdjustFrame = R128AdjustFrame; + pScrn->EnterVT = R128EnterVT; + pScrn->LeaveVT = R128LeaveVT; + pScrn->FreeScreen = R128FreeScreen; + pScrn->ValidMode = R128ValidMode; foundScreen = TRUE; diff --git a/src/r128_probe.h b/src/r128_probe.h index 91502963..180e52a9 100644 --- a/src/r128_probe.h +++ b/src/r128_probe.h @@ -73,6 +73,4 @@ extern ModeStatus R128ValidMode(int, DisplayModePtr, Bool, int); extern const OptionInfoRec * R128OptionsWeak(void); -extern void R128FillInScreenInfo(ScrnInfoPtr); - #endif /* _R128_PROBE_H_ */ diff --git a/src/radeon.h b/src/radeon.h index 5bb005b9..fa2bccdf 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -39,6 +39,7 @@ #include <stdlib.h> /* For abs() */ #include <unistd.h> /* For usleep() */ +#include <sys/time.h> /* For gettimeofday() */ #include "xf86str.h" #include "compiler.h" @@ -65,6 +66,8 @@ #include "xf86xv.h" #include "radeon_probe.h" +#include "radeon_tv.h" + /* DRI support */ #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -77,6 +80,9 @@ #endif #endif +#include "xf86Crtc.h" +#include "X11/Xatom.h" + /* Render support */ #ifdef RENDER #include "picturestr.h" @@ -115,21 +121,8 @@ typedef enum { OPTION_ACCEL_DFS, #endif #endif - OPTION_PANEL_OFF, OPTION_DDC_MODE, - OPTION_MONITOR_LAYOUT, OPTION_IGNORE_EDID, - OPTION_FBDEV, - OPTION_MERGEDFB, - OPTION_CRT2HSYNC, - OPTION_CRT2VREFRESH, - OPTION_CRT2POS, - OPTION_METAMODES, - OPTION_MERGEDDPI, - OPTION_RADEONXINERAMA, - OPTION_CRT2ISSCRN0, - OPTION_MERGEDFBNONRECT, - OPTION_MERGEDFBMOUSER, OPTION_DISP_PRIORITY, OPTION_PANEL_SIZE, OPTION_MIN_DOTCLOCK, @@ -157,39 +150,17 @@ typedef enum { OPTION_LVDS_PROBE_PLL, OPTION_ACCELMETHOD, OPTION_CONSTANTDPI, - OPTION_REVERSE_DISPLAY, - OPTION_DRI + OPTION_CONNECTORTABLE, + OPTION_DRI, + OPTION_DEFAULT_CONNECTOR_TABLE } RADEONOpts; -/* ------- mergedfb support ------------- */ - /* Psuedo Xinerama support */ -#define NEED_REPLIES /* ? */ -#define EXTENSION_PROC_ARGS void * -#include "extnsionst.h" /* required */ -#include <X11/extensions/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; - -typedef struct _region { - int x0,x1,y0,y1; -} region; -/* ------------------------------------- */ - -#define RADEON_DEBUG 1 /* 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 */ +#define RADEON_VSYNC_TIMEOUT 20000 /* Maximum wait for VSYNC (in usecs) */ + /* Buffer are aligned on 4096 byte boundaries */ #define RADEON_BUFFER_ALIGN 0x00000fff #define RADEON_VBIOS_SIZE 0x00010000 @@ -198,22 +169,28 @@ typedef struct _region { * for something else. */ -#if RADEON_DEBUG -#define RADEONTRACE(x) \ -do { \ - ErrorF("(**) %s(%d): ", RADEON_NAME, pScrn->scrnIndex); \ - ErrorF x; \ -} while(0) -#else -#define RADEONTRACE(x) do { } while(0) -#endif +#define RADEON_LOGLEVEL_DEBUG 4 +/* for Xv, outputs */ +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) /* Other macros */ #define RADEON_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) #define RADEON_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1)) #define RADEONPTR(pScrn) ((RADEONInfoPtr)(pScrn)->driverPrivate) +typedef struct { + int revision; + CARD16 rr1_offset; + CARD16 rr2_offset; + CARD16 dyn_clk_offset; + CARD16 pll_offset; + CARD16 mem_config_offset; + CARD16 mem_reset_offset; + CARD16 short_mem_offset; + CARD16 rr3_offset; + CARD16 rr4_offset; +} RADEONBIOSInitTable; typedef struct { /* Common registers */ @@ -262,10 +239,11 @@ typedef struct { CARD32 disp_merge_cntl; CARD32 grph_buffer_cntl; CARD32 crtc_more_cntl; + CARD32 crtc_tile_x0_y0; /* CRTC2 registers */ CARD32 crtc2_gen_cntl; - + CARD32 dac_macro_cntl; CARD32 dac2_cntl; CARD32 disp_output_cntl; CARD32 disp_tv_out_cntl; @@ -279,6 +257,8 @@ typedef struct { CARD32 crtc2_offset; CARD32 crtc2_offset_cntl; CARD32 crtc2_pitch; + CARD32 crtc2_tile_x0_y0; + /* Flat panel registers */ CARD32 fp_crtc_h_total_disp; CARD32 fp_crtc_v_total_disp; @@ -306,7 +286,7 @@ typedef struct { unsigned ppll_ref_div; unsigned ppll_div_3; CARD32 htotal_cntl; - CARD32 vclk_cntl; + CARD32 vclk_ecp_cntl; /* Computed values for PLL2 */ CARD32 dot_clock_freq_2; @@ -325,7 +305,54 @@ typedef struct { CARD32 palette[256]; CARD32 palette2[256]; - CARD32 tv_dac_cntl; + CARD32 rs480_unk_e30; + CARD32 rs480_unk_e34; + CARD32 rs480_unk_e38; + CARD32 rs480_unk_e3c; + + /* TV out registers */ + CARD32 tv_master_cntl; + CARD32 tv_htotal; + CARD32 tv_hsize; + CARD32 tv_hdisp; + CARD32 tv_hstart; + CARD32 tv_vtotal; + CARD32 tv_vdisp; + CARD32 tv_timing_cntl; + CARD32 tv_vscaler_cntl1; + CARD32 tv_vscaler_cntl2; + CARD32 tv_sync_size; + CARD32 tv_vrestart; + CARD32 tv_hrestart; + CARD32 tv_frestart; + CARD32 tv_ftotal; + CARD32 tv_clock_sel_cntl; + CARD32 tv_clkout_cntl; + CARD32 tv_data_delay_a; + CARD32 tv_data_delay_b; + CARD32 tv_dac_cntl; + CARD32 tv_pll_cntl; + CARD32 tv_pll_cntl1; + CARD32 tv_pll_fine_cntl; + CARD32 tv_modulator_cntl1; + CARD32 tv_modulator_cntl2; + CARD32 tv_frame_lock_cntl; + CARD32 tv_pre_dac_mux_cntl; + CARD32 tv_rgb_cntl; + CARD32 tv_y_saw_tooth_cntl; + CARD32 tv_y_rise_cntl; + CARD32 tv_y_fall_cntl; + CARD32 tv_uv_adr; + CARD32 tv_upsamp_and_gain_cntl; + CARD32 tv_gain_limit_settings; + CARD32 tv_linear_gain_settings; + CARD32 tv_crc_cntl; + CARD32 tv_sync_cntl; + CARD32 gpiopad_a; + CARD32 pll_test_cntl; + + CARD16 h_code_timing[MAX_H_CODE_TIMING_LEN]; + CARD16 v_code_timing[MAX_V_CODE_TIMING_LEN]; } RADEONSaveRec, *RADEONSavePtr; @@ -402,11 +429,6 @@ typedef enum { } RADEONCardType; typedef struct { - CARD32 freq; - CARD32 value; -}RADEONTMDSPll; - -typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; PCITAG PciTag; @@ -414,8 +436,6 @@ typedef struct { RADEONChipFamily ChipFamily; RADEONErrata ChipErrata; - Bool FBDev; - unsigned long LinearAddr; /* Frame buffer physical address */ unsigned long MMIOAddr; /* MMIO region physical address */ unsigned long BIOSAddr; /* BIOS physical address */ @@ -438,36 +458,16 @@ typedef struct { unsigned long FbMapSize; /* Size of frame buffer, in bytes */ unsigned long FbSecureSize; /* Size of secured fb area at end of framebuffer */ - int Flags; /* Saved copy of mode flags */ - - /* VE/M6 support */ - RADEONMonitorType DisplayType; /* Monitor connected on */ - RADEONDDCType DDCType; - RADEONConnectorType ConnectorType; Bool IsMobility; /* Mobile chips for laptops */ Bool IsIGP; /* IGP chips */ Bool HasSingleDAC; /* only TVDAC on chip */ - Bool IsSecondary; /* Second Screen */ - Bool IsPrimary; /* Primary Screen */ - Bool IsSwitching; /* Flag for switching mode */ - Bool OverlayOnCRTC2; Bool ddc_mode; /* Validate mode by matching exactly * the modes supported in DDC data */ Bool R300CGWorkaround; /* EDID or BIOS values for FPs */ - int PanelXRes; - int PanelYRes; - int HOverPlus; - int HSyncWidth; - int HBlank; - int VOverPlus; - int VSyncWidth; - int VBlank; - int PanelPwrDly; - int DotClock; int RefDivider; int FeedbackDivider; int PostDivider; @@ -476,11 +476,9 @@ typedef struct { Bool ddc_bios; Bool ddc1; Bool ddc2; - I2CBusPtr pI2CBus; - CARD32 DDCReg; RADEONPLLRec pll; - RADEONTMDSPll tmds_pll[4]; + int RamWidth; float sclk; /* in MHz */ float mclk; /* in MHz */ @@ -497,6 +495,8 @@ typedef struct { #ifdef USE_EXA ExaDriverPtr exa; + int exaSyncMarker; + int exaMarkerSynced; int engineMode; #define EXA_ENGINEMODE_UNKNOWN 0 #define EXA_ENGINEMODE_2D 1 @@ -605,6 +605,7 @@ typedef struct { Bool allowPageFlip; /* Enable 3d page flipping */ #ifdef DAMAGE DamagePtr pDamage; + RegionRec driRegion; #endif Bool have3DWindows; /* Are there any 3d clients? */ @@ -614,7 +615,6 @@ typedef struct { unsigned long gartOffset; unsigned char *AGP; /* Map */ int agpMode; - int agpFastWrite; CARD32 pciCommand; @@ -774,42 +774,10 @@ typedef struct { /* X itself has the 3D context */ Bool XInited3D; - /* 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; - int CRT1XOffs, CRT1YOffs, CRT2XOffs, CRT2YOffs; - int MBXNR1XMAX, MBXNR1YMAX, MBXNR2XMAX, MBXNR2YMAX; - Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions; - region NonRectDead, OffDead1, OffDead2; + DisplayModePtr currentMode, savedCurrentMode; int constantDPI; /* -1 = auto, 0 = off, 1 = on */ int RADEONDPIVX, RADEONDPIVY; - RADEONScrn2Rel MergedDPISRel; - int RADEONMergedDPIVX, RADEONMergedDPIVY, RADEONMergedDPIRot; /* special handlings for DELL triple-head server */ Bool IsDellServer; @@ -820,7 +788,22 @@ typedef struct { int MaxLines; CARD32 tv_dac_adj; + CARD32 tv_dac_enable_mask; + + Bool want_vblank_interrupts; + RADEONBIOSConnector BiosConnector[RADEON_MAX_BIOS_CONNECTOR]; + RADEONBIOSInitTable BiosTable; + + /* save crtc state for console restore */ + Bool crtc_on; + Bool crtc2_on; + + Bool InternalTVOut; + int tvdac_use_count; + Rotation rotation; + void (*PointerMoved)(int, int, int); + CreateScreenResourcesProcPtr CreateScreenResources; } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ @@ -839,7 +822,7 @@ extern void RADEONWaitForIdleCP(ScrnInfoPtr pScrn); #endif extern void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, - int clone); + Bool clone); extern void RADEONEngineReset(ScrnInfoPtr pScrn); extern void RADEONEngineFlush(ScrnInfoPtr pScrn); @@ -858,6 +841,7 @@ extern Bool RADEONAccelInit(ScreenPtr pScreen); extern Bool RADEONSetupMemEXA (ScreenPtr pScreen); extern Bool RADEONDrawInitMMIO(ScreenPtr pScreen); #ifdef XF86DRI +extern unsigned long long RADEONTexOffsetStart(PixmapPtr pPix); extern Bool RADEONGetDatatypeBpp(int bpp, CARD32 *type); extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, CARD32 *pitch_offset); @@ -892,19 +876,47 @@ extern void RADEONPllErrataAfterData(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); - +extern Bool RADEONGetLVDSInfoFromBIOS (xf86OutputPtr output); +extern Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output); +extern Bool RADEONGetTVInfoFromBIOS (xf86OutputPtr output); +extern Bool RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output); + +extern void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreDACRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreFP2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore); +extern void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore); + +extern void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr save, + RADEONInfoPtr info); extern void RADEONInitDispBandwidth(ScrnInfoPtr pScrn); extern Bool RADEONI2cInit(ScrnInfoPtr pScrn); extern void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag); -extern void RADEONSetupConnectors(ScrnInfoPtr pScrn); -extern Bool RADEONMapControllers(ScrnInfoPtr pScrn); -extern void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable); +extern Bool RADEONSetupConnectors(ScrnInfoPtr pScrn); +extern void RADEONPrintPortMap(ScrnInfoPtr pScrn); +extern void RADEONEnableDisplay(xf86OutputPtr pPort, BOOL bEnable); extern void RADEONDisableDisplays(ScrnInfoPtr pScrn); extern void RADEONGetPanelInfo(ScrnInfoPtr pScrn); -extern void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn); +extern void RADEONGetTVDacAdjInfo(xf86OutputPtr output); +extern void RADEONUnblank(ScrnInfoPtr pScrn); extern void RADEONUnblank(ScrnInfoPtr pScrn); extern void RADEONBlank(ScrnInfoPtr pScrn); extern void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, @@ -912,13 +924,48 @@ extern void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int flags); extern Bool RADEONAllocateControllers(ScrnInfoPtr pScrn); extern Bool RADEONAllocateConnectors(ScrnInfoPtr pScrn); -extern RADEONConnector *RADEONGetCrtcConnector(ScrnInfoPtr pScrn, int crtc_num); extern int RADEONValidateMergeModes(ScrnInfoPtr pScrn); extern int RADEONValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName, RADEONMonitorType DisplayType, int crtc2); -extern int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName); +extern int RADEONValidateFPModes(xf86OutputPtr output, char **ppModeName, DisplayModePtr *modeList); extern void RADEONSetPitch (ScrnInfoPtr pScrn); - +extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode); + +DisplayModePtr +RADEONProbeOutputModes(xf86OutputPtr output); +extern Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, + DisplayModePtr crtc2, int crtc_mask, + RADEONSavePtr save, RADEONMonitorType montype); + +void +radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y); +void +radeon_crtc_show_cursor (xf86CrtcPtr crtc); +void +radeon_crtc_hide_cursor (xf86CrtcPtr crtc); +void +radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y); +void +radeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg); +void +radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image); +void +RADEONEnableOutputs(ScrnInfoPtr pScrn, int crtc_num); + +extern void RADEONAdjustCrtcRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONAdjustPLLRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONAdjustPLL2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output); +extern void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary); + +extern void RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore); +extern void RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore); +extern void RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore); #ifdef XF86DRI #ifdef USE_XAA @@ -937,6 +984,7 @@ extern drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn); extern void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard); extern void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn); extern int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info); +extern Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on); extern void RADEONHostDataParams(ScrnInfoPtr pScrn, CARD8 *dst, CARD32 pitch, int cpp, @@ -964,6 +1012,16 @@ do { \ info->CPStarted = TRUE; \ } while (0) +#define RADEONCP_RELEASE(pScrn, info) \ +do { \ + if (info->CPInUse) { \ + RADEON_PURGE_CACHE(); \ + RADEON_WAIT_UNTIL_IDLE(); \ + RADEONCPReleaseIndirect(pScrn); \ + info->CPInUse = FALSE; \ + } \ +} while (0) + #define RADEONCP_STOP(pScrn, info) \ do { \ int _ret; \ @@ -1128,14 +1186,6 @@ do { \ ADVANCE_RING(); \ } while (0) -#define RADEON_FLUSH_CACHE() \ -do { \ - BEGIN_RING(2); \ - OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH); \ - ADVANCE_RING(); \ -} while (0) - #define RADEON_PURGE_CACHE() \ do { \ BEGIN_RING(2); \ @@ -1176,4 +1226,21 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn) #endif } +static __inline__ void radeon_init_timeout(struct timeval *endtime, + unsigned int timeout) +{ + gettimeofday(endtime, NULL); + endtime->tv_usec += timeout; + endtime->tv_sec += endtime->tv_usec / 1000000; + endtime->tv_usec %= 1000000; +} + +static __inline__ int radeon_timedout(const struct timeval *endtime) +{ + struct timeval now; + gettimeofday(&now, NULL); + return now.tv_sec == endtime->tv_sec ? + now.tv_usec > endtime->tv_usec : now.tv_sec > endtime->tv_sec; +} + #endif /* _RADEON_H_ */ diff --git a/src/radeon_accel.c b/src/radeon_accel.c index 41859c4a..b739988f 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -134,9 +134,10 @@ void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries) INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; if (info->fifo_slots >= entries) return; } - RADEONTRACE(("FIFO timed out: %u entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "FIFO timed out: %u entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS)); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FIFO timed out, resetting engine...\n"); RADEONEngineReset(pScrn); @@ -165,8 +166,9 @@ void RADEONEngineFlush(ScrnInfoPtr pScrn) break; } if (i == RADEON_TIMEOUT) { - RADEONTRACE(("DC flush timeout: %x\n", - INREG(RADEON_RB3D_DSTCACHE_CTLSTAT))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "DC flush timeout: %x\n", + INREG(RADEON_RB3D_DSTCACHE_CTLSTAT)); } } @@ -296,9 +298,10 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONTRACE(("EngineRestore (%d/%d)\n", - info->CurrentLayout.pixel_code, - info->CurrentLayout.bitsPerPixel)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "EngineRestore (%d/%d)\n", + info->CurrentLayout.pixel_code, + info->CurrentLayout.bitsPerPixel); /* Setup engine location. This shouldn't be necessary since we * set them appropriately before any accel ops, but let's avoid @@ -347,9 +350,10 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONTRACE(("EngineInit (%d/%d)\n", - info->CurrentLayout.pixel_code, - info->CurrentLayout.bitsPerPixel)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "EngineInit (%d/%d)\n", + info->CurrentLayout.pixel_code, + info->CurrentLayout.bitsPerPixel); OUTREG(RADEON_RB3D_CNTL, 0); @@ -362,15 +366,17 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) case 24: info->datatype = 5; break; case 32: info->datatype = 6; break; default: - RADEONTRACE(("Unknown depth/bpp = %d/%d (code = %d)\n", - info->CurrentLayout.depth, - info->CurrentLayout.bitsPerPixel, - info->CurrentLayout.pixel_code)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Unknown depth/bpp = %d/%d (code = %d)\n", + info->CurrentLayout.depth, + info->CurrentLayout.bitsPerPixel, + info->CurrentLayout.pixel_code); } info->pitch = ((info->CurrentLayout.displayWidth / 8) * (info->CurrentLayout.pixel_bytes == 3 ? 3 : 1)); - RADEONTRACE(("Pitch for acceleration = %d\n", info->pitch)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Pitch for acceleration = %d\n", info->pitch); info->dp_gui_master_cntl = ((info->datatype << RADEON_GMC_DST_DATATYPE_SHIFT) diff --git a/src/radeon_accelfuncs.c b/src/radeon_accelfuncs.c index 784b0745..212131fd 100644 --- a/src/radeon_accelfuncs.c +++ b/src/radeon_accelfuncs.c @@ -1204,8 +1204,14 @@ FUNC_NAME(RADEONAccelInit)(ScreenPtr pScreen, XAAInfoRecPtr a) hardware accel two point lines */ miSetZeroLineBias(pScreen, (OCTANT5 | OCTANT6 | OCTANT7 | OCTANT8)); - a->SubsequentSolidTwoPointLine - = FUNC_NAME(RADEONSubsequentSolidTwoPointLine); +#ifdef ACCEL_CP + /* RV280s lock up with this using the CP for reasons to be determined. + * See https://bugs.freedesktop.org/show_bug.cgi?id=5986 . + */ + if (info->ChipFamily != CHIP_FAMILY_RV280) +#endif + a->SubsequentSolidTwoPointLine + = FUNC_NAME(RADEONSubsequentSolidTwoPointLine); /* Disabled on RV200 and newer because it does not pass XTest */ if (info->ChipFamily < CHIP_FAMILY_RV200) { diff --git a/src/radeon_bios.c b/src/radeon_bios.c index 1d4c9bbb..b24c4817 100644 --- a/src/radeon_bios.c +++ b/src/radeon_bios.c @@ -34,12 +34,27 @@ #include "xf86.h" #include "xf86_OSproc.h" +#include "xf86PciInfo.h" #include "radeon.h" #include "radeon_reg.h" #include "radeon_macros.h" #include "radeon_probe.h" #include "vbe.h" +int RADEONBIOSApplyConnectorQuirks(ScrnInfoPtr pScrn, int connector_found) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + /* quirk for compaq nx6125 - the bios lies about the VGA DDC */ + if (info->PciInfo->subsysVendor == PCI_VENDOR_HP) { + if (info->PciInfo->subsysCard == 0x308b) { + if (info->BiosConnector[1].DDCType == DDC_CRT2) + info->BiosConnector[1].DDCType = DDC_MONID; + } + } + return connector_found; +} + /* Read the Video BIOS block and the FP registers (if applicable). */ Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) { @@ -126,11 +141,191 @@ Bool RADEONGetBIOSInfo(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) return TRUE; } +static Bool RADEONGetATOMConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + int offset, i, tmp, tmp0, crtc, portinfo, gpio; + + if (!info->VBIOS) return FALSE; + + offset = RADEON_BIOS16(info->MasterDataStart + 22); + + if (offset) { + tmp = RADEON_BIOS16(offset + 4); + for (i = 0; i < 8; i++) { + if (tmp & (1 << i)) { + info->BiosConnector[i].valid = TRUE; + portinfo = RADEON_BIOS16(offset + 6 + i * 2); + info->BiosConnector[i].DACType = (portinfo & 0xf) - 1; + info->BiosConnector[i].ConnectorType = (portinfo >> 4) & 0xf; + crtc = (portinfo >> 8) & 0xf; + tmp0 = RADEON_BIOS16(info->MasterDataStart + 24); + gpio = RADEON_BIOS16(tmp0 + 4 + 27 * crtc) * 4; + switch(gpio) { + case RADEON_GPIO_MONID: + info->BiosConnector[i].DDCType = DDC_MONID; + break; + case RADEON_GPIO_DVI_DDC: + info->BiosConnector[i].DDCType = DDC_DVI; + break; + case RADEON_GPIO_VGA_DDC: + info->BiosConnector[i].DDCType = DDC_VGA; + break; + case RADEON_GPIO_CRT2_DDC: + info->BiosConnector[i].DDCType = DDC_CRT2; + break; + case RADEON_LCD_GPIO_MASK: + info->BiosConnector[i].DDCType = DDC_LCD; + break; + default: + info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; + break; + } + + if (i == 3) + info->BiosConnector[i].TMDSType = TMDS_INT; + else if (i == 7) + info->BiosConnector[i].TMDSType = TMDS_EXT; + else + info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; + + } else { + info->BiosConnector[i].valid = FALSE; + } + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); + return FALSE; + } + + /* DVI-I ports have 2 entries: one for analog, one for digital. combine them */ + if (info->BiosConnector[0].valid && info->BiosConnector[7].valid) { + info->BiosConnector[7].DACType = info->BiosConnector[0].DACType; + info->BiosConnector[0].valid = FALSE; + } + + if (info->BiosConnector[4].valid && info->BiosConnector[3].valid) { + info->BiosConnector[3].DACType = info->BiosConnector[4].DACType; + info->BiosConnector[4].valid = FALSE; + } + + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); + } + } + + return TRUE; +} + +static Bool RADEONGetLegacyConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + int offset, i, entry, tmp, tmp0, tmp1; + + if (!info->VBIOS) return FALSE; + + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x50); + if (offset) { + for (i = 0; i < 4; i++) { + entry = offset + 2 + i*2; + + if (!RADEON_BIOS16(entry)) { + break; + } + info->BiosConnector[i].valid = TRUE; + tmp = RADEON_BIOS16(entry); + info->BiosConnector[i].ConnectorType = (tmp >> 12) & 0xf; + info->BiosConnector[i].DDCType = (tmp >> 8) & 0xf; + info->BiosConnector[i].DACType = tmp & 0x1; + info->BiosConnector[i].TMDSType = tmp & 0x10; + + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n"); + return FALSE; + } + + /* check LVDS table */ + if (info->IsMobility) { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x40); + if (offset) { + info->BiosConnector[4].valid = TRUE; + info->BiosConnector[4].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[4].DACType = DAC_NONE; + info->BiosConnector[4].TMDSType = TMDS_NONE; + + tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42); + if (tmp) { + tmp0 = RADEON_BIOS16(tmp + 0x15); + if (tmp0) { + tmp1 = RADEON_BIOS8(tmp0+2) & 0x07; + if (tmp1) { + info->BiosConnector[4].DDCType = tmp1; + if (info->BiosConnector[4].DDCType > DDC_LCD) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Unknown DDCType %d found\n", + info->BiosConnector[4].DDCType); + info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); + } + } + } else { + info->BiosConnector[4].DDCType = DDC_NONE_DETECTED; + } + } + } + + /* check TV table */ + if (info->InternalTVOut) { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); + if (offset) { + if (RADEON_BIOS8(offset + 6) == 'T') { + info->BiosConnector[5].valid = TRUE; + /* assume s-video for now */ + info->BiosConnector[5].ConnectorType = CONNECTOR_STV; + info->BiosConnector[5].DACType = DAC_TVDAC; + info->BiosConnector[5].TMDSType = TMDS_NONE; + info->BiosConnector[5].DDCType = DDC_NONE_DETECTED; + } + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Port%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); + } + } + + return TRUE; +} + +Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + + if(!info->VBIOS) return FALSE; + + if (info->IsAtomBios) + return RADEONGetATOMConnectorInfoFromBIOS(pScrn); + else + return RADEONGetLegacyConnectorInfoFromBIOS(pScrn); +} + +#if 0 Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR (pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); int i = 0, j, tmp, tmp0=0, tmp1=0; + RADEONBIOSConnector tempConnector; if(!info->VBIOS) return FALSE; @@ -148,46 +343,49 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) /* sharing same port with id[0] */ if (((portinfo>>8) & 0xf) == id[0]) { if (i == 3) - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_INT; + info->BiosConnector[0].TMDSType = TMDS_INT; else if (i == 7) - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_EXT; + info->BiosConnector[0].TMDSType = TMDS_EXT; - if (pRADEONEnt->PortInfo[0]->DACType == DAC_UNKNOWN) - pRADEONEnt->PortInfo[0]->DACType = (portinfo & 0xf) - 1; + if (info->BiosConnector[0].DACType == DAC_UNKNOWN) + info->BiosConnector[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; + info->BiosConnector[crtc].DACType = (portinfo & 0xf) - 1; + info->BiosConnector[crtc].ConnectorType = (portinfo>>4) & 0xf; if (i == 3) - pRADEONEnt->PortInfo[crtc]->TMDSType = TMDS_INT; + info->BiosConnector[crtc].TMDSType = TMDS_INT; else if (i == 7) - pRADEONEnt->PortInfo[crtc]->TMDSType = TMDS_EXT; + info->BiosConnector[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; + info->BiosConnector[crtc].DDCType = DDC_MONID; break; case RADEON_GPIO_DVI_DDC: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_DVI; + info->BiosConnector[crtc].DDCType = DDC_DVI; break; case RADEON_GPIO_VGA_DDC: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_VGA; + info->BiosConnector[crtc].DDCType = DDC_VGA; break; case RADEON_GPIO_CRT2_DDC: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_CRT2; + info->BiosConnector[crtc].DDCType = DDC_CRT2; + break; + case RADEON_LCD_GPIO_MASK: + info->BiosConnector[crtc].DDCType = DDC_LCD; break; default: - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_NONE_DETECTED; + info->BiosConnector[crtc].DDCType = DDC_NONE_DETECTED; break; } } else { - pRADEONEnt->PortInfo[crtc]->DDCType = DDC_NONE_DETECTED; + info->BiosConnector[crtc].DDCType = DDC_NONE_DETECTED; } crtc++; } else { @@ -197,22 +395,28 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) for (j=0; j<2; j++) { if (((portinfo>>8) & 0xf) == id[j]) { if (i == 3) - pRADEONEnt->PortInfo[j]->TMDSType = TMDS_INT; + info->BiosConnector[j].TMDSType = TMDS_INT; else if (i == 7) - pRADEONEnt->PortInfo[j]->TMDSType = TMDS_EXT; + info->BiosConnector[j].TMDSType = TMDS_EXT; - if (pRADEONEnt->PortInfo[j]->DACType == DAC_UNKNOWN) - pRADEONEnt->PortInfo[j]->DACType = (portinfo & 0xf) - 1; + if (info->BiosConnector[j].DACType == DAC_UNKNOWN) + info->BiosConnector[j].DACType = (portinfo & 0xf) - 1; } } } } } + /* R4xx seem to get the connector table backwards */ + tempConnector = info->BiosConnector[0]; + info->BiosConnector[0] = info->BiosConnector[1]; + info->BiosConnector[1] = tempConnector; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bios Connector table: \n"); 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); + i, info->BiosConnector[i].DDCType, info->BiosConnector[i].DACType, + info->BiosConnector[i].TMDSType, info->BiosConnector[i].ConnectorType); } } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Device Info Table found!\n"); @@ -239,25 +443,27 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) tmp0 = RADEON_BIOS16(tmp + i*2); if (((tmp0 >> 12) & 0x0f) == 0) continue; /* no connector */ if (connector_found > 0) { - if (pRADEONEnt->PortInfo[tmp1]->DDCType == ((tmp0 >> 8) & 0x0f)) + if (info->BiosConnector[tmp1].DDCType == ((tmp0 >> 8) & 0x0f)) continue; /* same 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; + info->BiosConnector[tmp1].DDCType = (tmp0 >> 8) & 0x0f; + if (info->BiosConnector[tmp1].DDCType > DDC_CRT2) + info->BiosConnector[tmp1].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[tmp1].DACType = (tmp0 & 0x01) ? DAC_TVDAC : DAC_PRIMARY; + info->BiosConnector[tmp1].ConnectorType = (tmp0 >> 12) & 0x0f; + if (info->BiosConnector[tmp1].ConnectorType > CONNECTOR_UNSUPPORTED) + info->BiosConnector[tmp1].ConnectorType = CONNECTOR_UNSUPPORTED; + info->BiosConnector[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; + if (((info->BiosConnector[tmp1].ConnectorType != CONNECTOR_DVI_D) && + (info->BiosConnector[tmp1].ConnectorType != CONNECTOR_DVI_I)) && + info->BiosConnector[tmp1].TMDSType == TMDS_INT) + info->BiosConnector[tmp1].TMDSType = TMDS_UNKNOWN; connector_found += (tmp1 + 1); } @@ -267,69 +473,52 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) } if (info->IsMobility) { - /* For the cases where only one VGA connector is found, - we assume LVDS is not listed in the connector table, - add it in here as the first port. - */ - if ((connector_found < 3) && (pRADEONEnt->PortInfo[tmp1]->ConnectorType == CONNECTOR_CRT)) { - if (connector_found == 1) { - memcpy (&pRADEONEnt->PortInfo[1], &pRADEONEnt->PortInfo[0], - sizeof (pRADEONEnt->PortInfo[0])); - } - pRADEONEnt->PortInfo[0]->DACType = DAC_TVDAC; - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[0]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[0]->ConnectorType = CONNECTOR_PROPRIETARY; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS port is not in connector table, added in.\n"); - if (connector_found == 0) connector_found = 1; - else connector_found = 3; - } - 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; - if (pRADEONEnt->PortInfo[0]->DDCType > DDC_CRT2) { + info->BiosConnector[0].DDCType = tmp1; + if (info->BiosConnector[0].DDCType > DDC_LCD) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown DDCType %d found\n", - pRADEONEnt->PortInfo[0]->DDCType); - pRADEONEnt->PortInfo[0]->DDCType = DDC_NONE_DETECTED; + info->BiosConnector[0].DDCType); + info->BiosConnector[0].DDCType = DDC_NONE_DETECTED; } xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n"); } } } } else if (connector_found == 2) { - memcpy (&pRADEONEnt->PortInfo[0], &pRADEONEnt->PortInfo[1], - sizeof (pRADEONEnt->PortInfo[0])); - pRADEONEnt->PortInfo[1]->DACType = DAC_UNKNOWN; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[1]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_NONE; + memcpy (&info->BiosConnector[0], &info->BiosConnector[1], + sizeof (info->BiosConnector[0])); + info->BiosConnector[1].DACType = DAC_UNKNOWN; + info->BiosConnector[1].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[1].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[1].ConnectorType = CONNECTOR_NONE; connector_found = 1; } + connector_found = RADEONBIOSApplyConnectorQuirks(pScrn, connector_found); + if (connector_found == 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No connector found in Connector Info Table.\n"); } else { - xf86DrvMsg(0, X_INFO, "Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - pRADEONEnt->PortInfo[0]->DDCType, pRADEONEnt->PortInfo[0]->DACType, - pRADEONEnt->PortInfo[0]->TMDSType, pRADEONEnt->PortInfo[0]->ConnectorType); + xf86DrvMsg(0, X_INFO, "Bios Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + info->BiosConnector[0].DDCType, info->BiosConnector[0].DACType, + info->BiosConnector[0].TMDSType, info->BiosConnector[0].ConnectorType); } if (connector_found == 3) { - xf86DrvMsg(0, X_INFO, "Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", - pRADEONEnt->PortInfo[1]->DDCType, pRADEONEnt->PortInfo[1]->DACType, - pRADEONEnt->PortInfo[1]->TMDSType, pRADEONEnt->PortInfo[1]->ConnectorType); + xf86DrvMsg(0, X_INFO, "Bios Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n", + info->BiosConnector[1].DDCType, info->BiosConnector[1].DACType, + info->BiosConnector[1].TMDSType, info->BiosConnector[1].ConnectorType); } #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; + //info->BiosConnector[1].DDCType = (RADEON_BIOS8(tmp0 + 7) & 0x07); + //info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_I; + //info->BiosConnector[1].TMDSType = TMDS_EXT; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "External TMDS found.\n"); } else { @@ -341,6 +530,100 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn) } return TRUE; } +#endif + +Bool RADEONGetTVInfoFromBIOS (xf86OutputPtr output) { + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int offset, refclk, stds; + + if (!info->VBIOS) return FALSE; + + if (info->IsAtomBios) { + /* no idea where TV table is on ATOM bios */ + return FALSE; + } else { + offset = RADEON_BIOS16(info->ROMHeaderStart + 0x32); + if (offset) { + if (RADEON_BIOS8(offset + 6) == 'T') { + switch (RADEON_BIOS8(offset + 7) & 0xf) { + case 1: + radeon_output->default_tvStd = TV_STD_NTSC; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC\n"); + break; + case 2: + radeon_output->default_tvStd = TV_STD_PAL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL\n"); + break; + case 3: + radeon_output->default_tvStd = TV_STD_PAL_M; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-M\n"); + break; + case 4: + radeon_output->default_tvStd = TV_STD_PAL_60; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: PAL-60\n"); + break; + case 5: + radeon_output->default_tvStd = TV_STD_NTSC_J; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: NTSC-J\n"); + break; + case 6: + radeon_output->default_tvStd = TV_STD_SCART_PAL; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Default TV standard: SCART-PAL\n"); + break; + default: + radeon_output->default_tvStd = TV_STD_NTSC; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Unknown TV standard; defaulting to NTSC\n"); + break; + } + radeon_output->tvStd = radeon_output->default_tvStd; + + refclk = (RADEON_BIOS8(offset + 9) >> 2) & 0x3; + if (refclk == 0) + radeon_output->TVRefClk = 29.498928713; /* MHz */ + else if (refclk == 1) + radeon_output->TVRefClk = 28.636360000; + else if (refclk == 2) + radeon_output->TVRefClk = 14.318180000; + else if (refclk == 3) + radeon_output->TVRefClk = 27.000000000; + + radeon_output->SupportedTVStds = radeon_output->default_tvStd; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standards supported by chip: "); + stds = RADEON_BIOS8(offset + 10) & 0x1f; + if (stds & TV_STD_NTSC) { + radeon_output->SupportedTVStds |= TV_STD_NTSC; + ErrorF("NTSC "); + } + if (stds & TV_STD_PAL) { + radeon_output->SupportedTVStds |= TV_STD_PAL; + ErrorF("PAL "); + } + if (stds & TV_STD_PAL_M) { + radeon_output->SupportedTVStds |= TV_STD_PAL_M; + ErrorF("PAL-M "); + } + if (stds & TV_STD_PAL_60) { + radeon_output->SupportedTVStds |= TV_STD_PAL_60; + ErrorF("PAL-60 "); + } + if (stds & TV_STD_NTSC_J) { + radeon_output->SupportedTVStds |= TV_STD_NTSC_J; + ErrorF("NTSC-J "); + } + if (stds & TV_STD_SCART_PAL) { + radeon_output->SupportedTVStds |= TV_STD_SCART_PAL; + ErrorF("SCART-PAL"); + } + ErrorF("\n"); + + return TRUE; + } + } + } + return FALSE; +} /* Read PLL parameters from BIOS block. Default to typical values if there is no BIOS. */ @@ -370,8 +653,11 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) 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); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref_freq: %d, min_pll: %u, " + "max_pll: %u, xclk: %d, sclk: %f, mclk: %f\n", + pll->reference_freq, (unsigned)pll->min_pll_freq, + (unsigned)pll->max_pll_freq, pll->xclk, info->sclk, + info->mclk); } else { pll_info_block = RADEON_BIOS16 (info->ROMHeaderStart + 0x30); @@ -390,9 +676,11 @@ Bool RADEONGetClockInfoFromBIOS (ScrnInfoPtr pScrn) return TRUE; } -Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) +Bool RADEONGetLVDSInfoFromBIOS (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; unsigned long tmp, i; if (!info->VBIOS) return FALSE; @@ -400,26 +688,29 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) 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; + radeon_output->PanelXRes = RADEON_BIOS16(tmp+6); + radeon_output->PanelYRes = RADEON_BIOS16(tmp+10); + radeon_output->DotClock = RADEON_BIOS16(tmp+4)*10; + radeon_output->HBlank = RADEON_BIOS16(tmp+8); + radeon_output->HOverPlus = RADEON_BIOS16(tmp+14); + radeon_output->HSyncWidth = RADEON_BIOS16(tmp+16); + radeon_output->VBlank = RADEON_BIOS16(tmp+12); + radeon_output->VOverPlus = RADEON_BIOS16(tmp+18); + radeon_output->VSyncWidth = RADEON_BIOS16(tmp+20); + radeon_output->PanelPwrDly = RADEON_BIOS16(tmp+40); + + if (radeon_output->PanelPwrDly > 2000 || radeon_output->PanelPwrDly < 0) + radeon_output->PanelPwrDly = 2000; + + radeon_output->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); + radeon_output->PanelXRes, radeon_output->PanelYRes, radeon_output->DotClock, + radeon_output->HBlank, radeon_output->HOverPlus, radeon_output->HSyncWidth, + radeon_output->VBlank, radeon_output->VOverPlus, radeon_output->VSyncWidth); } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No LVDS Info Table found in BIOS!\n"); @@ -444,14 +735,14 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel ID string: %s\n", stmp); - info->PanelXRes = RADEON_BIOS16(tmp+25); - info->PanelYRes = RADEON_BIOS16(tmp+27); + radeon_output->PanelXRes = RADEON_BIOS16(tmp+25); + radeon_output->PanelYRes = RADEON_BIOS16(tmp+27); xf86DrvMsg(0, X_INFO, "Panel Size from BIOS: %dx%d\n", - info->PanelXRes, info->PanelYRes); + radeon_output->PanelXRes, radeon_output->PanelYRes); - info->PanelPwrDly = RADEON_BIOS16(tmp+44); - if (info->PanelPwrDly > 2000 || info->PanelPwrDly < 0) - info->PanelPwrDly = 2000; + radeon_output->PanelPwrDly = RADEON_BIOS16(tmp+44); + if (radeon_output->PanelPwrDly > 2000 || radeon_output->PanelPwrDly < 0) + radeon_output->PanelPwrDly = 2000; /* some panels only work well with certain divider combinations. */ @@ -472,20 +763,20 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) 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) - + if ((RADEON_BIOS16(tmp0) == radeon_output->PanelXRes) && + (RADEON_BIOS16(tmp0+2) == radeon_output->PanelYRes)) { + radeon_output->HBlank = (RADEON_BIOS16(tmp0+17) - RADEON_BIOS16(tmp0+19)) * 8; - info->HOverPlus = (RADEON_BIOS16(tmp0+21) - + radeon_output->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_output->HSyncWidth = RADEON_BIOS8(tmp0+23) * 8; + radeon_output->VBlank = (RADEON_BIOS16(tmp0+24) - RADEON_BIOS16(tmp0+26)); - info->VOverPlus = ((RADEON_BIOS16(tmp0+28) & 0x7ff) - + radeon_output->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; + radeon_output->VSyncWidth = ((RADEON_BIOS16(tmp0+28) & 0xf800) >> 11); + radeon_output->DotClock = RADEON_BIOS16(tmp0+9) * 10; + radeon_output->Flags = 0; } } } @@ -493,9 +784,11 @@ Bool RADEONGetLVDSInfoFromBIOS (ScrnInfoPtr pScrn) return TRUE; } -Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn) +Bool RADEONGetHardCodedEDIDFromBIOS (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; unsigned long tmp; char EDID[256]; @@ -511,24 +804,26 @@ Bool RADEONGetHardCodedEDIDFromBIOS (ScrnInfoPtr pScrn) 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);*/ + radeon_output->DotClock = (*(CARD16*)(EDID+54)) * 10; + radeon_output->PanelXRes = (*(CARD8*)(EDID+56)) + ((*(CARD8*)(EDID+58))>>4)*256; + radeon_output->HBlank = (*(CARD8*)(EDID+57)) + ((*(CARD8*)(EDID+58)) & 0xf)*256; + radeon_output->HOverPlus = (*(CARD8*)(EDID+62)) + ((*(CARD8*)(EDID+65)>>6)*256); + radeon_output->HSyncWidth = (*(CARD8*)(EDID+63)) + (((*(CARD8*)(EDID+65)>>4) & 3)*256); + radeon_output->PanelYRes = (*(CARD8*)(EDID+59)) + ((*(CARD8*)(EDID+61))>>4)*256; + radeon_output->VBlank = ((*(CARD8*)(EDID+60)) + ((*(CARD8*)(EDID+61)) & 0xf)*256); + radeon_output->VOverPlus = (((*(CARD8*)(EDID+64))>>4) + (((*(CARD8*)(EDID+65)>>2) & 3)*16)); + radeon_output->VSyncWidth = (((*(CARD8*)(EDID+64)) & 0xf) + ((*(CARD8*)(EDID+65)) & 3)*256); + radeon_output->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) +Bool RADEONGetTMDSInfoFromBIOS (xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; CARD32 tmp, maxfreq; int i, n; @@ -540,18 +835,19 @@ Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) maxfreq = RADEON_BIOS16(tmp+4); for (i=0; i<4; i++) { - info->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*6+6); + radeon_output->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_output->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); + "TMDS PLL from BIOS: %u %x\n", + (unsigned)radeon_output->tmds_pll[i].freq, + (unsigned)radeon_output->tmds_pll[i].value); - if (maxfreq == info->tmds_pll[i].freq) { - info->tmds_pll[i].freq = 0xffffffff; + if (maxfreq == radeon_output->tmds_pll[i].freq) { + radeon_output->tmds_pll[i].freq = 0xffffffff; break; } } @@ -567,8 +863,8 @@ Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) 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); + radeon_output->tmds_pll[i].value = RADEON_BIOS32(tmp+i*10+0x08); + radeon_output->tmds_pll[i].freq = RADEON_BIOS16(tmp+i*10+0x10); } return TRUE; } else if (RADEON_BIOS8(tmp) == 4) { @@ -576,31 +872,475 @@ Bool RADEONGetTMDSInfoFromBIOS (ScrnInfoPtr pScrn) 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); + radeon_output->tmds_pll[i].value = RADEON_BIOS32(tmp+stride+0x08); + radeon_output->tmds_pll[i].freq = RADEON_BIOS16(tmp+stride+0x10); if (i == 0) stride += 10; else stride += 6; } 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; } + +/* support for init from bios tables + * + * Based heavily on the netbsd radeonfb driver + * Written by Garrett D'Amore + * Copyright (c) 2006 Itronix Inc. + * + */ + +/* bios table defines */ + +#define RADEON_TABLE_ENTRY_FLAG_MASK 0xe000 +#define RADEON_TABLE_ENTRY_INDEX_MASK 0x1fff +#define RADEON_TABLE_ENTRY_COMMAND_MASK 0x00ff + +#define RADEON_TABLE_FLAG_WRITE_INDEXED 0x0000 +#define RADEON_TABLE_FLAG_WRITE_DIRECT 0x2000 +#define RADEON_TABLE_FLAG_MASK_INDEXED 0x4000 +#define RADEON_TABLE_FLAG_MASK_DIRECT 0x6000 +#define RADEON_TABLE_FLAG_DELAY 0x8000 +#define RADEON_TABLE_FLAG_SCOMMAND 0xa000 + +#define RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK 0x03 +#define RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE 0x08 + +#define RADEON_PLL_FLAG_MASK 0xc0 +#define RADEON_PLL_INDEX_MASK 0x3f + +#define RADEON_PLL_FLAG_WRITE 0x00 +#define RADEON_PLL_FLAG_MASK_BYTE 0x40 +#define RADEON_PLL_FLAG_WAIT 0x80 + +#define RADEON_PLL_WAIT_150MKS 1 +#define RADEON_PLL_WAIT_5MS 2 +#define RADEON_PLL_WAIT_MC_BUSY_MASK 3 +#define RADEON_PLL_WAIT_DLL_READY_MASK 4 +#define RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24 5 + +static CARD16 +RADEONValidateBIOSOffset(ScrnInfoPtr pScrn, CARD16 offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + CARD8 revision = RADEON_BIOS8(offset - 1); + + if (revision > 0x10) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Bad revision %d for BIOS table\n", revision); + return 0; + } + + if (offset < 0x60) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Bad offset 0x%x for BIOS Table\n", offset); + return 0; + } + + return offset; +} + +Bool +RADEONGetBIOSInitTableOffsets(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + CARD8 val; + + if (!info->VBIOS) { + return FALSE; + } else { + if (info->IsAtomBios) { + return FALSE; + } else { + info->BiosTable.revision = RADEON_BIOS8(info->ROMHeaderStart + 4); + info->BiosTable.rr1_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x0c); + if (info->BiosTable.rr1_offset) { + info->BiosTable.rr1_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr1_offset); + } + if (info->BiosTable.revision > 0x09) + return TRUE; + info->BiosTable.rr2_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x4e); + if (info->BiosTable.rr2_offset) { + info->BiosTable.rr2_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.rr2_offset); + } + info->BiosTable.dyn_clk_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x52); + if (info->BiosTable.dyn_clk_offset) { + info->BiosTable.dyn_clk_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.dyn_clk_offset); + } + info->BiosTable.pll_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x46); + if (info->BiosTable.pll_offset) { + info->BiosTable.pll_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.pll_offset); + } + info->BiosTable.mem_config_offset = RADEON_BIOS16(info->ROMHeaderStart + 0x48); + if (info->BiosTable.mem_config_offset) { + info->BiosTable.mem_config_offset = + RADEONValidateBIOSOffset(pScrn, info->BiosTable.mem_config_offset); + } + if (info->BiosTable.mem_config_offset) { + info->BiosTable.mem_reset_offset = info->BiosTable.mem_config_offset; + if (info->BiosTable.mem_reset_offset) { + while (RADEON_BIOS8(info->BiosTable.mem_reset_offset)) + info->BiosTable.mem_reset_offset++; + info->BiosTable.mem_reset_offset++; + info->BiosTable.mem_reset_offset += 2; + } + } + if (info->BiosTable.mem_config_offset) { + info->BiosTable.short_mem_offset = info->BiosTable.mem_config_offset; + if ((info->BiosTable.short_mem_offset != 0) && + (RADEON_BIOS8(info->BiosTable.short_mem_offset - 2) <= 64)) + info->BiosTable.short_mem_offset += + RADEON_BIOS8(info->BiosTable.short_mem_offset - 3); + } + if (info->BiosTable.rr2_offset) { + info->BiosTable.rr3_offset = info->BiosTable.rr2_offset; + if (info->BiosTable.rr3_offset) { + while ((val = RADEON_BIOS8(info->BiosTable.rr3_offset + 1)) != 0) { + if (val & 0x40) + info->BiosTable.rr3_offset += 10; + else if (val & 0x80) + info->BiosTable.rr3_offset += 4; + else + info->BiosTable.rr3_offset += 6; + } + info->BiosTable.rr3_offset += 2; + } + } + + if (info->BiosTable.rr3_offset) { + info->BiosTable.rr4_offset = info->BiosTable.rr3_offset; + if (info->BiosTable.rr4_offset) { + while ((val = RADEON_BIOS8(info->BiosTable.rr4_offset + 1)) != 0) { + if (val & 0x40) + info->BiosTable.rr4_offset += 10; + else if (val & 0x80) + info->BiosTable.rr4_offset += 4; + else + info->BiosTable.rr4_offset += 6; + } + info->BiosTable.rr4_offset += 2; + } + } + + if (info->BiosTable.rr3_offset + 1 == info->BiosTable.pll_offset) { + info->BiosTable.rr3_offset = 0; + info->BiosTable.rr4_offset = 0; + } + + return TRUE; + + } + } +} + +static void +RADEONRestoreBIOSRegBlock(ScrnInfoPtr pScrn, CARD16 table_offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 offset = table_offset; + CARD16 value, flag, index, count; + CARD32 andmask, ormask, val, channel_complete_mask; + CARD8 command; + + if (offset == 0) + return; + + while ((value = RADEON_BIOS16(offset)) != 0) { + flag = value & RADEON_TABLE_ENTRY_FLAG_MASK; + index = value & RADEON_TABLE_ENTRY_INDEX_MASK; + command = value & RADEON_TABLE_ENTRY_COMMAND_MASK; + + offset += 2; + + switch (flag) { + case RADEON_TABLE_FLAG_WRITE_INDEXED: + val = RADEON_BIOS32(offset); + ErrorF("WRITE INDEXED: 0x%x 0x%x\n", + index, (unsigned)val); + OUTREG(RADEON_MM_INDEX, index); + OUTREG(RADEON_MM_DATA, val); + offset += 4; + break; + + case RADEON_TABLE_FLAG_WRITE_DIRECT: + val = RADEON_BIOS32(offset); + ErrorF("WRITE DIRECT: 0x%x 0x%x\n", index, (unsigned)val); + OUTREG(index, val); + offset += 4; + break; + + case RADEON_TABLE_FLAG_MASK_INDEXED: + andmask = RADEON_BIOS32(offset); + offset += 4; + ormask = RADEON_BIOS32(offset); + offset += 4; + ErrorF("MASK INDEXED: 0x%x 0x%x 0x%x\n", + index, (unsigned)andmask, (unsigned)ormask); + OUTREG(RADEON_MM_INDEX, index); + val = INREG(RADEON_MM_DATA); + val = (val & andmask) | ormask; + OUTREG(RADEON_MM_DATA, val); + break; + + case RADEON_TABLE_FLAG_MASK_DIRECT: + andmask = RADEON_BIOS32(offset); + offset += 4; + ormask = RADEON_BIOS32(offset); + offset += 4; + ErrorF("MASK DIRECT: 0x%x 0x%x 0x%x\n", + index, (unsigned)andmask, (unsigned)ormask); + val = INREG(index); + val = (val & andmask) | ormask; + OUTREG(index, val); + break; + + case RADEON_TABLE_FLAG_DELAY: + count = RADEON_BIOS16(offset); + ErrorF("delay: %d\n", count); + usleep(count); + offset += 2; + break; + + case RADEON_TABLE_FLAG_SCOMMAND: + ErrorF("SCOMMAND 0x%x\n", command); + switch (command) { + case RADEON_TABLE_SCOMMAND_WAIT_MC_BUSY_MASK: + count = RADEON_BIOS16(offset); + ErrorF("SCOMMAND_WAIT_MC_BUSY_MASK %d\n", count); + while (count--) { + if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + + case RADEON_TABLE_SCOMMAND_WAIT_MEM_PWRUP_COMPLETE: + count = RADEON_BIOS16(offset); + ErrorF("SCOMMAND_WAIT_MEM_PWRUP_COMPLETE %d\n", count); + /* may need to take into account how many memory channels + * each card has + */ + if (IS_R300_VARIANT) + channel_complete_mask = R300_MEM_PWRUP_COMPLETE; + else + channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; + while (count--) { + /* XXX: may need indexed access */ + if ((INREG(RADEON_MEM_STR_CNTL) & + channel_complete_mask) == + channel_complete_mask) + break; + } + break; + + } + offset += 2; + break; + } + } +} + +static void +RADEONRestoreBIOSMemBlock(ScrnInfoPtr pScrn, CARD16 table_offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 offset = table_offset; + CARD16 count; + CARD32 ormask, val, channel_complete_mask; + CARD8 index; + + if (offset == 0) + return; + + while ((index = RADEON_BIOS8(offset)) != 0xff) { + offset++; + if (index == 0x0f) { + count = 20000; + ErrorF("MEM_WAIT_MEM_PWRUP_COMPLETE %d\n", count); + /* may need to take into account how many memory channels + * each card has + */ + if (IS_R300_VARIANT) + channel_complete_mask = R300_MEM_PWRUP_COMPLETE; + else + channel_complete_mask = RADEON_MEM_PWRUP_COMPLETE; + while (count--) { + /* XXX: may need indexed access */ + if ((INREG(RADEON_MEM_STR_CNTL) & + channel_complete_mask) == + channel_complete_mask) + break; + } + } else { + ormask = RADEON_BIOS16(offset); + offset += 2; + + ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", + RADEON_SDRAM_MODE_MASK, (unsigned)ormask); + + /* can this use direct access? */ + OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); + val = INREG(RADEON_MM_DATA); + val = (val & RADEON_SDRAM_MODE_MASK) | ormask; + OUTREG(RADEON_MM_DATA, val); + + ormask = (CARD32)index << 24; + + ErrorF("INDEX RADEON_MEM_SDRAM_MODE_REG %x %x\n", + RADEON_B3MEM_RESET_MASK, (unsigned)ormask); + + /* can this use direct access? */ + OUTREG(RADEON_MM_INDEX, RADEON_MEM_SDRAM_MODE_REG); + val = INREG(RADEON_MM_DATA); + val = (val & RADEON_B3MEM_RESET_MASK) | ormask; + OUTREG(RADEON_MM_DATA, val); + } + } +} + +static void +RADEONRestoreBIOSPllBlock(ScrnInfoPtr pScrn, CARD16 table_offset) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + CARD16 offset = table_offset; + CARD8 index, shift; + CARD32 andmask, ormask, val, clk_pwrmgt_cntl; + CARD16 count; + + if (offset == 0) + return; + + while ((index = RADEON_BIOS8(offset)) != 0) { + offset++; + + switch (index & RADEON_PLL_FLAG_MASK) { + case RADEON_PLL_FLAG_WAIT: + switch (index & RADEON_PLL_INDEX_MASK) { + case RADEON_PLL_WAIT_150MKS: + ErrorF("delay: 150 us\n"); + usleep(150); + break; + case RADEON_PLL_WAIT_5MS: + ErrorF("delay: 5 ms\n"); + usleep(5000); + break; + + case RADEON_PLL_WAIT_MC_BUSY_MASK: + count = 1000; + ErrorF("PLL_WAIT_MC_BUSY_MASK %d\n", count); + while (count--) { + if (!(INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & + RADEON_MC_BUSY)) + break; + } + break; + + case RADEON_PLL_WAIT_DLL_READY_MASK: + count = 1000; + ErrorF("PLL_WAIT_DLL_READY_MASK %d\n", count); + while (count--) { + if (INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL) & + RADEON_DLL_READY) + break; + } + break; + + case RADEON_PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24: + ErrorF("PLL_WAIT_CHK_SET_CLK_PWRMGT_CNTL24\n"); + clk_pwrmgt_cntl = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL); + if (clk_pwrmgt_cntl & RADEON_CG_NO1_DEBUG_0) { + val = INPLL(pScrn, RADEON_MCLK_CNTL); + /* is this right? */ + val = (val & 0xFFFF0000) | 0x1111; /* seems like we should clear these... */ + OUTPLL(pScrn, RADEON_MCLK_CNTL, val); + usleep(10000); + OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, + clk_pwrmgt_cntl & ~RADEON_CG_NO1_DEBUG_0); + usleep(10000); + } + break; + } + break; + + case RADEON_PLL_FLAG_MASK_BYTE: + shift = RADEON_BIOS8(offset) * 8; + offset++; + + andmask = + (((CARD32)RADEON_BIOS8(offset)) << shift) | + ~((CARD32)0xff << shift); + offset++; + + ormask = ((CARD32)RADEON_BIOS8(offset)) << shift; + offset++; + + ErrorF("PLL_MASK_BYTE 0x%x 0x%x 0x%x 0x%x\n", + index, shift, (unsigned)andmask, (unsigned)ormask); + val = INPLL(pScrn, index); + val = (val & andmask) | ormask; + OUTPLL(pScrn, index, val); + break; + + case RADEON_PLL_FLAG_WRITE: + val = RADEON_BIOS32(offset); + ErrorF("PLL_WRITE 0x%x 0x%x\n", index, (unsigned)val); + OUTPLL(pScrn, index, val); + offset += 4; + break; + } + } +} + +Bool +RADEONPostCardFromBIOSTables(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + + if (!info->VBIOS) { + return FALSE; + } else { + if (info->IsAtomBios) { + return FALSE; + } else { + if (info->BiosTable.rr1_offset) { + ErrorF("rr1 restore, 0x%x\n", info->BiosTable.rr1_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr1_offset); + } + if (info->BiosTable.revision < 0x09) { + if (info->BiosTable.pll_offset) { + ErrorF("pll restore, 0x%x\n", info->BiosTable.pll_offset); + RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.pll_offset); + } + if (info->BiosTable.rr2_offset) { + ErrorF("rr2 restore, 0x%x\n", info->BiosTable.rr2_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr2_offset); + } + if (info->BiosTable.rr4_offset) { + ErrorF("rr4 restore, 0x%x\n", info->BiosTable.rr4_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr4_offset); + } + if (info->BiosTable.mem_reset_offset) { + ErrorF("mem reset restore, 0x%x\n", info->BiosTable.mem_reset_offset); + RADEONRestoreBIOSMemBlock(pScrn, info->BiosTable.mem_reset_offset); + } + if (info->BiosTable.rr3_offset) { + ErrorF("rr3 restore, 0x%x\n", info->BiosTable.rr3_offset); + RADEONRestoreBIOSRegBlock(pScrn, info->BiosTable.rr3_offset); + } + if (info->BiosTable.dyn_clk_offset) { + ErrorF("dyn_clk restore, 0x%x\n", info->BiosTable.dyn_clk_offset); + RADEONRestoreBIOSPllBlock(pScrn, info->BiosTable.dyn_clk_offset); + } + } + } + } + return TRUE; +} diff --git a/src/radeon_common.h b/src/radeon_common.h index 3f2c6aba..467addf4 100644 --- a/src/radeon_common.h +++ b/src/radeon_common.h @@ -420,6 +420,8 @@ typedef union { #define RADEON_PARAM_SAREA_HANDLE 9 #define RADEON_PARAM_GART_TEX_HANDLE 10 #define RADEON_PARAM_SCRATCH_OFFSET 11 +#define RADEON_PARAM_CARD_TYPE 12 +#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ typedef struct drm_radeon_getparam { int param; @@ -473,7 +475,7 @@ typedef struct drm_radeon_set_param { #define RADEON_SETPARAM_PCIGART_LOCATION 3 #define RADEON_SETPARAM_NEW_MEMMAP 4 #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 - +#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ /* 1.14: Clients can allocate/free a surface */ typedef struct drm_radeon_surface_alloc { @@ -486,4 +488,7 @@ typedef struct drm_radeon_surface_free { unsigned int address; } drmRadeonSurfaceFree; +#define DRM_RADEON_VBLANK_CRTC1 1 +#define DRM_RADEON_VBLANK_CRTC2 2 + #endif diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c index 70f7ddc1..6a999af5 100644 --- a/src/radeon_commonfuncs.c +++ b/src/radeon_commonfuncs.c @@ -156,9 +156,10 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) #endif #if 0 - RADEONTRACE(("WaitForIdle (entering): %d entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "WaitForIdle (entering): %d entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS)); #endif /* Wait for the engine to go idle */ @@ -171,9 +172,10 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) return; } } - RADEONTRACE(("Idle timed out: %u entries, stat=0x%08x\n", - INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, - INREG(RADEON_RBBM_STATUS))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Idle timed out: %u entries, stat=0x%08x\n", + INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, + INREG(RADEON_RBBM_STATUS)); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); RADEONEngineReset(pScrn); diff --git a/src/radeon_crtc.c b/src/radeon_crtc.c new file mode 100644 index 00000000..e976e2c9 --- /dev/null +++ b/src/radeon_crtc.c @@ -0,0 +1,1317 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, 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, 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" + +#ifdef XF86DRI +#define _XF86DRI_SERVER_ +#include "radeon_dri.h" +#include "radeon_sarea.h" +#include "sarea.h" +#endif + +void radeon_crtc_load_lut(xf86CrtcPtr crtc); + +static void +radeon_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + int mask; + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + mask = radeon_crtc->crtc_id ? (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS | RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_REQ_EN_B) : (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_VSYNC_DIS); + + + switch(mode) { + case DPMSModeOn: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask); + } + break; + case DPMSModeStandby: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), ~mask); + } + break; + case DPMSModeSuspend: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), ~mask); + } + break; + case DPMSModeOff: + if (radeon_crtc->crtc_id) { + OUTREGP(RADEON_CRTC2_GEN_CNTL, mask, ~mask); + } else { + OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~RADEON_CRTC_DISP_REQ_EN_B); + OUTREGP(RADEON_CRTC_EXT_CNTL, mask, ~mask); + } + break; + } + + if (mode != DPMSModeOff) + radeon_crtc_load_lut(crtc); +} + +static Bool +radeon_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void +radeon_crtc_mode_prepare(xf86CrtcPtr crtc) +{ + radeon_crtc_dpms(crtc, DPMSModeOff); +} + +/* Define common registers for requested video mode */ +static void +RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) +{ + save->ovr_clr = 0; + save->ovr_wid_left_right = 0; + save->ovr_wid_top_bottom = 0; + save->ov0_scale_cntl = 0; + save->subpic_cntl = 0; + save->viph_control = 0; + save->i2c_cntl_1 = 0; + save->rbbm_soft_reset = 0; + save->cap0_trig_cntl = 0; + save->cap1_trig_cntl = 0; + save->bus_cntl = info->BusCntl; + /* + * If bursts are enabled, turn on discards + * Radeon doesn't have write bursts + */ + if (save->bus_cntl & (RADEON_BUS_READ_BURST)) + save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; +} + +static void +RADEONInitSurfaceCntl(xf86CrtcPtr crtc, RADEONSavePtr save) +{ + ScrnInfoPtr pScrn = crtc->scrn; + + save->surface_cntl = 0; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* We must set both apertures as they can be both used to map the entire + * video memory. -BenH. + */ + switch (pScrn->bitsPerPixel) { + case 16: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; + break; + + case 32: + save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; + save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; + break; + } +#endif + +} + +static Bool +RADEONInitCrtcBase(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int Base; +#ifdef XF86DRI + RADEONSAREAPrivPtr pSAREAPriv; + XF86DRISAREAPtr pSAREA; +#endif + + save->crtc_offset = pScrn->fbOffset; +#ifdef XF86DRI + if (info->allowPageFlip) + save->crtc_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; + else +#endif + save->crtc_offset_cntl = 0; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) + save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + Base = pScrn->fbOffset; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) { + /* On r300/r400 when tiling is enabled crtc_offset is set to the address of + * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc + * Makes tiling MUCH easier. + */ + save->crtc_tile_x0_y0 = x | (y << 16); + Base &= ~0x7ff; + } else { + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ + /*save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL) & ~0xf;*/ +#if 0 + /* try to get rid of flickering when scrolling at least for 2d */ +#ifdef XF86DRI + if (!info->have3DWindows) +#endif + save->crtc_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; +#endif + + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + save->crtc_offset_cntl = save->crtc_offset_cntl | (y % 16); + } + } + else { + int offset = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + } + + if (crtc->rotatedData != NULL) { + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + } + + Base &= ~7; /* 3 lower bits are always 0 */ + + +#ifdef XF86DRI + if (info->directRenderingInited) { + /* note cannot use pScrn->pScreen since this is unitialized when called from + RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ + /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for + *** pageflipping! + ***/ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + /* can't get at sarea in a semi-sane way? */ + pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); + + pSAREA->frame.x = (Base / info->CurrentLayout.pixel_bytes) + % info->CurrentLayout.displayWidth; + pSAREA->frame.y = (Base / info->CurrentLayout.pixel_bytes) + / info->CurrentLayout.displayWidth; + pSAREA->frame.width = pScrn->frameX1 - x + 1; + pSAREA->frame.height = pScrn->frameY1 - y + 1; + + if (pSAREAPriv->pfCurrentPage == 1) { + Base += info->backOffset - info->frontOffset; + } + } +#endif + save->crtc_offset = Base; + + return TRUE; + +} + +/* Define CRTC registers for requested video mode */ +static Bool +RADEONInitCrtcRegisters(xf86CrtcPtr crtc, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", + info->CurrentLayout.bitsPerPixel); + return FALSE; + } + + save->bios_4_scratch = info->SavedReg.bios_4_scratch; + save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN + | RADEON_CRTC_EN + | (format << 8) + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_CSYNC) + ? RADEON_CRTC_CSYNC_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC_INTERLACE_EN + : 0)); + + save->crtc_ext_cntl |= (RADEON_XCRT_CNT_EN| + RADEON_CRTC_VSYNC_DIS | + RADEON_CRTC_HSYNC_DIS | + RADEON_CRTC_DISPLAY_DIS); + + save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; + save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; + + 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->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) + << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + + save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC_V_SYNC_POL + : 0)); + + save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / + (pScrn->bitsPerPixel * 8)); + save->crtc_pitch |= save->crtc_pitch << 16; + + save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; + save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; + save->fp_crtc_h_total_disp = save->crtc_h_total_disp; + save->fp_crtc_v_total_disp = save->crtc_v_total_disp; + + 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)); + } + + return TRUE; +} + +static Bool +RADEONInitCrtc2Base(xf86CrtcPtr crtc, RADEONSavePtr save, + int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int Base; +#ifdef XF86DRI + RADEONSAREAPrivPtr pSAREAPriv; + XF86DRISAREAPtr pSAREA; +#endif + + /* It seems all fancy options apart from pflip can be safely disabled + */ + save->crtc2_offset = pScrn->fbOffset; +#ifdef XF86DRI + if (info->allowPageFlip) + save->crtc2_offset_cntl = RADEON_CRTC_OFFSET_FLIP_CNTL; + else +#endif + save->crtc2_offset_cntl = 0; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; + } + else { + if (IS_R300_VARIANT) + save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | + R300_CRTC_MICRO_TILE_BUFFER_DIS | + R300_CRTC_MACRO_TILE_EN); + else + save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; + } + + Base = pScrn->fbOffset; + + if (info->tilingEnabled && (crtc->rotatedData == NULL)) { + if (IS_R300_VARIANT) { + /* On r300/r400 when tiling is enabled crtc_offset is set to the address of + * the surface. the x/y offsets are handled by the X_Y tile reg for each crtc + * Makes tiling MUCH easier. + */ + save->crtc2_tile_x0_y0 = x | (y << 16); + Base &= ~0x7ff; + } else { + /* note we cannot really simply use the info->ModeReg.crtc_offset_cntl value, since the + drm might have set FLIP_CNTL since we wrote that. Unfortunately FLIP_CNTL causes + flickering when scrolling vertically in a virtual screen, possibly because crtc will + pick up the new offset value at the end of each scanline, but the new offset_cntl value + only after a vsync. We'd probably need to wait (in drm) for vsync and only then update + OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ + /*save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL) & ~0xf;*/ +#if 0 + /* try to get rid of flickering when scrolling at least for 2d */ +#ifdef XF86DRI + if (!info->have3DWindows) +#endif + save->crtc2_offset_cntl &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; +#endif + + int byteshift = info->CurrentLayout.bitsPerPixel >> 4; + /* crtc uses 256(bytes)x8 "half-tile" start addresses? */ + int tile_addr = (((y >> 3) * info->CurrentLayout.displayWidth + x) >> (8 - byteshift)) << 11; + Base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); + save->crtc2_offset_cntl = save->crtc_offset_cntl | (y % 16); + } + } + else { + int offset = y * info->CurrentLayout.displayWidth + x; + switch (info->CurrentLayout.pixel_code) { + case 15: + case 16: offset *= 2; break; + case 24: offset *= 3; break; + case 32: offset *= 4; break; + } + Base += offset; + } + + if (crtc->rotatedData != NULL) { + Base = pScrn->fbOffset + (char *)crtc->rotatedData - (char *)info->FB; + } + + Base &= ~7; /* 3 lower bits are always 0 */ + +#ifdef XF86DRI + if (info->directRenderingInited) { + /* note cannot use pScrn->pScreen since this is unitialized when called from + RADEONScreenInit, and we need to call from there to get mergedfb + pageflip working */ + /*** NOTE: r3/4xx will need sarea and drm pageflip updates to handle the xytile regs for + *** pageflipping! + ***/ + pSAREAPriv = DRIGetSAREAPrivate(screenInfo.screens[pScrn->scrnIndex]); + /* can't get at sarea in a semi-sane way? */ + pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); + + pSAREAPriv->crtc2_base = Base; + + if (pSAREAPriv->pfCurrentPage == 1) { + Base += info->backOffset - info->frontOffset; + } + } +#endif + save->crtc2_offset = Base; + + return TRUE; +} + +/* Define CRTC2 registers for requested video mode */ +static Bool +RADEONInitCrtc2Registers(xf86CrtcPtr crtc, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + int format; + int hsync_start; + int hsync_wid; + int vsync_wid; + + switch (info->CurrentLayout.pixel_code) { + case 4: format = 1; break; + case 8: format = 2; break; + case 15: format = 3; break; /* 555 */ + case 16: format = 4; break; /* 565 */ + case 24: format = 5; break; /* RGB */ + case 32: format = 6; break; /* xRGB */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unsupported pixel depth (%d)\n", + info->CurrentLayout.bitsPerPixel); + return FALSE; + } + + save->crtc2_h_total_disp = + ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) + | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); + + hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; + if (!hsync_wid) hsync_wid = 1; + if (hsync_wid > 0x3f) hsync_wid = 0x3f; + hsync_start = mode->CrtcHSyncStart - 8; + + save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) + | (hsync_wid << 16) + | ((mode->Flags & V_NHSYNC) + ? RADEON_CRTC_H_SYNC_POL + : 0)); + + /* This works for double scan mode. */ + save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) + | ((mode->CrtcVDisplay - 1) << 16)); + + vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; + if (!vsync_wid) vsync_wid = 1; + if (vsync_wid > 0x1f) vsync_wid = 0x1f; + + save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) + | (vsync_wid << 16) + | ((mode->Flags & V_NVSYNC) + ? RADEON_CRTC2_V_SYNC_POL + : 0)); + + save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + + ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); + save->crtc2_pitch |= save->crtc2_pitch << 16; + + /* check to see if TV DAC is enabled for another crtc and keep it enabled */ + if (save->crtc2_gen_cntl & RADEON_CRTC2_CRT2_ON) + save->crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; + else + save->crtc2_gen_cntl = 0; + + save->crtc2_gen_cntl |= (RADEON_CRTC2_EN + | (format << 8) + | RADEON_CRTC2_VSYNC_DIS + | RADEON_CRTC2_HSYNC_DIS + | RADEON_CRTC2_DISP_DIS + | ((mode->Flags & V_DBLSCAN) + ? RADEON_CRTC2_DBL_SCAN_EN + : 0) + | ((mode->Flags & V_CSYNC) + ? RADEON_CRTC2_CSYNC_EN + : 0) + | ((mode->Flags & V_INTERLACE) + ? RADEON_CRTC2_INTERLACE_EN + : 0)); + + save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; + save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); + + save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; + save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; + + if (info->ChipFamily == CHIP_FAMILY_RS400) { + save->rs480_unk_e30 = 0x105DC1CC; /* because I'm worth it */ + save->rs480_unk_e34 = 0x2749D000; /* AMD really should */ + save->rs480_unk_e38 = 0x29ca71dc; /* release docs */ + save->rs480_unk_e3c = 0x28FBC3AC; /* this is so a trade secret */ + } + + return TRUE; +} + + +/* Compute n/d with rounding */ +static int RADEONDiv(int n, int d) +{ + return (n + (d / 2)) / d; +} + +/* Define PLL registers for requested video mode */ +static void +RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info, + RADEONSavePtr save, RADEONPLLPtr pll, + double dot_clock) +{ + unsigned long freq = dot_clock * 100; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 16, 5 }, /* VCLK_SRC/16 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if (info->UseBiosDividers) { + save->ppll_ref_div = info->RefDivider; + save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); + save->htotal_cntl = 0; + return; + } + + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; + if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + save->pll_output_freq = post_div->divider * freq; + + if (save->pll_output_freq >= pll->min_pll_freq + && save->pll_output_freq <= pll->max_pll_freq) break; + } + + if (!post_div->divider) { + save->pll_output_freq = freq; + post_div = &post_divs[0]; + } + + save->dot_clock_freq = freq; + save->feedback_div = RADEONDiv(pll->reference_div + * save->pll_output_freq, + pll->reference_freq); + save->post_div = post_div->divider; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "dc=%u, of=%u, fd=%d, pd=%d\n", + (unsigned)save->dot_clock_freq, + (unsigned)save->pll_output_freq, + save->feedback_div, + save->post_div); + + save->ppll_ref_div = pll->reference_div; + save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); + save->htotal_cntl = 0; + + save->vclk_ecp_cntl = (info->SavedReg.vclk_ecp_cntl & + ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; + +} + +/* Define PLL2 registers for requested video mode */ +static void +RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, + RADEONPLLPtr pll, double dot_clock, + int no_odd_postdiv) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long freq = dot_clock * 100; + + struct { + int divider; + int bitvalue; + } *post_div, post_divs[] = { + /* From RAGE 128 VR/RAGE 128 GL Register + * Reference Manual (Technical Reference + * Manual P/N RRG-G04100-C Rev. 0.04), page + * 3-17 (PLL_DIV_[3:0]). + */ + { 1, 0 }, /* VCLK_SRC */ + { 2, 1 }, /* VCLK_SRC/2 */ + { 4, 2 }, /* VCLK_SRC/4 */ + { 8, 3 }, /* VCLK_SRC/8 */ + { 3, 4 }, /* VCLK_SRC/3 */ + { 6, 6 }, /* VCLK_SRC/6 */ + { 12, 7 }, /* VCLK_SRC/12 */ + { 0, 0 } + }; + + if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; + if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; + + for (post_div = &post_divs[0]; post_div->divider; ++post_div) { + /* Odd post divider value don't work properly on the second digital + * output + */ + if (no_odd_postdiv && (post_div->divider & 1)) + continue; + save->pll_output_freq_2 = post_div->divider * freq; + if (save->pll_output_freq_2 >= pll->min_pll_freq + && save->pll_output_freq_2 <= pll->max_pll_freq) break; + } + + if (!post_div->divider) { + save->pll_output_freq_2 = freq; + post_div = &post_divs[0]; + } + + save->dot_clock_freq_2 = freq; + save->feedback_div_2 = RADEONDiv(pll->reference_div + * save->pll_output_freq_2, + pll->reference_freq); + save->post_div_2 = post_div->divider; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "dc=%u, of=%u, fd=%d, pd=%d\n", + (unsigned)save->dot_clock_freq_2, + (unsigned)save->pll_output_freq_2, + save->feedback_div_2, + save->post_div_2); + + save->p2pll_ref_div = pll->reference_div; + save->p2pll_div_0 = (save->feedback_div_2 | + (post_div->bitvalue << 16)); + save->htotal_cntl2 = 0; + + save->pixclks_cntl = ((info->SavedReg.pixclks_cntl & + ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | + RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); + +} + +static void +radeon_update_tv_routing(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + /* pixclks_cntl controls tv clock routing */ + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); +} + +static void +radeon_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + Bool tilingOld = info->tilingEnabled; + int i = 0; + double dot_clock = 0; + Bool no_odd_post_div = FALSE; + Bool update_tv_routing = FALSE; + + + if (info->allowColorTiling) { + info->tilingEnabled = (adjusted_mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; +#ifdef XF86DRI + if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { + RADEONSAREAPrivPtr pSAREAPriv; + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_SWITCH_TILING, (info->tilingEnabled ? 1 : 0)) < 0) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed changing tiling status\n"); + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + info->tilingEnabled = pSAREAPriv->tiling_enabled ? TRUE : FALSE; + } +#endif + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (output->crtc == crtc) { + if (radeon_output->MonType != MT_CRT) + no_odd_post_div = TRUE; + } + } + + ErrorF("init memmap\n"); + RADEONInitMemMapRegisters(pScrn, &info->ModeReg, info); + ErrorF("init common\n"); + RADEONInitCommonRegisters(&info->ModeReg, info); + + RADEONInitSurfaceCntl(crtc, &info->ModeReg); + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("init crtc1\n"); + RADEONInitCrtcRegisters(crtc, &info->ModeReg, adjusted_mode); + RADEONInitCrtcBase(crtc, &info->ModeReg, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll1\n"); + RADEONInitPLLRegisters(pScrn, info, &info->ModeReg, &info->pll, dot_clock); + } else { + info->ModeReg.ppll_ref_div = info->SavedReg.ppll_ref_div; + info->ModeReg.ppll_div_3 = info->SavedReg.ppll_div_3; + info->ModeReg.htotal_cntl = info->SavedReg.htotal_cntl; + } + break; + case 1: + ErrorF("init crtc2\n"); + RADEONInitCrtc2Registers(crtc, &info->ModeReg, adjusted_mode); + RADEONInitCrtc2Base(crtc, &info->ModeReg, x, y); + dot_clock = adjusted_mode->Clock / 1000.0; + if (dot_clock) { + ErrorF("init pll2\n"); + RADEONInitPLL2Registers(pScrn, &info->ModeReg, &info->pll, dot_clock, no_odd_post_div); + } + break; + } + + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (output->crtc == crtc) { + if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { + switch (radeon_crtc->crtc_id) { + case 0: + RADEONAdjustCrtcRegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + RADEONAdjustPLLRegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + update_tv_routing = TRUE; + break; + case 1: + RADEONAdjustCrtc2RegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + RADEONAdjustPLL2RegistersForTV(pScrn, &info->ModeReg, adjusted_mode, output); + break; + } + } + } + } + + ErrorF("restore memmap\n"); + RADEONRestoreMemMapRegisters(pScrn, &info->ModeReg); + ErrorF("restore common\n"); + RADEONRestoreCommonRegisters(pScrn, &info->ModeReg); + + switch (radeon_crtc->crtc_id) { + case 0: + ErrorF("restore crtc1\n"); + RADEONRestoreCrtcRegisters(pScrn, &info->ModeReg); + ErrorF("restore pll1\n"); + RADEONRestorePLLRegisters(pScrn, &info->ModeReg); + break; + case 1: + ErrorF("restore crtc2\n"); + RADEONRestoreCrtc2Registers(pScrn, &info->ModeReg); + ErrorF("restore pll2\n"); + RADEONRestorePLL2Registers(pScrn, &info->ModeReg); + break; + } + + /* pixclks_cntl handles tv-out clock routing */ + if (update_tv_routing) + radeon_update_tv_routing(pScrn, &info->ModeReg); + + if (info->DispPriority) + RADEONInitDispBandwidth(pScrn); + + if (info->tilingEnabled != tilingOld) { + /* need to redraw front buffer, I guess this can be considered a hack ? */ + xf86EnableDisableFBAccess(pScrn->scrnIndex, FALSE); + RADEONChangeSurfaces(pScrn); + xf86EnableDisableFBAccess(pScrn->scrnIndex, TRUE); + /* xf86SetRootClip would do, but can't access that here */ + } + + /* reset ecp_div for Xv */ + info->ecp_div = -1; + +} + +static void +radeon_crtc_mode_commit(xf86CrtcPtr crtc) +{ + radeon_crtc_dpms(crtc, DPMSModeOn); +} + +void radeon_crtc_load_lut(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int i; + + if (!crtc->enabled) + return; + + PAL_SELECT(radeon_crtc->crtc_id); + + for (i = 0; i < 256; i++) { + OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]); + } + +} + + +static void +radeon_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, + CARD16 *blue, int size) +{ + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + ScrnInfoPtr pScrn = crtc->scrn; + int i, j; + + if (pScrn->depth == 16) { + for (i = 0; i < 64; i++) { + if (i <= 31) { + for (j = 0; j < 8; j++) { + radeon_crtc->lut_r[i * 8 + j] = red[i] >> 8; + radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 8; + } + } + + for (j = 0; j < 4; j++) { + radeon_crtc->lut_g[i * 4 + j] = green[i] >> 8; + } + } + } else { + for (i = 0; i < 256; i++) { + radeon_crtc->lut_r[i] = red[i] >> 8; + radeon_crtc->lut_g[i] = green[i] >> 8; + radeon_crtc->lut_b[i] = blue[i] >> 8; + } + } + + radeon_crtc_load_lut(crtc); +} + +static Bool +radeon_crtc_lock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + +#ifdef XF86DRI + if (info->CPStarted && pScrn->pScreen) { + DRILock(pScrn->pScreen, 0); + if (info->accelOn) + RADEON_SYNC(info, pScrn); + return TRUE; + } +#endif + if (info->accelOn) + RADEON_SYNC(info, pScrn); + + return FALSE; + +} + +static void +radeon_crtc_unlock(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + +#ifdef XF86DRI + if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); +#endif + + if (info->accelOn) + RADEON_SYNC(info, pScrn); +} + +#ifdef USE_XAA +/** + * Allocates memory from the XF86 linear allocator, but also purges + * memory if possible to cause the allocation to succeed. + */ +static FBLinearPtr +radeon_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length, + int granularity, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData) +{ + FBLinearPtr linear; + int max_size; + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, + removeCB, privData); + if (linear != NULL) + return linear; + + /* The above allocation didn't succeed, so purge unlocked stuff and try + * again. + */ + xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity, + PRIORITY_EXTREME); + + if (max_size < length) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, + removeCB, privData); + + return linear; +} +#endif + +/** + * Allocates memory for a locked-in-framebuffer shadow of the given + * width and height for this CRTC's rotated shadow framebuffer. + */ + +static void * +radeon_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = pScrn->pScreen; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + unsigned long rotate_pitch; + unsigned long rotate_offset; + int align = 4096, size; + int cpp = pScrn->bitsPerPixel / 8; + + rotate_pitch = pScrn->displayWidth * cpp; + size = rotate_pitch * height; + +#ifdef USE_EXA + /* We could get close to what we want here by just creating a pixmap like + * normal, but we have to lock it down in framebuffer, and there is no + * setter for offscreen area locking in EXA currently. So, we just + * allocate offscreen memory and fake up a pixmap header for it. + */ + if (info->useEXA) { + assert(radeon_crtc->rotate_mem_exa == NULL); + + radeon_crtc->rotate_mem_exa = exaOffscreenAlloc(pScreen, size, align, + TRUE, NULL, NULL); + if (radeon_crtc->rotate_mem_exa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + rotate_offset = radeon_crtc->rotate_mem_exa->offset; + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + /* The XFree86 linear allocator operates in units of screen pixels, + * sadly. + */ + size = (size + cpp - 1) / cpp; + align = (align + cpp - 1) / cpp; + + assert(radeon_crtc->rotate_mem_xaa == NULL); + + radeon_crtc->rotate_mem_xaa = + radeon_xf86AllocateOffscreenLinear(pScreen, size, align, + NULL, NULL, NULL); + if (radeon_crtc->rotate_mem_xaa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } +#ifdef XF86DRI + rotate_offset = info->frontOffset + + radeon_crtc->rotate_mem_xaa->offset * cpp; +#endif + } +#endif /* USE_XAA */ + + return info->FB + rotate_offset; +} + +/** + * Creates a pixmap for this CRTC's rotated shadow framebuffer. + */ +static PixmapPtr +radeon_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + unsigned long rotate_pitch; + PixmapPtr rotate_pixmap; + int cpp = pScrn->bitsPerPixel / 8; + + if (!data) + data = radeon_crtc_shadow_allocate(crtc, width, height); + + rotate_pitch = pScrn->displayWidth * cpp; + + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + rotate_pitch, + data); + + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + } + + return rotate_pixmap; +} + +static void +radeon_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + if (rotate_pixmap) + FreeScratchPixmapHeader(rotate_pixmap); + + if (data) { +#ifdef USE_EXA + if (info->useEXA && radeon_crtc->rotate_mem_exa != NULL) { + exaOffscreenFree(pScrn->pScreen, radeon_crtc->rotate_mem_exa); + radeon_crtc->rotate_mem_exa = NULL; + } +#endif /* USE_EXA */ +#ifdef USE_XAA + if (!info->useEXA) { + xf86FreeOffscreenLinear(radeon_crtc->rotate_mem_xaa); + radeon_crtc->rotate_mem_xaa = NULL; + } +#endif /* USE_XAA */ + } +} + +static const xf86CrtcFuncsRec radeon_crtc_funcs = { + .dpms = radeon_crtc_dpms, + .save = NULL, /* XXX */ + .restore = NULL, /* XXX */ + .mode_fixup = radeon_crtc_mode_fixup, + .prepare = radeon_crtc_mode_prepare, + .mode_set = radeon_crtc_mode_set, + .commit = radeon_crtc_mode_commit, + .gamma_set = radeon_crtc_gamma_set, + .lock = radeon_crtc_lock, + .unlock = radeon_crtc_unlock, + .shadow_create = radeon_crtc_shadow_create, + .shadow_allocate = radeon_crtc_shadow_allocate, + .shadow_destroy = radeon_crtc_shadow_destroy, + .set_cursor_colors = radeon_crtc_set_cursor_colors, + .set_cursor_position = radeon_crtc_set_cursor_position, + .show_cursor = radeon_crtc_show_cursor, + .hide_cursor = radeon_crtc_hide_cursor, + .load_cursor_argb = radeon_crtc_load_cursor_argb, + .destroy = NULL, /* XXX */ +}; + +Bool RADEONAllocateControllers(ScrnInfoPtr pScrn) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + if (pRADEONEnt->Controller[0]) + return TRUE; + + pRADEONEnt->pCrtc[0] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); + if (!pRADEONEnt->pCrtc[0]) + return FALSE; + + pRADEONEnt->Controller[0] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); + if (!pRADEONEnt->Controller[0]) + return FALSE; + + pRADEONEnt->pCrtc[0]->driver_private = pRADEONEnt->Controller[0]; + pRADEONEnt->Controller[0]->crtc_id = 0; + + if (!pRADEONEnt->HasCRTC2) + return TRUE; + + pRADEONEnt->pCrtc[1] = xf86CrtcCreate(pScrn, &radeon_crtc_funcs); + if (!pRADEONEnt->pCrtc[1]) + return FALSE; + + pRADEONEnt->Controller[1] = xnfcalloc(sizeof(RADEONCrtcPrivateRec), 1); + if (!pRADEONEnt->Controller[1]) + { + xfree(pRADEONEnt->Controller[0]); + return FALSE; + } + + pRADEONEnt->pCrtc[1]->driver_private = pRADEONEnt->Controller[1]; + pRADEONEnt->Controller[1]->crtc_id = 1; + return TRUE; +} + +/** + * In the current world order, there are lists of modes per output, which may + * or may not include the mode that was asked to be set by XFree86's mode + * selection. Find the closest one, in the following preference order: + * + * - Equality + * - Closer in size to the requested mode, but no larger + * - Closer in refresh rate to the requested mode. + */ +DisplayModePtr +RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DisplayModePtr pBest = NULL, pScan = NULL; + int i; + + /* Assume that there's only one output connected to the given CRTC. */ + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc && output->probed_modes != NULL) + { + pScan = output->probed_modes; + break; + } + } + + /* If the pipe doesn't have any detected modes, just let the system try to + * spam the desired mode in. + */ + if (pScan == NULL) { + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No crtc mode list for crtc %d," + "continuing with desired mode\n", radeon_crtc->crtc_id); + return pMode; + } + + for (; pScan != NULL; pScan = pScan->next) { + assert(pScan->VRefresh != 0.0); + + /* If there's an exact match, we're done. */ + if (xf86ModesEqual(pScan, pMode)) { + pBest = pMode; + break; + } + + /* Reject if it's larger than the desired mode. */ + if (pScan->HDisplay > pMode->HDisplay || + pScan->VDisplay > pMode->VDisplay) + { + continue; + } + + if (pBest == NULL) { + pBest = pScan; + continue; + } + + /* Find if it's closer to the right size than the current best + * option. + */ + if ((pScan->HDisplay > pBest->HDisplay && + pScan->VDisplay >= pBest->VDisplay) || + (pScan->HDisplay >= pBest->HDisplay && + pScan->VDisplay > pBest->VDisplay)) + { + pBest = pScan; + continue; + } + + /* Find if it's still closer to the right refresh than the current + * best resolution. + */ + if (pScan->HDisplay == pBest->HDisplay && + pScan->VDisplay == pBest->VDisplay && + (fabs(pScan->VRefresh - pMode->VRefresh) < + fabs(pBest->VRefresh - pMode->VRefresh))) { + pBest = pScan; + } + } + + if (pBest == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "No suitable mode found to program for the pipe.\n" + " continuing with desired mode %dx%d@%.1f\n", + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + } else if (!xf86ModesEqual(pBest, pMode)) { + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc = radeon_crtc->crtc_id; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Choosing pipe %d's mode %dx%d@%.1f instead of xf86 " + "mode %dx%d@%.1f\n", crtc, + pBest->HDisplay, pBest->VDisplay, pBest->VRefresh, + pMode->HDisplay, pMode->VDisplay, pMode->VRefresh); + pMode = pBest; + } + return pMode; +} + diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c index a45198ae..f19f2bc0 100644 --- a/src/radeon_cursor.c +++ b/src/radeon_cursor.c @@ -31,7 +31,7 @@ #endif #define RADEONCTRACE(x) -/* #define RADEONCTRACE(x) RADEONTRACE(x) */ +/*#define RADEONCTRACE(x) RADEONTRACE(x) */ /* * Authors: @@ -55,24 +55,13 @@ #include "radeon_version.h" #include "radeon_reg.h" #include "radeon_macros.h" -#include "radeon_mergedfb.h" /* X and server generic header files */ #include "xf86.h" -/* Mono ARGB cursor colours (premultiplied). */ -static CARD32 mono_cursor_color[] = { - 0x00000000, /* White, fully transparent. */ - 0x00000000, /* Black, fully transparent. */ - 0xffffffff, /* White, fully opaque. */ - 0xff000000, /* Black, fully opaque. */ -}; - #define CURSOR_WIDTH 64 #define CURSOR_HEIGHT 64 -#define COMMON_CURSOR_SWAPPING_START() RADEON_SYNC(info, pScrn) - /* * The cursor bits are always 32bpp. On MSBFirst buses, * configure byte swapping to swap 32 bit units when writing @@ -84,7 +73,6 @@ static CARD32 mono_cursor_color[] = { #define CURSOR_SWAPPING_DECL_MMIO unsigned char *RADEONMMIO = info->MMIO; #define CURSOR_SWAPPING_START() \ do { \ - COMMON_CURSOR_SWAPPING_START(); \ OUTREG(RADEON_SURFACE_CNTL, \ (info->ModeReg.surface_cntl | \ RADEON_NONSURF_AP0_SWP_32BPP | RADEON_NONSURF_AP1_SWP_32BPP) & \ @@ -96,278 +84,151 @@ static CARD32 mono_cursor_color[] = { #else #define CURSOR_SWAPPING_DECL_MMIO -#define CURSOR_SWAPPING_START() \ - do { \ - COMMON_CURSOR_SWAPPING_START(); \ - } while (0) +#define CURSOR_SWAPPING_START() #define CURSOR_SWAPPING_END() #endif - -/* Set cursor foreground and background colors */ -static void RADEONSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +void +radeon_crtc_show_cursor (xf86CrtcPtr crtc) { - RADEONInfoPtr info = RADEONPTR(pScrn); - CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); - int pixel, i; - CURSOR_SWAPPING_DECL_MMIO - - RADEONCTRACE(("RADEONSetCursorColors\n")); - -#ifdef ARGB_CURSOR - /* Don't recolour cursors set with SetCursorARGB. */ - if (info->cursor_argb) - return; -#endif + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc_id = radeon_crtc->crtc_id; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; - fg |= 0xff000000; - bg |= 0xff000000; + if (crtc_id == 0) + OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN | 2 << 20, + ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); + else if (crtc_id == 1) + OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN | 2 << 20, + ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_CUR_MODE_MASK)); +} - /* Don't recolour the image if we don't have to. */ - if (fg == info->cursor_fg && bg == info->cursor_bg) - return; +void +radeon_crtc_hide_cursor (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc_id = radeon_crtc->crtc_id; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; - CURSOR_SWAPPING_START(); + if (crtc_id == 0) + OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN); + else if (crtc_id == 1) + OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); - /* Note: We assume that the pixels are either fully opaque or fully - * transparent, so we won't premultiply them, and we can just - * check for non-zero pixel values; those are either fg or bg - */ - for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++) - if ((pixel = *pixels)) - *pixels = (pixel == info->cursor_fg) ? fg : bg; - CURSOR_SWAPPING_END(); - info->cursor_fg = fg; - info->cursor_bg = bg; } - -/* Set cursor position to (x,y) with offset into cursor bitmap at - * (xorigin,yorigin) - */ -static void RADEONSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +void +radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) { + ScrnInfoPtr pScrn = crtc->scrn; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + int crtc_id = radeon_crtc->crtc_id; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - xf86CursorInfoPtr cursor = info->cursor; - int xorigin = 0; - int yorigin = 0; - int total_y = pScrn->frameY1 - pScrn->frameY0; - int stride = 256; - - if(info->MergedFB) { - RADEONCTRACE(("RADEONSetCursorPositionMerged\n")); - RADEONSetCursorPositionMerged(pScrn, x, y); - return; - } - - RADEONCTRACE(("RADEONSetCursorPosition\n")); + int xorigin = 0, yorigin = 0; + int stride = 256; + DisplayModePtr mode = &crtc->mode; if (x < 0) xorigin = -x+1; if (y < 0) yorigin = -y+1; - if (y > total_y) y = total_y; - if (info->Flags & V_DBLSCAN) y *= 2; - if (xorigin >= cursor->MaxWidth) xorigin = cursor->MaxWidth - 1; - if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1; + if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1; + if (yorigin >= CURSOR_HEIGHT) yorigin = CURSOR_HEIGHT - 1; - if (!info->IsSecondary) { + if (mode->Flags & V_INTERLACE) + y /= 2; + else if (mode->Flags & V_DBLSCAN) + y *= 2; + + if (crtc_id == 0) { OUTREG(RADEON_CUR_HORZ_VERT_OFF, (RADEON_CUR_LOCK | (xorigin << 16) | yorigin)); OUTREG(RADEON_CUR_HORZ_VERT_POSN, (RADEON_CUR_LOCK | ((xorigin ? 0 : x) << 16) | (yorigin ? 0 : y))); - RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d\n", - info->cursor_offset + pScrn->fbOffset, yorigin, stride)); + RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n", + info->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); OUTREG(RADEON_CUR_OFFSET, info->cursor_offset + pScrn->fbOffset + yorigin * stride); - } else { + } else if (crtc_id == 1) { OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) | yorigin)); OUTREG(RADEON_CUR2_HORZ_VERT_POSN, (RADEON_CUR2_LOCK - | ((xorigin ? 0 : x) << 16) - | (yorigin ? 0 : y))); + | ((xorigin ? 0 : x) << 16) + | (yorigin ? 0 : y))); + RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n", + info->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); OUTREG(RADEON_CUR2_OFFSET, - info->cursor_offset + pScrn->fbOffset + yorigin * stride); + info->cursor_offset + pScrn->fbOffset + yorigin * stride); } } -/* Copy cursor image from `image' to video memory. RADEONSetCursorPosition - * will be called after this, so we can ignore xorigin and yorigin. - */ -static void RADEONLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) +void +radeon_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - CARD8 *s = (CARD8 *)(pointer)image; - CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); - CARD32 save1 = 0; - CARD32 save2 = 0; - CARD8 chunk; - CARD32 i, j; - - RADEONCTRACE(("RADEONLoadCursorImage (at %x)\n", info->cursor_offset)); - - if (!info->IsSecondary) { - save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); - save1 |= (CARD32) (2 << 20); - OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); - } + ScrnInfoPtr pScrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD32 *pixels = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); + int pixel, i; + CURSOR_SWAPPING_DECL_MMIO - 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); - } + RADEONCTRACE(("RADEONSetCursorColors\n")); #ifdef ARGB_CURSOR - info->cursor_argb = FALSE; + /* Don't recolour cursors set with SetCursorARGB. */ + if (info->cursor_argb) + return; #endif - /* - * Convert the bitmap to ARGB32. - * - * HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 always places - * source in the low bit of the pair and mask in the high bit, - * and MSBFirst machines set HARDWARE_CURSOR_BIT_ORDER_MSBFIRST - * (which actually bit swaps the image) to make the bits LSBFirst - */ - CURSOR_SWAPPING_START(); -#define ARGB_PER_CHUNK (8 * sizeof (chunk) / 2) - for (i = 0; i < (CURSOR_WIDTH * CURSOR_HEIGHT / ARGB_PER_CHUNK); i++) { - chunk = *s++; - for (j = 0; j < ARGB_PER_CHUNK; j++, chunk >>= 2) - *d++ = mono_cursor_color[chunk & 3]; - } - CURSOR_SWAPPING_END(); - - info->cursor_bg = mono_cursor_color[2]; - info->cursor_fg = mono_cursor_color[3]; - - if (!info->IsSecondary) - OUTREG(RADEON_CRTC_GEN_CNTL, save1); - - if (info->IsSecondary || info->MergedFB) - OUTREG(RADEON_CRTC2_GEN_CNTL, save2); - -} - -/* Hide hardware cursor. */ -static void RADEONHideCursor(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - RADEONCTRACE(("RADEONHideCursor\n")); - - if (info->IsSecondary || info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~RADEON_CRTC2_CUR_EN); - - if (!info->IsSecondary) - OUTREGP(RADEON_CRTC_GEN_CNTL, 0, ~RADEON_CRTC_CUR_EN); -} - -/* Show hardware cursor. */ -static void RADEONShowCursor(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - RADEONCTRACE(("RADEONShowCursor\n")); + fg |= 0xff000000; + bg |= 0xff000000; - if (info->IsSecondary || info->MergedFB) - OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_CUR_EN, - ~RADEON_CRTC2_CUR_EN); + /* Don't recolour the image if we don't have to. */ + if (fg == info->cursor_fg && bg == info->cursor_bg) + return; - if (!info->IsSecondary) - OUTREGP(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_CUR_EN, - ~RADEON_CRTC_CUR_EN); -} + CURSOR_SWAPPING_START(); -/* Determine if hardware cursor is in use. */ -static Bool RADEONUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) -{ - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); + /* Note: We assume that the pixels are either fully opaque or fully + * transparent, so we won't premultiply them, and we can just + * check for non-zero pixel values; those are either fg or bg + */ + for (i = 0; i < CURSOR_WIDTH * CURSOR_HEIGHT; i++, pixels++) + if ((pixel = *pixels)) + *pixels = (pixel == info->cursor_fg) ? fg : bg; - return info->cursor ? TRUE : FALSE; + CURSOR_SWAPPING_END(); + info->cursor_fg = fg; + info->cursor_bg = bg; } #ifdef ARGB_CURSOR -#include "cursorstr.h" -static Bool RADEONUseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) -{ - if (RADEONUseHWCursor(pScreen, pCurs) && - pCurs->bits->height <= CURSOR_HEIGHT && pCurs->bits->width <= CURSOR_WIDTH) - return TRUE; - return FALSE; -} - -static void RADEONLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) +void +radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { + ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 *d = (CARD32 *)(pointer)(info->FB + info->cursor_offset + pScrn->fbOffset); - int x, y, w, h; - CARD32 save1 = 0; - CARD32 save2 = 0; - CARD32 *image = pCurs->bits->argb; - CARD32 *i; RADEONCTRACE(("RADEONLoadCursorARGB\n")); - if (!info->IsSecondary) { - save1 = INREG(RADEON_CRTC_GEN_CNTL) & ~(CARD32) (3 << 20); - save1 |= (CARD32) (2 << 20); - OUTREG(RADEON_CRTC_GEN_CNTL, save1 & (CARD32)~RADEON_CRTC_CUR_EN); - } - - 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); - } - -#ifdef ARGB_CURSOR info->cursor_argb = TRUE; -#endif CURSOR_SWAPPING_START(); - w = pCurs->bits->width; - if (w > CURSOR_WIDTH) - w = CURSOR_WIDTH; - h = pCurs->bits->height; - if (h > CURSOR_HEIGHT) - h = CURSOR_HEIGHT; - for (y = 0; y < h; y++) - { - i = image; - image += pCurs->bits->width; - for (x = 0; x < w; x++) - *d++ = *i++; - /* pad to the right with transparent */ - for (; x < CURSOR_WIDTH; x++) - *d++ = 0; - } - /* pad below with transparent */ - for (; y < CURSOR_HEIGHT; y++) - for (x = 0; x < CURSOR_WIDTH; x++) - *d++ = 0; + memcpy (d, image, CURSOR_HEIGHT * CURSOR_WIDTH * 4); CURSOR_SWAPPING_END (); - - if (!info->IsSecondary) - OUTREG(RADEON_CRTC_GEN_CNTL, save1); - - if (info->IsSecondary || info->MergedFB) - OUTREG(RADEON_CRTC2_GEN_CNTL, save2); - } #endif @@ -378,39 +239,12 @@ Bool RADEONCursorInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); - xf86CursorInfoPtr cursor; int width; int width_bytes; int height; int size_bytes; - if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE; - cursor->MaxWidth = CURSOR_WIDTH; - cursor->MaxHeight = CURSOR_HEIGHT; - cursor->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP - | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* this is a lie -- - * HARDWARE_CURSOR_BIT_ORDER_MSBFIRST - * actually inverts the bit order, so - * this switches to LSBFIRST - */ - | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST -#endif - | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1); - - cursor->SetCursorColors = RADEONSetCursorColors; - cursor->SetCursorPosition = RADEONSetCursorPosition; - cursor->LoadCursorImage = RADEONLoadCursorImage; - cursor->HideCursor = RADEONHideCursor; - cursor->ShowCursor = RADEONShowCursor; - cursor->UseHWCursor = RADEONUseHWCursor; - -#ifdef ARGB_CURSOR - cursor->UseHWCursorARGB = RADEONUseHWCursorARGB; - cursor->LoadCursorARGB = RADEONLoadCursorARGB; -#endif size_bytes = CURSOR_WIDTH * 4 * CURSOR_HEIGHT; width = pScrn->displayWidth; width_bytes = width * (pScrn->bitsPerPixel / 8); @@ -440,5 +274,17 @@ Bool RADEONCursorInit(ScreenPtr pScreen) } #endif - return xf86InitCursor(pScreen, cursor); + return xf86_cursors_init (pScreen, CURSOR_WIDTH, CURSOR_HEIGHT, + (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* this is a lie -- + * HARDWARE_CURSOR_BIT_ORDER_MSBFIRST + * actually inverts the bit order, so + * this switches to LSBFIRST + */ + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | +#endif + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | + HARDWARE_CURSOR_ARGB)); } diff --git a/src/radeon_display.c b/src/radeon_display.c index d661c17b..fa80e104 100644 --- a/src/radeon_display.c +++ b/src/radeon_display.c @@ -36,8 +36,8 @@ /* X and server generic header files */ #include "xf86.h" #include "xf86_OSproc.h" -#include "fbdevhw.h" #include "vgaHW.h" +#include "xf86Modes.h" /* Driver data structures */ #include "radeon.h" @@ -45,97 +45,9 @@ #include "radeon_macros.h" #include "radeon_probe.h" #include "radeon_version.h" -#include "radeon_mergedfb.h" extern int getRADEONEntityIndex(void); -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" -}; - - -static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = -{ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ - {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ - {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ - {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ - {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ - {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ - {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ - {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ -}; - static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = { 0x00000000, /* unknown */ @@ -158,53 +70,6 @@ static const CARD32 default_tvdac_adj [CHIP_FAMILY_LAST] = 0x00780000, /* rs400 */ /* FIXME: just values from rv380 used... */ }; -static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - /* Get the result */ - val = INREG(info->DDCReg); - - *Clock = (val & RADEON_GPIO_Y_1) != 0; - *data = (val & RADEON_GPIO_Y_0) != 0; -} - -static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) -{ - ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long val; - unsigned char *RADEONMMIO = info->MMIO; - - val = INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); - val |= (Clock ? 0:RADEON_GPIO_EN_1); - val |= (data ? 0:RADEON_GPIO_EN_0); - OUTREG(info->DDCReg, val); - - /* read back to improve reliability on some cards. */ - val = INREG(info->DDCReg); -} - -Bool RADEONI2cInit(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - info->pI2CBus = xf86CreateI2CBusRec(); - if (!info->pI2CBus) return FALSE; - - info->pI2CBus->BusName = "DDC"; - info->pI2CBus->scrnIndex = pScrn->scrnIndex; - info->pI2CBus->I2CPutBits = RADEONI2CPutBits; - info->pI2CBus->I2CGetBits = RADEONI2CGetBits; - info->pI2CBus->AcknTimeout = 5; - - if (!xf86I2CBusInit(info->pI2CBus)) return FALSE; - return TRUE; -} - void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) { MonPtr mon = pScrn->monitor; @@ -293,1137 +158,21 @@ void RADEONSetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag) } } -static RADEONMonitorType -RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int bConnected = 0; - - /* the monitor either wasn't connected or it is a non-DDC CRT. - * try to probe it - */ - if(IsCrtDac) { - unsigned long ulOrigVCLK_ECP_CNTL; - unsigned long ulOrigDAC_CNTL; - unsigned long ulOrigDAC_MACRO_CNTL; - unsigned long ulOrigDAC_EXT_CNTL; - unsigned long ulOrigCRTC_EXT_CNTL; - unsigned long ulData; - unsigned long ulMask; - - ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - - ulData = ulOrigVCLK_ECP_CNTL; - ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb - | RADEON_PIXCLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb - |RADEON_PIXCLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); - ulData = ulOrigCRTC_EXT_CNTL; - ulData |= RADEON_CRTC_CRT_ON; - OUTREG(RADEON_CRTC_EXT_CNTL, ulData); - - ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); - ulData = ulOrigDAC_EXT_CNTL; - ulData &= ~RADEON_DAC_FORCE_DATA_MASK; - ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN - |RADEON_DAC_FORCE_DATA_EN - |RADEON_DAC_FORCE_DATA_SEL_MASK); - if ((info->ChipFamily == CHIP_FAMILY_RV250) || - (info->ChipFamily == CHIP_FAMILY_RV280)) - ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); - else - ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); - - OUTREG(RADEON_DAC_EXT_CNTL, ulData); - - /* turn on power so testing can go through */ - ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); - ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN; - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL); - - ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); - ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); - - /* Enable comparators and set DAC range to PS2 (VGA) output level */ - ulData = ulOrigDAC_CNTL; - ulData |= RADEON_DAC_CMP_EN; - ulData &= ~RADEON_DAC_RANGE_CNTL_MASK; - ulData |= 0x2; - OUTREG(RADEON_DAC_CNTL, ulData); - - /* Settle down */ - usleep(10000); - - /* Read comparators */ - ulData = INREG(RADEON_DAC_CNTL); - bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; - - /* Restore things */ - ulData = ulOrigVCLK_ECP_CNTL; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); - - OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); - OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); - OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); - - if (!bConnected) { - /* Power DAC down if CRT is not connected */ - ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); - ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | - RADEON_DAC_PDWN_B); - OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); - - ulData = INREG(RADEON_DAC_CNTL); - ulData |= RADEON_DAC_PDWN; - OUTREG(RADEON_DAC_CNTL, ulData); - } - } else { /* TV DAC */ - - /* This doesn't seem to work reliably (maybe worse on some OEM cards), - for now we always return false. If one wants to connected a - non-DDC monitor on the DVI port when CRT port is also connected, - he will need to explicitly tell the driver in the config file - with Option MonitorLayout. - */ - bConnected = FALSE; - -#if 0 - if (info->ChipFamily == CHIP_FAMILY_R200) { - unsigned long ulOrigGPIO_MONID; - unsigned long ulOrigFP2_GEN_CNTL; - unsigned long ulOrigDISP_OUTPUT_CNTL; - unsigned long ulOrigCRTC2_GEN_CNTL; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; - unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; - unsigned long ulOrigCRTC2_H_TOTAL_DISP; - unsigned long ulOrigCRTC2_V_TOTAL_DISP; - unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; - unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; - unsigned long ulData, i; - - ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); - ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); - ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); - ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); - ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); - ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); - ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); - ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); - ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); - ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); - - ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); - ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); - ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); - ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); - - ulData = INREG(RADEON_GPIO_MONID); - ulData &= ~RADEON_GPIO_A_0; - OUTREG(RADEON_GPIO_MONID, ulData); - - OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); - - OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); - - OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); - - for (i = 0; i < 200; i++) { - ulData = INREG(RADEON_GPIO_MONID); - bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; - if (!bConnected) break; - - usleep(1000); - } - - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); - OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); - OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); - OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); - OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); - OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); - OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); - OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); - OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); - } else { - unsigned long ulOrigPIXCLKSDATA; - unsigned long ulOrigTV_MASTER_CNTL; - unsigned long ulOrigTV_DAC_CNTL; - unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; - unsigned long ulOrigDAC_CNTL2; - unsigned long ulData; - unsigned long ulMask; - - ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - - ulData = ulOrigPIXCLKSDATA; - ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb - | RADEON_PIX2CLK_DAC_ALWAYS_ONb); - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); - ulData = ulOrigTV_MASTER_CNTL; - ulData &= ~RADEON_TVCLK_ALWAYS_ONb; - OUTREG(RADEON_TV_MASTER_CNTL, ulData); - - ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); - ulData = ulOrigDAC_CNTL2; - ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; - OUTREG(RADEON_DAC_CNTL2, ulData); - - ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); - - ulData = 0x00880213; - OUTREG(RADEON_TV_DAC_CNTL, ulData); - - ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); - - ulData = (RADEON_Y_RED_EN - | RADEON_C_GRN_EN - | RADEON_CMP_BLU_EN - | RADEON_RED_MX_FORCE_DAC_DATA - | RADEON_GRN_MX_FORCE_DAC_DATA - | RADEON_BLU_MX_FORCE_DAC_DATA); - 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(10000); - - ulData = INREG(RADEON_TV_DAC_CNTL); - bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; - - ulData = ulOrigPIXCLKSDATA; - ulMask = 0xFFFFFFFFL; - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); - - OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); - OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); - OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); - OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); - } -#endif - } - - return(bConnected ? MT_CRT : MT_NONE); -} - - -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; - switch(DDCType) - { - case DDC_MONID: - info->DDCReg = RADEON_GPIO_MONID; - break; - case DDC_DVI: - info->DDCReg = RADEON_GPIO_DVI_DDC; - break; - case DDC_VGA: - info->DDCReg = RADEON_GPIO_VGA_DDC; - break; - case DDC_CRT2: - info->DDCReg = RADEON_GPIO_CRT2_DDC; - break; - default: - info->DDCReg = DDCReg; - return MT_NONE; - } - - /* Read and output monitor info using DDC2 over I2C bus */ - if (info->pI2CBus && info->ddc2) { - OUTREG(info->DDCReg, INREG(info->DDCReg) & - (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); - - /* For some old monitors (like Compaq Presario FP500), we need - * following process to initialize/stop DDC - */ - OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (j = 0; j < 3; j++) { - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(13000); - - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 10; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - if (i == 10) continue; - - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); - for (i = 0; i < 5; i++) { - usleep(15000); - if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) - break; - } - usleep(15000); - OUTREG(info->DDCReg, - INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); - usleep(15000); - - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); - OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); - usleep(15000); - if(*MonInfo) break; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); - MonType = MT_NONE; - } - - OUTREG(info->DDCReg, INREG(info->DDCReg) & - ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); - - if (*MonInfo) { - if ((*MonInfo)->rawData[0x14] & 0x80) { - /* 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) & RADEON_FP_EN_TMDS) || !info->IsMobility) - MonType = MT_DFP; - else - MonType = MT_LCD; - } - } else MonType = MT_CRT; - } else MonType = MT_NONE; - - info->DDCReg = DDCReg; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "DDC Type: %d, Detected Type: %d\n", DDCType, MonType); - - return MonType; -} - -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_horz_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; - } - - if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { - CARD32 ppll_div_sel, ppll_val; - - ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; - RADEONPllErrataAfterIndex(info); - ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); - if ((ppll_val & 0x000707ff) == 0x1bb) - goto noprobe; - info->FeedbackDivider = ppll_val & 0x7ff; - info->PostDivider = (ppll_val >> 16) & 0x7; - info->RefDivider = info->pll.reference_div; - info->UseBiosDividers = TRUE; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Existing panel PLL dividers will be used.\n"); - } - noprobe: - - 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); -} - - -/* BIOS may not have right panel size, we search through all supported - * DDC modes looking for the maximum panel size. - */ -static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn) -{ - int j; - RADEONInfoPtr info = RADEONPTR (pScrn); - xf86MonPtr ddc = pScrn->monitor->DDC; - DisplayModePtr p; - - if ((info->UseBiosDividers && info->DotClock != 0) || (ddc == NULL)) - return; - - /* Go thru detailed timing table first */ - for (j = 0; j < 4; j++) { - if (ddc->det_mon[j].type == 0) { - struct detailed_timings *d_timings = - &ddc->det_mon[j].section.d_timings; - int match = 0; - - /* If we didn't get a panel clock or guessed one, try to match the - * mode with the panel size. We do that because we _need_ a panel - * clock, or ValidateFPModes will fail, even when UseBiosDividers - * is set. - */ - if (info->DotClock == 0 && - info->PanelXRes == d_timings->h_active && - info->PanelYRes == d_timings->v_active) - match = 1; - - /* If we don't have a BIOS provided panel data with fixed dividers, - * check for a larger panel size - */ - if (info->PanelXRes < d_timings->h_active && - info->PanelYRes < d_timings->v_active && - !info->UseBiosDividers) - match = 1; - - if (match) { - info->PanelXRes = d_timings->h_active; - info->PanelYRes = d_timings->v_active; - info->DotClock = d_timings->clock / 1000; - info->HOverPlus = d_timings->h_sync_off; - info->HSyncWidth = d_timings->h_sync_width; - info->HBlank = d_timings->h_blanking; - info->VOverPlus = d_timings->v_sync_off; - info->VSyncWidth = d_timings->v_sync_width; - info->VBlank = d_timings->v_blanking; - info->Flags = (d_timings->interlaced ? V_INTERLACE : 0); - if (d_timings->sync == 3) { - switch (d_timings->misc) { - case 0: info->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: info->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: info->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: info->Flags |= V_PHSYNC | V_PVSYNC; break; - } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - - if (info->UseBiosDividers && info->DotClock != 0) - return; - - /* Search thru standard VESA modes from EDID */ - for (j = 0; j < 8; j++) { - if ((info->PanelXRes < ddc->timings2[j].hsize) && - (info->PanelYRes < ddc->timings2[j].vsize)) { - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((ddc->timings2[j].hsize == p->HDisplay) && - (ddc->timings2[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - info->PanelXRes = ddc->timings2[j].hsize; - info->PanelYRes = ddc->timings2[j].vsize; - info->HBlank = p->HTotal - p->HDisplay; - info->HOverPlus = p->HSyncStart - p->HDisplay; - info->HSyncWidth = p->HSyncEnd - p->HSyncStart; - info->VBlank = p->VTotal - p->VDisplay; - info->VOverPlus = p->VSyncStart - p->VDisplay; - info->VSyncWidth = p->VSyncEnd - p->VSyncStart; - info->DotClock = p->Clock; - info->Flags = p->Flags; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", - info->PanelXRes, info->PanelYRes); - } - } - } - } - } -} - -static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (!RADEONGetLVDSInfoFromBIOS(pScrn)) - RADEONGetPanelInfoFromReg(pScrn); - - /* 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 - * found from EDID data. - */ - RADEONUpdatePanelSize(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); - int i; - - for (i=0; i<4; i++) { - info->tmds_pll[i].value = 0; - info->tmds_pll[i].freq = 0; - } - - 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; - } -} - -void RADEONGetPanelInfo (ScrnInfoPtr pScrn) -{ - 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); - if (info->MergeType == MT_DFP) { - RADEONGetTMDSInfo(pScrn); - } - } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { - RADEONGetTMDSInfo(pScrn); - if (!pScrn->monitor->DDC) - RADEONGetHardCodedEDIDFromBIOS(pScrn); - else if (!info->IsSecondary) - RADEONUpdatePanelSize(pScrn); - } - } -} - -void RADEONGetTVDacAdjInfo(ScrnInfoPtr pScrn) +void RADEONGetTVDacAdjInfo(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; /* Todo: get this setting from BIOS */ - info->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; + radeon_output->tv_dac_adj = default_tvdac_adj[info->ChipFamily]; if (info->IsMobility) { /* some mobility chips may different */ if (info->ChipFamily == CHIP_FAMILY_RV250) - info->tv_dac_adj = 0x00880000; + radeon_output->tv_dac_adj = 0x00880000; } } /* - * initialise the static data sos we don't have to re-do at randr change */ -void RADEONSetupConnectors(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - const char *s; - Bool ignore_edid = FALSE; - int i = 0, second = 0, max_mt = 5; - - /* 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; - } - pRADEONEnt->Controller[0]->IsUsed = FALSE; - pRADEONEnt->Controller[1]->IsUsed = FALSE; - pRADEONEnt->Controller[0]->IsActive = FALSE; - pRADEONEnt->Controller[1]->IsActive = FALSE; - - if (!RADEONGetConnectorInfoFromBIOS(pScrn) || - ((pRADEONEnt->PortInfo[0]->DDCType == 0) && - (pRADEONEnt->PortInfo[1]->DDCType == 0))) { - /* 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_I; - - 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; - - - /* Some cards have the DDC lines swapped and we have no way to - * detect it yet (Mac cards) - */ - if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { - pRADEONEnt->PortInfo[0]->DDCType = DDC_VGA; - pRADEONEnt->PortInfo[1]->DDCType = DDC_DVI; - } - } - - /* 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 */ - /* On my Inspiron 8600 both internal and external ports are - marked DAC_PRIMARY in BIOS. So be extra careful - only - swap when the first port is not DAC_PRIMARY */ - if ((!(pRADEONEnt->PortInfo[0]->ConnectorType == CONNECTOR_PROPRIETARY)) && (pRADEONEnt->PortInfo[1]->DACType == DAC_PRIMARY) && - (pRADEONEnt->PortInfo[0]->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 (!pRADEONEnt->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. - * For example, you can config your laptop with - * Option "MonitorLayout" "LVDS, CRT" - * Option "CloneHSync" "40-150" - * Option "CloneVRefresh" "60-120" - * With these options, you can connect in your CRT monitor later - * after the X server has started. - */ - 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 1st port \n"); - - for (i = 0; i < max_mt; i++) - { - if (strcmp(s2, MonTypeName[i]) == 0) - { - pRADEONEnt->PortInfo[1]->MonType = MonTypeID[i]; - break; - } - - } - if (i == max_mt) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Invalid Monitor type specified for 2nd port \n"); - - 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 0 - 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; - } -#endif - - /* some thinkpads and powerbooks use lvds and internal tmds - * at the same time. --AGD - */ - if ((pRADEONEnt->PortInfo[0]->MonType == MT_LCD) && - (pRADEONEnt->PortInfo[1]->MonType == MT_DFP)) { - pRADEONEnt->PortInfo[1]->DDCType = DDC_DVI; - pRADEONEnt->PortInfo[0]->DDCType = DDC_MONID; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_INT; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_DVI_I; - pRADEONEnt->PortInfo[0]->TMDSType = TMDS_UNKNOWN; - } - - } -} - -static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, int connector) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - if (info->IsMobility) { - switch(connector) { - case 0: - /* non-DDC laptop panel connected on primary */ - if (INREG(RADEON_BIOS_4_SCRATCH) & 4) - return MT_LCD; - break; - case 1: - /* non-DDC TMDS panel connected through DVO */ - if (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_ON) - return MT_DFP; - break; - default: - break; - } - } - return MT_NONE; -} - -/* Primary Head (DVI or Laptop Int. panel)*/ -/* A ddc capable display connected on DVI port */ -/* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ -void RADEONConnectorFindMonitor(ScrnInfoPtr pScrn, int connector) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONConnector *pPort = pRADEONEnt->PortInfo[connector]; - - if (pPort->MonType == MT_UNKNOWN) { - if ((pPort->MonType = RADEONDisplayDDCConnected(pScrn, - pPort->DDCType, - pPort))); - else if((pPort->MonType = RADEONPortCheckNonDDC(pScrn, connector))); - else - pPort->MonType = RADEONCrtIsPhysicallyConnected(pScrn, !(pPort->DACType)); - } -} - -static void RADEONQueryConnectedDisplays(ScrnInfoPtr pScrn) -{ - - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - const char *s; - Bool ignore_edid = FALSE; - - /* 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"); - } - - if ((s = xf86GetOptValString(info->Options, OPTION_MONITOR_LAYOUT))) { - 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]); - } - } - else { - /* force monitor redetection */ - pRADEONEnt->PortInfo[0]->MonType = MT_UNKNOWN; - pRADEONEnt->PortInfo[1]->MonType = MT_UNKNOWN; - } - - - if (pRADEONEnt->PortInfo[0]->MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1]->MonType == MT_UNKNOWN) { - - if ((!pRADEONEnt->HasCRTC2) && (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->PortInfo[1]->MonType = MT_NONE; - pRADEONEnt->PortInfo[1]->MonInfo = NULL; - pRADEONEnt->PortInfo[1]->DDCType = DDC_NONE_DETECTED; - pRADEONEnt->PortInfo[1]->DACType = DAC_UNKNOWN; - pRADEONEnt->PortInfo[1]->TMDSType = TMDS_UNKNOWN; - pRADEONEnt->PortInfo[1]->ConnectorType = CONNECTOR_NONE; - - pRADEONEnt->PortInfo[0]->crtc_num = 1; - pRADEONEnt->PortInfo[1]->crtc_num = 2; - - return; - } - - RADEONConnectorFindMonitor(pScrn, 0); - RADEONConnectorFindMonitor(pScrn, 1); - - } - - 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 1st port ----------------------\n"); - xf86PrintEDID( pRADEONEnt->PortInfo[0]->MonInfo ); - } - - if (pRADEONEnt->PortInfo[1]->MonInfo) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on 2nd port -----------------------\n"); - xf86PrintEDID( pRADEONEnt->PortInfo[1]->MonInfo ); - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\n"); - - return; -} - -Bool RADEONMapControllers(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - Bool head_reversed = FALSE; - RADEONConnector *connector; - - info->MergeType = MT_NONE; - - if (!info->IsSecondary) { - RADEONQueryConnectedDisplays(pScrn); - - pRADEONEnt->PortInfo[0]->crtc_num = 1; - pRADEONEnt->PortInfo[1]->crtc_num = 2; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Port1:\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, - "Port2:\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]); - - /* no display detected on primary port*/ - if (pRADEONEnt->PortInfo[0]->MonType == MT_NONE) { - if (pRADEONEnt->PortInfo[1]->MonType != MT_NONE) { - /* Only one detected on secondary, let it to be primary */ - pRADEONEnt->PortInfo[0]->crtc_num = 2; - pRADEONEnt->PortInfo[1]->crtc_num = 1; - head_reversed = TRUE; - } else { - /* None detected, Default to a CRT connected */ - pRADEONEnt->PortInfo[0]->MonType = MT_CRT; - } - } - - if ((pRADEONEnt->PortInfo[0]->MonType == MT_LCD) && - (pRADEONEnt->PortInfo[1]->MonType == MT_CRT)) { - if (!(INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON)) { - /* LCD is switched off, don't turn it on, otherwise it may casue lockup due to SS issue. */ - pRADEONEnt->PortInfo[0]->crtc_num = 2; - pRADEONEnt->PortInfo[1]->crtc_num = 1; - pRADEONEnt->PortInfo[0]->MonType = MT_NONE; - head_reversed = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "LCD is switched off, only CRT will be used\n"); - } - } - - if ((pRADEONEnt->PortInfo[0]->MonType != MT_NONE) && - (pRADEONEnt->PortInfo[1]->MonType != MT_NONE)) { - if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DISPLAY, FALSE)) { - if (info->IsMobility) { - /* Don't reverse display for mobility chips, as only CRTC1 path has RMX which - will be required by many LCD panels - */ - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Reverse Display cannot be used for mobility chip\n"); - } else { - pRADEONEnt->PortInfo[0]->crtc_num = 2; - pRADEONEnt->PortInfo[1]->crtc_num = 1; - head_reversed = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Primary and Secondary mapping is reversed\n"); - } - } - } - - if (pRADEONEnt->HasSecondary && pRADEONEnt->PortInfo[1]->MonType == MT_NONE) { - pRADEONEnt->HasSecondary = FALSE; - } - } - - if(pRADEONEnt->HasCRTC2) { - if(info->IsSecondary) { - connector = RADEONGetCrtcConnector(pScrn, 2); - pRADEONEnt->Controller[1]->binding = 2; - if (connector) { - info->DisplayType = connector->MonType; - pScrn->monitor->DDC = connector->MonInfo; - } - } else { - connector = RADEONGetCrtcConnector(pScrn, 1); - pRADEONEnt->Controller[0]->binding = 1; - if (connector) { - info->DisplayType = connector->MonType; - pScrn->monitor->DDC = connector->MonInfo; - } - } - - if(!pRADEONEnt->HasSecondary) { - connector = RADEONGetCrtcConnector(pScrn, 2); - if (connector) - info->MergeType = connector->MonType; - if (info->MergeType) - pRADEONEnt->Controller[1]->binding = 1; - } - } else { - connector = RADEONGetCrtcConnector(pScrn, 1); - if (connector) { - if (connector->MonType == MT_NONE) - connector->MonType = MT_CRT; - info->DisplayType = connector->MonType; - pScrn->monitor->DDC = connector->MonInfo; - } - connector = RADEONGetCrtcConnector(pScrn, 2); - if (connector) - connector->MonType = MT_NONE; - pRADEONEnt->Controller[1]->binding = 1; - } - - if (!info->IsSecondary) { - connector = RADEONGetCrtcConnector(pScrn, 2); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Primary Head: Port%d ---- \n", head_reversed?2:1); - if (connector->MonType != MT_NONE) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Port%d ----\n", head_reversed?1:2); - else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "---- Secondary Head: Not used ----\n"); - } - - info->HBlank = 0; - info->HOverPlus = 0; - info->HSyncWidth = 0; - info->VBlank = 0; - info->VOverPlus = 0; - info->VSyncWidth = 0; - info->DotClock = 0; - info->UseBiosDividers = FALSE; - - info->OverlayOnCRTC2 = FALSE; - - return TRUE; -} - -/* * Powering done DAC, needed for DPMS problem with ViewSonic P817 (or its variant). * */ @@ -1436,8 +185,7 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) CARD32 dac_cntl; CARD32 dac_macro_cntl = 0; dac_cntl = INREG(RADEON_DAC_CNTL); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); if (IsOn) { dac_cntl &= ~RADEON_DAC_PDWN; dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | @@ -1450,8 +198,7 @@ static void RADEONDacPowerSet(ScrnInfoPtr pScrn, Bool IsOn, Bool IsPrimaryDAC) RADEON_DAC_PDWN_B); } OUTREG(RADEON_DAC_CNTL, dac_cntl); - if ((!info->IsMobility) || (info->ChipFamily == CHIP_FAMILY_RV350)) - OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); } else { CARD32 tv_dac_cntl; CARD32 fp2_gen_cntl; @@ -1528,6 +275,13 @@ void RADEONDisableDisplays(ScrnInfoPtr pScrn) { } RADEONDacPowerSet(pScrn, FALSE, FALSE); + /* turn off tv-out */ + if (info->InternalTVOut) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp &= ~RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + } + /* FP 1 */ tmp = INREG(RADEON_FP_GEN_CNTL); tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); @@ -1539,39 +293,47 @@ void RADEONDisableDisplays(ScrnInfoPtr pScrn) { OUTREG(RADEON_FP2_GEN_CNTL, tmp); /* LVDS */ - tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - tmp = INREG(RADEON_LVDS_GEN_CNTL); - tmp |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); - tmp &= ~(RADEON_LVDS_BLON); - OUTREG(RADEON_LVDS_GEN_CNTL, tmp); - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + if (info->IsMobility) { + tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + if (info->IsMobility || info->IsIGP) { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); + } + tmp = INREG(RADEON_LVDS_GEN_CNTL); + tmp |= RADEON_LVDS_DISPLAY_DIS; + tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); + OUTREG(RADEON_LVDS_GEN_CNTL, tmp); + if (info->IsMobility || info->IsIGP) { + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); + } } } /* This is to be used enable/disable displays dynamically */ -void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable) +void RADEONEnableDisplay(xf86OutputPtr output, BOOL bEnable) { + ScrnInfoPtr pScrn = output->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); RADEONSavePtr save = &info->ModeReg; unsigned char * RADEONMMIO = info->MMIO; unsigned long tmp; + RADEONOutputPrivatePtr radeon_output; + int tv_dac_change = 0; + radeon_output = output->driver_private; if (bEnable) { - if (pPort->MonType == MT_CRT) { - if (pPort->DACType == DAC_PRIMARY) { + ErrorF("enable montype: %d\n", radeon_output->MonType); + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { tmp = INREG(RADEON_CRTC_EXT_CNTL); tmp |= RADEON_CRTC_CRT_ON; OUTREG(RADEON_CRTC_EXT_CNTL, tmp); save->crtc_ext_cntl |= RADEON_CRTC_CRT_ON; - } else if (pPort->DACType == DAC_TVDAC) { + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } else if (radeon_output->DACType == DAC_TVDAC) { if (info->ChipFamily == CHIP_FAMILY_R200) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); @@ -1579,41 +341,50 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); } else { tmp = INREG(RADEON_CRTC2_GEN_CNTL); - tmp |= RADEON_CRTC2_CRT2_ON; + tmp |= RADEON_CRTC2_CRT2_ON; OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); save->crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; } + tv_dac_change = 1; } - RADEONDacPowerSet(pScrn, bEnable, (pPort->DACType == DAC_PRIMARY)); - } else if (pPort->MonType == MT_DFP) { - if (pPort->TMDSType == TMDS_INT) { + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { tmp = INREG(RADEON_FP_GEN_CNTL); tmp |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); OUTREG(RADEON_FP_GEN_CNTL, tmp); save->fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else if (pPort->TMDSType == TMDS_EXT) { + } else if (radeon_output->TMDSType == TMDS_EXT) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); OUTREG(RADEON_FP2_GEN_CNTL, tmp); save->fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); } - } else if (pPort->MonType == MT_LCD) { + } else if (radeon_output->MonType == MT_LCD) { tmp = INREG(RADEON_LVDS_GEN_CNTL); tmp |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); tmp &= ~(RADEON_LVDS_DISPLAY_DIS); - usleep (info->PanelPwrDly * 1000); + usleep (radeon_output->PanelPwrDly * 1000); OUTREG(RADEON_LVDS_GEN_CNTL, tmp); save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_BLON); save->lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); - } + } else if (radeon_output->MonType == MT_STV || + radeon_output->MonType == MT_CTV) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp |= RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + tv_dac_change = 2; + radeon_output->tv_on = TRUE; + } } else { - if (pPort->MonType == MT_CRT || pPort->MonType == NONE) { - if (pPort->DACType == DAC_PRIMARY) { + ErrorF("disable montype: %d\n", radeon_output->MonType); + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { tmp = INREG(RADEON_CRTC_EXT_CNTL); - tmp &= ~RADEON_CRTC_CRT_ON; + tmp &= ~RADEON_CRTC_CRT_ON; OUTREG(RADEON_CRTC_EXT_CNTL, tmp); save->crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; - } else if (pPort->DACType == DAC_TVDAC) { + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } else if (radeon_output->DACType == DAC_TVDAC) { if (info->ChipFamily == CHIP_FAMILY_R200) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); @@ -1625,26 +396,21 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); save->crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; } + tv_dac_change = 1; } - RADEONDacPowerSet(pScrn, bEnable, (pPort->DACType == DAC_PRIMARY)); - } - - if (pPort->MonType == MT_DFP || pPort->MonType == NONE) { - if (pPort->TMDSType == TMDS_INT) { + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { tmp = INREG(RADEON_FP_GEN_CNTL); tmp &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); OUTREG(RADEON_FP_GEN_CNTL, tmp); save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); - } else if (pPort->TMDSType == TMDS_EXT) { + } else if (radeon_output->TMDSType == TMDS_EXT) { tmp = INREG(RADEON_FP2_GEN_CNTL); tmp &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); OUTREG(RADEON_FP2_GEN_CNTL, tmp); save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); } - } - - if (pPort->MonType == MT_LCD || - (pPort->MonType == NONE && pPort->ConnectorType == CONNECTOR_PROPRIETARY)) { + } else if (radeon_output->MonType == MT_LCD) { unsigned long tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); if (info->IsMobility || info->IsIGP) { /* Asic bug, when turning off LVDS_ON, we have to make sure @@ -1653,21 +419,39 @@ void RADEONEnableDisplay(ScrnInfoPtr pScrn, RADEONConnector* pPort, BOOL bEnable OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); } tmp = INREG(RADEON_LVDS_GEN_CNTL); - tmp |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); - tmp &= ~(RADEON_LVDS_BLON); + tmp |= RADEON_LVDS_DISPLAY_DIS; + tmp &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); OUTREG(RADEON_LVDS_GEN_CNTL, tmp); - save->lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_DISPLAY_DIS); - save->lvds_gen_cntl &= ~(RADEON_LVDS_BLON); + save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); if (info->IsMobility || info->IsIGP) { OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); } - } + } else if (radeon_output->MonType == MT_STV || radeon_output->MonType == MT_CTV) { + tmp = INREG(RADEON_TV_MASTER_CNTL); + tmp &= ~RADEON_TV_ON; + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + tv_dac_change = 2; + radeon_output->tv_on = FALSE; + } + } + + if (tv_dac_change) { + if (bEnable) + info->tv_dac_enable_mask |= tv_dac_change; + else + info->tv_dac_enable_mask &= ~tv_dac_change; + + if (bEnable && info->tv_dac_enable_mask) + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + else if (!bEnable && info->tv_dac_enable_mask == 0) + RADEONDacPowerSet(pScrn, bEnable, (radeon_output->DACType == DAC_PRIMARY)); + } } /* Calculate display buffer watermark to prevent buffer underflow */ -void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoPtr info2, - DisplayModePtr mode1, DisplayModePtr mode2) +void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, int pixel_bytes2, DisplayModePtr mode1, DisplayModePtr mode2) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; @@ -1705,7 +489,7 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP */ if ((info->DispPriority == 2) && IS_R300_VARIANT) { CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); - if (pRADEONEnt->Controller[1]->IsActive) { + if (pRADEONEnt->pCrtc[1]->enabled) { mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ } else { mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ @@ -1717,11 +501,6 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP /* R420 and RV410 family not supported yet */ if (info->ChipFamily == CHIP_FAMILY_R420 || info->ChipFamily == CHIP_FAMILY_RV410) return; - if (pRADEONEnt->pSecondaryScrn) { - if (info->IsSecondary) return; - info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (pRADEONEnt->Controller[1]->binding == 1) info2 = info; - /* * Determine if there is enough bandwidth for current display mode */ @@ -1734,8 +513,8 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP pix_clk2 = 0; peak_disp_bw = (pix_clk * info->CurrentLayout.pixel_bytes); - if (info2) - peak_disp_bw += (pix_clk2 * info2->CurrentLayout.pixel_bytes); + if (pixel_bytes2) + peak_disp_bw += (pix_clk2 * pixel_bytes2); if (peak_disp_bw >= mem_bw * min_mem_eff) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -1875,8 +654,8 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP Find the drain rate of the display buffer. */ disp_drain_rate = pix_clk / (16.0/info->CurrentLayout.pixel_bytes); - if (info2) - disp_drain_rate2 = pix_clk2 / (16.0/info2->CurrentLayout.pixel_bytes); + if (pixel_bytes2) + disp_drain_rate2 = pix_clk2 / (16.0/pixel_bytes2); else disp_drain_rate2 = 0; @@ -1925,11 +704,13 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP OUTREG(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - RADEONTRACE(("GRPH_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg.grph_buffer_cntl, INREG(RADEON_GRPH_BUFFER_CNTL))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "GRPH_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg.grph_buffer_cntl, + INREG(RADEON_GRPH_BUFFER_CNTL)); if (mode2) { - stop_req = mode2->HDisplay * info2->CurrentLayout.pixel_bytes / 16; + stop_req = mode2->HDisplay * pixel_bytes2 / 16; if (stop_req > max_stop_req) stop_req = max_stop_req; @@ -1973,427 +754,81 @@ void RADEONInitDispBandwidth2(ScrnInfoPtr pScrn, RADEONInfoPtr info, RADEONInfoP OUTREG(RADEON_GRPH2_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); - RADEONTRACE(("GRPH2_BUFFER_CNTL from %x to %x\n", - (unsigned int)info->SavedReg.grph2_buffer_cntl, INREG(RADEON_GRPH2_BUFFER_CNTL))); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "GRPH2_BUFFER_CNTL from %x to %x\n", + (unsigned int)info->SavedReg.grph2_buffer_cntl, + INREG(RADEON_GRPH2_BUFFER_CNTL)); } } void RADEONInitDispBandwidth(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); DisplayModePtr mode1, mode2; - RADEONInfoPtr info2 = NULL; - - if (pRADEONEnt->pSecondaryScrn) { - if (info->IsSecondary) return; - info2 = RADEONPTR(pRADEONEnt->pSecondaryScrn); - } else if (pRADEONEnt->Controller[1]->binding == 1) info2 = info; + int pixel_bytes2 = 0; mode1 = info->CurrentLayout.mode; - if (info->MergedFB) { - mode1 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT1; - mode2 = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2; - } else if ((pRADEONEnt->HasSecondary) && info2) { - mode2 = info2->CurrentLayout.mode; - } else { - mode2 = NULL; - } + mode2 = NULL; + pixel_bytes2 = info->CurrentLayout.pixel_bytes; - RADEONInitDispBandwidth2(pScrn, info, info2, mode1, mode2); -} + if (xf86_config->num_crtc == 2) { + pixel_bytes2 = 0; + mode2 = NULL; -static void RADEONBlankSet(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - switch(pPort->MonType) { - case MT_LCD: - OUTREGP(RADEON_LVDS_GEN_CNTL, RADEON_LVDS_DISPLAY_DIS, ~RADEON_LVDS_DISPLAY_DIS); - break; + if (xf86_config->crtc[1]->enabled && xf86_config->crtc[0]->enabled) { + pixel_bytes2 = info->CurrentLayout.pixel_bytes; + mode1 = &xf86_config->crtc[0]->mode; + mode2 = &xf86_config->crtc[1]->mode; + } else if (xf86_config->crtc[0]->enabled) { + mode1 = &xf86_config->crtc[0]->mode; + } else if (xf86_config->crtc[1]->enabled) { + mode1 = &xf86_config->crtc[1]->mode; + } else + return; + } - case MT_CRT: - if ((info->ChipFamily == CHIP_FAMILY_R200) && - (pPort->DACType == DAC_TVDAC)) - OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - - break; - case MT_DFP: - if (pPort->TMDSType == TMDS_EXT) - OUTREGP(RADEON_FP2_GEN_CNTL, RADEON_FP2_BLANK_EN, ~RADEON_FP2_BLANK_EN); - else - OUTREGP(RADEON_FP_GEN_CNTL, RADEON_FP_BLANK_EN, ~RADEON_FP_BLANK_EN); - - break; - case MT_NONE: - default: - break; - } + RADEONInitDispBandwidth2(pScrn, info, pixel_bytes2, mode1, mode2); } -/* Blank screen */ void RADEONBlank(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONConnector *pPort; - - if (!pRADEONEnt->HasSecondary || - (pRADEONEnt->HasSecondary && !info->IsSwitching) || - (info->IsSwitching && (!info->IsSecondary))) { - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) - RADEONBlankSet(pScrn, pPort); - OUTREGP (RADEON_CRTC_EXT_CNTL, - RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS, - ~(RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS)); - - if (!pRADEONEnt->HasCRTC2) return; - - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONBlankSet(pScrn, pPort); - OUTREGP (RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } - } + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; - if ((pRADEONEnt->HasSecondary && !info->IsSwitching) || - (info->IsSwitching && info->IsSecondary)) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONBlankSet(pScrn, pPort); - OUTREGP (RADEON_CRTC2_GEN_CNTL, - RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } -} - -static void RADEONUnblankSet(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR (pScrn); - unsigned char *RADEONMMIO = info->MMIO; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; - switch(pPort->MonType) { - case MT_LCD: - OUTREGP(RADEON_LVDS_GEN_CNTL, 0, ~RADEON_LVDS_DISPLAY_DIS); - break; - case MT_CRT: - if ((info->ChipFamily == CHIP_FAMILY_R200) && - (pPort->DACType == DAC_TVDAC)) - OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - break; - case MT_DFP: - if (pPort->TMDSType == TMDS_EXT) - OUTREGP(RADEON_FP2_GEN_CNTL, 0, ~RADEON_FP2_BLANK_EN); - else - OUTREGP(RADEON_FP_GEN_CNTL, 0, ~RADEON_FP_BLANK_EN); - break; - case MT_NONE: - default: - break; + output->funcs->dpms(output, DPMSModeOff); + } + crtc->funcs->dpms(crtc, DPMSModeOff); } } -/* Unblank screen */ void RADEONUnblank(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONConnector *pPort; - - if (!pRADEONEnt->HasSecondary || (info->IsSwitching && !info->IsSecondary)) { - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) - RADEONUnblankSet(pScrn, pPort); - OUTREGP(RADEON_CRTC_EXT_CNTL, - 0, - ~(RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS)); - - if (!pRADEONEnt->HasCRTC2) return; - - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONUnblankSet(pScrn, pPort); - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } - } - - if (info->IsSwitching && info->IsSecondary) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) - RADEONUnblankSet(pScrn, pPort); - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, - ~(RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS)); - } -} - -static void RADEONDPMSSetOn(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONMonitorType MonType; - RADEONTmdsType TmdsType; - RADEONDacType DacType; - - MonType = pPort->MonType; - TmdsType = pPort->TMDSType; - DacType = pPort->DACType; - - switch(MonType) { - case MT_LCD: - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_BLON, ~RADEON_LVDS_BLON); - usleep (info->PanelPwrDly * 1000); - OUTREGP (RADEON_LVDS_GEN_CNTL, RADEON_LVDS_ON, ~RADEON_LVDS_ON); - break; - case MT_DFP: - if (TmdsType == TMDS_EXT) { - 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); - } - } else - OUTREGP (RADEON_FP_GEN_CNTL, (RADEON_FP_FPON | RADEON_FP_TMDS_EN), - ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - break; - case MT_CRT: - default: - RADEONDacPowerSet(pScrn, TRUE, (DacType == DAC_PRIMARY)); - break; - } -} - -static void RADEONDPMSSetOff(ScrnInfoPtr pScrn, RADEONConnector *pPort) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONMonitorType MonType; - RADEONTmdsType TmdsType; - RADEONDacType DacType; - unsigned long tmpPixclksCntl; - - MonType = pPort->MonType; - TmdsType = pPort->TMDSType; - DacType = pPort->DACType; - - switch(MonType) { - case MT_LCD: - tmpPixclksCntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - if (info->IsMobility || info->IsIGP) { - /* Asic bug, when turning off LVDS_ON, we have to make sure - RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off - */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); - } - OUTREGP (RADEON_LVDS_GEN_CNTL, 0, - ~(RADEON_LVDS_BLON | RADEON_LVDS_ON)); - if (info->IsMobility || info->IsIGP) { - OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl); - } - break; - case MT_DFP: - if (TmdsType == TMDS_EXT) { - 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); - } - } else - OUTREGP (RADEON_FP_GEN_CNTL, 0, ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN)); - break; - case MT_CRT: - default: - RADEONDacPowerSet(pScrn, FALSE, (DacType == DAC_PRIMARY)); - break; - } -} - - -/* Sets VESA Display Power Management Signaling (DPMS) Mode */ -void RADEONDisplayPowerManagementSet(ScrnInfoPtr pScrn, - int PowerManagementMode, - int flags) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - RADEONConnector *pPort; - if (!pScrn->vtSema) return; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + int o, c; - RADEONTRACE(("RADEONDisplayPowerManagementSet(%d,0x%x)\n", PowerManagementMode, flags)); + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + if(!crtc->enabled) + continue; + crtc->funcs->dpms(crtc, DPMSModeOn); + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + if (output->crtc != crtc) + continue; -#ifdef XF86DRI - if (info->CPStarted) DRILock(pScrn->pScreen, 0); -#endif - - if (info->accelOn) - RADEON_SYNC(info, pScrn); - - if (info->FBDev) { - fbdevHWDPMSSet(pScrn, PowerManagementMode, flags); - } else { - int mask1 = (RADEON_CRTC_DISPLAY_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_VSYNC_DIS); - int mask2 = (RADEON_CRTC2_DISP_DIS | - RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS); - - switch (PowerManagementMode) { - case DPMSModeOn: - /* Screen: On; HSync: On, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, 0, ~mask1); - } - break; - - case DPMSModeStandby: - /* Screen: Off; HSync: Off, VSync: On */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_HSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_HSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeSuspend: - /* Screen: Off; HSync: On, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, - (RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_VSYNC_DIS), - ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, - (RADEON_CRTC_DISPLAY_DIS | RADEON_CRTC_VSYNC_DIS), - ~mask1); - } - break; - - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - if (info->IsSecondary) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - else { - if (pRADEONEnt->Controller[1]->binding == 1) - OUTREGP(RADEON_CRTC2_GEN_CNTL, mask2, ~mask2); - OUTREGP(RADEON_CRTC_EXT_CNTL, mask1, ~mask1); - } - break; + output->funcs->dpms(output, DPMSModeOn); } - - if (PowerManagementMode == DPMSModeOn) { - pPort = RADEONGetCrtcConnector(pScrn, info->IsSecondary ? 2 : 1); - RADEONDPMSSetOn(pScrn, pPort); - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - RADEONDPMSSetOn(pScrn, pPort); - } - } else if ((PowerManagementMode == DPMSModeOff) || - (PowerManagementMode == DPMSModeSuspend) || - (PowerManagementMode == DPMSModeStandby)) { - pPort = RADEONGetCrtcConnector(pScrn, info->IsSecondary ? 2 : 1); - RADEONDPMSSetOff(pScrn, pPort); - if (pRADEONEnt->Controller[1]->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - RADEONDPMSSetOff(pScrn, pPort); - } - } } - -#ifdef XF86DRI - if (info->CPStarted) DRIUnlock(pScrn->pScreen); -#endif -} - -Bool RADEONAllocateControllers(ScrnInfoPtr pScrn) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - if (pRADEONEnt->Controller[0]) - return TRUE; - - pRADEONEnt->Controller[0] = xcalloc(sizeof(RADEONController), 1); - if (!pRADEONEnt->Controller[0]) - return FALSE; - - pRADEONEnt->Controller[1] = xcalloc(sizeof(RADEONController), 1); - if (!pRADEONEnt->Controller[1]) - { - xfree(pRADEONEnt->Controller[0]); - return FALSE; - } - - return TRUE; -} - -Bool RADEONAllocateConnectors(ScrnInfoPtr pScrn) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - int i; - - if (pRADEONEnt->PortInfo[0]) - return TRUE; - - /* for now always allocate max connectors */ - for (i = 0 ; i < RADEON_MAX_CONNECTOR; i++) { - pRADEONEnt->PortInfo[i] = xcalloc(sizeof(RADEONConnector), 1); - if (!pRADEONEnt->PortInfo[i]) - return FALSE; - } - - return TRUE; -} - -RADEONConnector *RADEONGetCrtcConnector(ScrnInfoPtr pScrn, int crtc_num) -{ - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - if (pRADEONEnt->PortInfo[0]->crtc_num == crtc_num) - return pRADEONEnt->PortInfo[0]; - else if (pRADEONEnt->PortInfo[1]->crtc_num == crtc_num) - return pRADEONEnt->PortInfo[1]; - return NULL; } diff --git a/src/radeon_dri.c b/src/radeon_dri.c index ee6192e9..24018e8b 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -69,7 +69,12 @@ static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen); static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen); #ifdef DAMAGE -static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg); + +#if (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)) +static void RADEONDRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num); +#endif #endif /* Initialize the visual configs that are supported by the hardware. @@ -398,10 +403,10 @@ static void RADEONLeaveServer(ScreenPtr pScreen) #ifdef DAMAGE if (info->pDamage) { RegionPtr pDamageReg = DamageRegion(info->pDamage); + int nrects = pDamageReg ? REGION_NUM_RECTS(pDamageReg) : 0; - if (pDamageReg) { - RADEONDRIRefreshArea(pScrn, REGION_NUM_RECTS(pDamageReg), - REGION_RECTS(pDamageReg)); + if (nrects) { + RADEONDRIRefreshArea(pScrn, pDamageReg); } } #endif @@ -409,13 +414,7 @@ static void RADEONLeaveServer(ScreenPtr pScreen) /* The CP is always running, but if we've generated any CP commands * we must flush them to the kernel module now. */ - if (info->CPInUse) { - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_IDLE(); - RADEONCPReleaseIndirect(pScrn); - - info->CPInUse = FALSE; - } + RADEONCP_RELEASE(pScrn, info); #ifdef USE_EXA info->engineMode = EXA_ENGINEMODE_UNKNOWN; @@ -754,28 +753,6 @@ static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, from, "Using AGP %dx\n", info->agpMode); - info->agpFastWrite = 0; // Always off by default as it sucks - - from = xf86GetOptValInteger(info->Options, OPTION_AGP_FW, - &info->agpFastWrite) ? X_CONFIG : X_DEFAULT; - - if (info->agpFastWrite && - (vendor == PCI_VENDOR_AMD) && - (device == PCI_CHIP_AMD761)) { - - /* Disable fast write for AMD 761 chipset, since they cause - * lockups when enabled. - */ - info->agpFastWrite = FALSE; - from = X_DEFAULT; - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[agp] Not enabling Fast Writes on AMD 761 chipset to avoid " - "lockups"); - } - - xf86DrvMsg(pScreen->myNum, from, "AGP Fast Writes %sabled\n", - info->agpFastWrite ? "en" : "dis"); - mode &= ~RADEON_AGP_MODE_MASK; if (is_v3) { /* only set one mode bit for AGPv3 */ @@ -794,8 +771,26 @@ static Bool RADEONSetAgpMode(RADEONInfoPtr info, ScreenPtr pScreen) } } - if (info->agpFastWrite) mode |= RADEON_AGP_FW_MODE; - else mode &= ~RADEON_AGP_FW_MODE; + /* AGP Fast Writes. + * TODO: take into account that certain agp modes don't support fast + * writes at all */ + mode &= ~RADEON_AGP_FW_MODE; /* Disable per default */ + if (xf86ReturnOptValBool(info->Options, OPTION_AGP_FW, FALSE)) { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "WARNING: Using the AGPFastWrite option is not recommended.\n"); + xf86Msg(X_NONE, "\tThis option does not provide much of a noticable speed" + " boost, while it\n\twill probably hard lock your machine." + " All bets are off!\n"); + + /* Black list some host/AGP bridges. */ + if ((vendor == PCI_VENDOR_AMD) && (device == PCI_CHIP_AMD761)) + xf86DrvMsg(pScreen->myNum, X_PROBED, "Ignoring AGPFastWrite option " + "for the AMD 761 northbridge.\n"); + else { + xf86DrvMsg(pScreen->myNum, X_CONFIG, "Enabling AGP Fast Writes.\n"); + mode |= RADEON_AGP_FW_MODE; + } + } /* Don't mention this otherwise, so that people don't get funny ideas */ xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n", @@ -1250,7 +1245,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) /* Check the DRI version */ DRIQueryVersion(&major, &minor, &patch); - if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { + if (major != DRIINFO_MAJOR_VERSION || minor < 0) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] RADEONDRIGetVersion failed because of a version " "mismatch.\n" @@ -1258,7 +1253,7 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) "needed.\n" "[dri] Disabling DRI.\n", major, minor, patch, - DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); + DRIINFO_MAJOR_VERSION, 0); return FALSE; } @@ -1358,6 +1353,29 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) return TRUE; } +Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int value = 0; + + if (info->directRenderingEnabled && info->pKernelDRMVersion->version_minor >= 28) { + if (on) { + if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled) + value = DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2; + else + value = DRM_RADEON_VBLANK_CRTC1; + } + + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_VBLANK_CRTC, value)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RADEON Vblank Crtc Setup Failed %d\n", value); + return FALSE; + } + } + return TRUE; +} + + /* Initialize the screen-specific data structures for the DRI and the * Radeon. This is the main entry point to the device-specific * initialization code. It calls device-independent DRI functions to @@ -1477,10 +1495,31 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d; pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d; pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d; +#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && \ + DRIINFO_MINOR_VERSION >= 1)) + pDRIInfo->ClipNotify = RADEONDRIClipNotify; +#endif pDRIInfo->createDummyCtx = TRUE; pDRIInfo->createDummyCtxPriv = FALSE; +#ifdef USE_EXA + if (info->useEXA) { +#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3 + int major, minor, patch; + + DRIQueryVersion(&major, &minor, &patch); + + if (minor >= 3) +#endif +#if DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 3) + pDRIInfo->texOffsetStart = RADEONTexOffsetStart; +#endif + } +#endif + if (!DRIScreenInit(pScreen, pDRIInfo, &info->drmFD)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); @@ -1646,6 +1685,9 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) info->DRICloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = RADEONDRIDoCloseScreen; + /* disable vblank at startup */ + RADEONDRISetVBlankInterrupt (pScrn, FALSE); + return TRUE; } @@ -1696,20 +1738,15 @@ void RADEONDRIStop(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); RING_LOCALS; - RADEONTRACE(("RADEONDRIStop\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONDRIStop\n"); /* Stop the CP */ if (info->directRenderingInited) { /* If we've generated any CP commands, we must flush them to the * kernel module now. */ - if (info->CPInUse) { - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_IDLE(); - RADEONCPReleaseIndirect(pScrn); - - info->CPInUse = FALSE; - } + RADEONCP_RELEASE(pScrn, info); RADEONCP_STOP(pScrn, info); } info->directRenderingInited = FALSE; @@ -1724,9 +1761,15 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); drmRadeonInit drmInfo; - RADEONTRACE(("RADEONDRICloseScreen\n")); - + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONDRICloseScreen\n"); + +#ifdef DAMAGE + REGION_UNINIT(pScreen, &info->driRegion); +#endif + if (info->irq) { + RADEONDRISetVBlankInterrupt (pScrn, FALSE); drmCtlUninstHandler(info->drmFD); info->irq = 0; info->ModeReg.gen_int_cntl = 0; @@ -1819,15 +1862,17 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) */ -static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg) { RADEONInfoPtr info = RADEONPTR(pScrn); - int i; + int i, num; ScreenPtr pScreen = pScrn->pScreen; RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); #ifdef USE_EXA PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); #endif + RegionRec region; + BoxPtr pbox; if (!info->directRenderingInited || !info->CPStarted) return; @@ -1838,6 +1883,17 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) if (!pSAREAPriv->pfAllowPageFlip && pSAREAPriv->pfCurrentPage == 0) return; + REGION_NULL(pScreen, ®ion); + REGION_SUBTRACT(pScreen, ®ion, pReg, &info->driRegion); + + num = REGION_NUM_RECTS(®ion); + + if (!num) { + goto out; + } + + pbox = REGION_RECTS(®ion); + /* pretty much a hack. */ #ifdef USE_EXA @@ -1858,7 +1914,7 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) if (!info->useEXA) { /* Make sure accel has been properly inited */ if (info->accel == NULL || info->accel->SetupForScreenToScreenCopy == NULL) - return; + goto out; if (info->tilingEnabled) info->dst_pitch_offset |= RADEON_DST_TILE_MACRO; (*info->accel->SetupForScreenToScreenCopy)(pScrn, @@ -1894,6 +1950,8 @@ static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) info->dst_pitch_offset &= ~RADEON_DST_TILE_MACRO; #endif +out: + REGION_NULL(pScreen, ®ion); DamageEmpty(info->pDamage); } @@ -1907,16 +1965,13 @@ static void RADEONEnablePageFlip(ScreenPtr pScreen) if (info->allowPageFlip) { RADEONSAREAPrivPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + BoxRec box = { .x1 = 0, .y1 = 0, .x2 = pScrn->virtualX - 1, + .y2 = pScrn->virtualY - 1 }; + RegionPtr pReg = REGION_CREATE(pScreen, &box, 1); pSAREAPriv->pfAllowPageFlip = 1; - -#ifdef USE_XAA - if (!info->useEXA) { - BoxRec box = { .x1 = 0, .y1 = 0, .x2 = pScrn->virtualX - 1, - .y2 = pScrn->virtualY - 1 }; - RADEONDRIRefreshArea(pScrn, 1, &box); - } -#endif + RADEONDRIRefreshArea(pScrn, pReg); + REGION_DESTROY(pScreen, pReg); } #endif } @@ -2023,6 +2078,9 @@ static void RADEONDRITransitionTo3d(ScreenPtr pScreen) RADEONChangeSurfaces(pScrn); RADEONEnablePageFlip(pScreen); + + info->want_vblank_interrupts = TRUE; + RADEONDRISetVBlankInterrupt(pScrn, TRUE); if (info->cursor) xf86ForceHWCursor (pScreen, TRUE); @@ -2062,10 +2120,40 @@ static void RADEONDRITransitionTo2d(ScreenPtr pScreen) RADEONChangeSurfaces(pScrn); + info->want_vblank_interrupts = FALSE; + RADEONDRISetVBlankInterrupt(pScrn, FALSE); + if (info->cursor) xf86ForceHWCursor (pScreen, FALSE); } +#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && \ + DRIINFO_MINOR_VERSION >= 1)) +static void +RADEONDRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + REGION_UNINIT(pScreen, &info->driRegion); + REGION_NULL(pScreen, &info->driRegion); + + if (num > 0) { + int i; + + for (i = 0; i < num; i++) { + WindowPtr pWin = ppWin[i]; + + if (pWin) { + REGION_UNION(pScreen, &info->driRegion, &pWin->clipList, + &info->driRegion); + } + } + } +} +#endif + void RADEONDRIAllocatePCIGARTTable(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; diff --git a/src/radeon_driver.c b/src/radeon_driver.c index ca0b2016..158e1e46 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -74,7 +74,6 @@ #include "radeon_macros.h" #include "radeon_probe.h" #include "radeon_version.h" -#include "radeon_mergedfb.h" #ifdef XF86DRI #define _XF86DRI_SERVER_ @@ -94,15 +93,15 @@ #include "xf86_ansic.h" /* For xf86getsecs() */ #include "xf86_OSproc.h" #include "xf86RAC.h" +#include "xf86RandR12.h" #include "xf86Resources.h" #include "xf86cmap.h" #include "vbe.h" - /* fbdevhw * vgaHW definitions */ + /* vgaHW definitions */ #ifdef WITH_VGAHW #include "vgaHW.h" #endif -#include "fbdevhw.h" #define DPMS_SERVER #include <X11/extensions/dpms.h> @@ -116,10 +115,7 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen); static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode); static void RADEONSave(ScrnInfoPtr pScrn); -static void RADEONRestore(ScrnInfoPtr pScrn); -static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); -static void RADEONGetMergedFBOptions(ScrnInfoPtr pScrn); static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode); static void RADEONForceSomeClocks(ScrnInfoPtr pScrn); static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); @@ -128,9 +124,11 @@ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); #endif -/* psuedo xinerama support */ +DisplayModePtr +RADEONCrtcFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode); -extern Bool RADEONnoPanoramiXExtension; +static void RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests, + unsigned nWaitLoops, unsigned cntThreshold); static const OptionInfoRec RADEONOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, @@ -159,19 +157,7 @@ static const OptionInfoRec RADEONOptions[] = { #endif #endif { 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_FBDEV, "UseFBDev", OPTV_BOOLEAN, {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_RADEONXINERAMA, "MergedXinerama", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_CRT2ISSCRN0, "MergedXineramaCRT2IsScreen0", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_MERGEDFBNONRECT, "MergedNonRectangular", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_MERGEDFBMOUSER, "MergedMouseRestriction", 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 }, @@ -198,12 +184,13 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_LVDS_PROBE_PLL, "LVDSProbePLL", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, { OPTION_CONSTANTDPI, "ConstantDPI", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_REVERSE_DISPLAY,"ReverseDisplay", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CONNECTORTABLE, "ConnectorTable", OPTV_STRING, {0}, FALSE }, + { OPTION_DEFAULT_CONNECTOR_TABLE, "DefaultConnectorTable", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; -_X_EXPORT const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions; } +const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions; } #ifdef WITH_VGAHW static const char *vgahwSymbols[] = { @@ -219,34 +206,6 @@ static const char *vgahwSymbols[] = { }; #endif -static const char *fbdevHWSymbols[] = { - "fbdevHWInit", - "fbdevHWUseBuildinMode", - - "fbdevHWGetVidmem", - - "fbdevHWDPMSSet", - - /* colormap */ - "fbdevHWLoadPalette", - /* ScrnInfo hooks */ - "fbdevHWAdjustFrame", - "fbdevHWEnterVT", - "fbdevHWLeaveVT", - "fbdevHWModeInit", - "fbdevHWRestore", - "fbdevHWSave", - "fbdevHWSwitchMode", - "fbdevHWValidModeWeak", - - "fbdevHWMapMMIO", - "fbdevHWMapVidmem", - "fbdevHWUnmapMMIO", - "fbdevHWUnmapVidmem", - - NULL -}; - static const char *ddcSymbols[] = { "xf86PrintEDID", "xf86DoEDID_DDC1", @@ -407,7 +366,6 @@ void RADEONLoaderRefSymLists(void) drmSymbols, driSymbols, #endif - fbdevHWSymbols, vbeSymbols, int10Symbols, i2cSymbols, @@ -441,6 +399,24 @@ struct RADEONInt10Save { static Bool RADEONMapMMIO(ScrnInfoPtr pScrn); static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn); +#if 0 +static Bool +RADEONCreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + pScreen->CreateScreenResources = info->CreateScreenResources; + if (!(*pScreen->CreateScreenResources)(pScreen)) + return FALSE; + + if (!xf86RandR12CreateScreenResources(pScreen)) + return FALSE; + + return TRUE; +} +#endif + RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) { DevUnion *pPriv; @@ -534,48 +510,6 @@ 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; @@ -588,15 +522,11 @@ static Bool RADEONMapMMIO(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) { - info->MMIO = fbdevHWMapMMIO(pScrn); - } else { - info->MMIO = xf86MapPciMem(pScrn->scrnIndex, - VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, - info->PciTag, - info->MMIOAddr, - info->MMIOSize); - } + info->MMIO = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, + info->PciTag, + info->MMIOAddr, + info->MMIOSize); if (!info->MMIO) return FALSE; return TRUE; @@ -609,11 +539,8 @@ static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) - fbdevHWUnmapMMIO(pScrn); - else { - xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, info->MMIOSize); - } + xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, info->MMIOSize); + info->MMIO = NULL; return TRUE; } @@ -623,16 +550,13 @@ static Bool RADEONMapFB(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) { - info->FB = fbdevHWMapVidmem(pScrn); - } else { - RADEONTRACE(("Map: 0x%08lx, 0x%08lx\n", info->LinearAddr, info->FbMapSize)); - info->FB = xf86MapPciMem(pScrn->scrnIndex, - VIDMEM_FRAMEBUFFER, - info->PciTag, - info->LinearAddr, - info->FbMapSize); - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Map: 0x%08lx, 0x%08lx\n", info->LinearAddr, info->FbMapSize); + info->FB = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_FRAMEBUFFER, + info->PciTag, + info->LinearAddr, + info->FbMapSize); if (!info->FB) return FALSE; return TRUE; @@ -643,10 +567,7 @@ static Bool RADEONUnmapFB(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->FBDev) - fbdevHWUnmapVidmem(pScrn); - else - xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize); + xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize); info->FB = NULL; return TRUE; } @@ -758,7 +679,7 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 crtc_gen_cntl; - int i; + struct timeval timeout; crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || @@ -769,10 +690,10 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn) OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ - for (i = 0; i < RADEON_TIMEOUT/1000; i++) { - if (INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) break; - usleep(1); - } + radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT); + while (!(INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) && + !radeon_timedout(&timeout)) + usleep(100); } /* Wait for vertical sync on secondary CRTC */ @@ -781,7 +702,7 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 crtc2_gen_cntl; - int i; + struct timeval timeout; crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || @@ -792,10 +713,10 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn) OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ - for (i = 0; i < RADEON_TIMEOUT/1000; i++) { - if (INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) break; - usleep(1); - } + radeon_init_timeout(&timeout, RADEON_VSYNC_TIMEOUT); + while (!(INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) && + !radeon_timedout(&timeout)) + usleep(100); } @@ -953,7 +874,8 @@ static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn) if (ref_div < 2) { CARD32 tmp; tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300)) + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300) + || (info->ChipFamily == CHIP_FAMILY_RS400)) ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; else @@ -1033,7 +955,8 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) CARD32 tmp; tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); if (IS_R300_VARIANT || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_RS400)) { 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; @@ -1083,10 +1006,11 @@ static void RADEONGetClockInfo(ScrnInfoPtr pScrn) } xf86DrvMsg (pScrn->scrnIndex, X_INFO, - "PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n", + "PLL parameters: rf=%d rd=%d min=%d max=%d; xclk=%d\n", pll->reference_freq, pll->reference_div, - pll->min_pll_freq, pll->max_pll_freq, pll->xclk); + (unsigned)pll->min_pll_freq, (unsigned)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 @@ -1200,7 +1124,7 @@ static Bool RADEONPreInitWeight(ScrnInfoPtr pScrn) return TRUE; } -static void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, +void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, RADEONInfoPtr info) { save->mc_fb_location = info->mc_fb_location; @@ -1214,7 +1138,7 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - unsigned long mem_size; + CARD32 mem_size; CARD32 aper_size; /* Default to existing values */ @@ -1242,8 +1166,7 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) } #endif - /* We won't try to change MC_FB_LOCATION when using fbdev */ - if (!info->FBDev) { + { if (info->IsIGP) info->mc_fb_location = INREG(RADEON_NB_TOM); else @@ -1283,10 +1206,15 @@ static void RADEONInitMemoryMap(ScrnInfoPtr pScrn) */ info->mc_agp_location = 0xffffffc0; - RADEONTRACE(("RADEONInitMemoryMap() : \n")); - RADEONTRACE((" mem_size : 0x%08lx\n", mem_size)); - RADEONTRACE((" MC_FB_LOCATION : 0x%08lx\n", info->mc_fb_location)); - RADEONTRACE((" MC_AGP_LOCATION : 0x%08lx\n", info->mc_agp_location)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "RADEONInitMemoryMap() : \n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " mem_size : 0x%08x\n", (unsigned)mem_size); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_FB_LOCATION : 0x%08x\n", (unsigned)info->mc_fb_location); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_AGP_LOCATION : 0x%08x\n", + (unsigned)info->mc_agp_location); } static void RADEONGetVRamType(ScrnInfoPtr pScrn) @@ -1349,8 +1277,8 @@ static CARD32 RADEONGetAccessibleVRAM(ScrnInfoPtr pScrn) if (info->directRenderingEnabled && info->pKernelDRMVersion->version_minor < 23) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "[dri] limiting video memory to one aperture of %ldK\n", - aper_size); + "[dri] limiting video memory to one aperture of %uK\n", + (unsigned)aper_size); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "[dri] detected radeon kernel module version 1.%d but" " 1.23 or newer is required for full memory mapping.\n", @@ -1406,9 +1334,7 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) MessageType from = X_PROBED; CARD32 accessible, bar_size; - if (info->FBDev) - pScrn->videoRam = fbdevHWGetVidmem(pScrn) / 1024; - else if ((info->IsIGP)) { + if ((info->IsIGP)) { CARD32 tom = INREG(RADEON_NB_TOM); pScrn->videoRam = (((tom >> 16) - @@ -1437,8 +1363,8 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) accessible = bar_size; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Detected total video RAM=%dK, accessible=%ldK (PCI BAR=%ldK)\n", - pScrn->videoRam, accessible, bar_size); + "Detected total video RAM=%dK, accessible=%uK (PCI BAR=%uK)\n", + pScrn->videoRam, (unsigned)accessible, (unsigned)bar_size); if (pScrn->videoRam > accessible) pScrn->videoRam = accessible; @@ -1459,24 +1385,6 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, from, "Mapped VideoRAM: %d kByte (%d bit %s SDRAM)\n", pScrn->videoRam, info->RamWidth, info->IsDDR?"DDR":"SDR"); - /* FIXME: For now, split FB into two equal sections. This should - * be able to be adjusted by user with a config option. */ - if (info->IsPrimary) { - pScrn->videoRam /= 2; - info->MergedFB = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %dk of videoram for primary head\n", - pScrn->videoRam); - } - - if (info->IsSecondary) { - pScrn->videoRam /= 2; - info->LinearAddr += pScrn->videoRam * 1024; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using %dk of videoram for secondary head\n", - pScrn->videoRam); - } - pScrn->videoRam &= ~1023; info->FbMapSize = pScrn->videoRam * 1024; @@ -1543,6 +1451,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) info->IsIGP = FALSE; info->IsDellServer = FALSE; info->HasSingleDAC = FALSE; + info->InternalTVOut = TRUE; switch (info->Chipset) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ: @@ -1602,6 +1511,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) case PCI_CHIP_R200_QL: case PCI_CHIP_R200_QM: info->ChipFamily = CHIP_FAMILY_R200; + info->InternalTVOut = FALSE; break; case PCI_CHIP_RADEON_LW: @@ -1713,7 +1623,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) case PCI_CHIP_RS482_5974: info->ChipFamily = CHIP_FAMILY_RS400; info->IsIGP = TRUE; - /*info->HasSingleDAC = TRUE;*/ /* ??? */ + info->HasSingleDAC = TRUE; break; case PCI_CHIP_RV410_564A: @@ -1784,6 +1694,7 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) /* Original Radeon/7200 */ info->ChipFamily = CHIP_FAMILY_RADEON; pRADEONEnt->HasCRTC2 = FALSE; + info->InternalTVOut = FALSE; } @@ -1903,10 +1814,15 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) } } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s card detected\n", (info->cardType==CARD_PCI) ? "PCI" : (info->cardType==CARD_PCIE) ? "PCIE" : "AGP"); + /* treat PCIE IGP cards as PCI */ + if (info->cardType == CARD_PCIE && info->IsIGP) + info->cardType = CARD_PCI; + if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { if (strcmp(s, "AGP") == 0) { info->cardType = CARD_AGP; @@ -1957,9 +1873,7 @@ static void RADEONPreInitDDC(ScrnInfoPtr pScrn) if (info->ddc2) { if (xf86LoadSubModule(pScrn, "i2c")) { xf86LoaderReqSymLists(i2cSymbols,NULL); - info->ddc2 = RADEONI2cInit(pScrn); } - else info->ddc2 = FALSE; } } @@ -1972,398 +1886,6 @@ static Bool RADEONPreInitGamma(ScrnInfoPtr pScrn) return TRUE; } -/* This is called by RADEONPreInit to validate modes and compute - * parameters for all of the valid modes. - */ -static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - ClockRangePtr clockRanges; - int modesFound; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - char *s; - RADEONConnector *connector; - /* This option has two purposes: - * - * 1. For CRT, if this option is on, xf86ValidateModes (to - * LOOKUP_BEST_REFRESH) is not going to be used for mode - * validation. Instead, we'll validate modes by matching exactly - * the modes supported from the DDC data. This option can be - * used (a) to enable non-standard modes listed in the Detailed - * Timings block of EDID, like 2048x1536 (not included in - * xf86DefModes), (b) to avoid unstable modes for some flat - * panels working in analog mode (some modes validated by - * xf86ValidateModes don't really work with these panels). - * - * 2. For DFP on primary head, with this option on, the validation - * routine will try to use supported modes from DDC data first - * before trying on-chip RMX streching. By default, native mode - * + RMX streching is used for all non-native modes, it appears - * more reliable. Some non-native modes listed in the DDC data - * may not work properly if they are used directly. This seems to - * only happen to a few panels (haven't nailed this down yet, it - * may related to the incorrect setting in TMDS_PLL_CNTL when - * pixel clock is changed). Use this option may give you better - * refresh rate for some non-native modes. The 2nd DVI port will - * always use DDC modes directly (only have one on-chip RMX - * unit). - * - * 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-tmds panels */ - - if ((connector = RADEONGetCrtcConnector(pScrn, 2))) - if (connector->MonType == MT_DFP) - info->ddc_mode = TRUE; - /* don't use RMX if we are Dell Server */ - if (info->IsDellServer) - { - info->ddc_mode = TRUE; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Validating modes on %s head ---------\n", - info->IsSecondary ? "Secondary" : "Primary"); - - if (!pRADEONEnt->PortInfo[0]->MonInfo && !pRADEONEnt->PortInfo[1]->MonInfo && info->ddc_mode) { - info->ddc_mode = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No DDC data available, DDCMode option is dismissed\n"); - } - - if ((info->DisplayType == MT_DFP) || - (info->DisplayType == MT_LCD)) { - if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { - int PanelX, PanelY; - DisplayModePtr tmp_mode = NULL; - if (sscanf(s, "%dx%d", &PanelX, &PanelY) == 2) { - info->PanelXRes = PanelX; - info->PanelYRes = PanelY; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Panel size is forced to: %s\n", s); - - /* We can't trust BIOS or DDC timings anymore, - Use whatever specified in the Modeline. - If no Modeline specified, we'll just pick the VESA mode at - 60Hz refresh rate which is likely to be the best for a flat panel. - */ - info->ddc_mode = FALSE; - pScrn->monitor->DDC = NULL; - tmp_mode = pScrn->monitor->Modes; - while(tmp_mode) { - if ((tmp_mode->HDisplay == PanelX) && - (tmp_mode->VDisplay == PanelY)) { - - float refresh = - (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; - if ((abs(60.0 - refresh) < 1.0) || - (tmp_mode->type == 0)) { - info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; - info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; - info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; - info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; - info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; - info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; - info->DotClock = tmp_mode->Clock; - info->Flags = 0; - break; - } - } - tmp_mode = tmp_mode->next; - } - if (info->DotClock == 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid timing info for specified panel size.\n" - "Please specify the Modeline for this panel\n"); - return FALSE; - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Invalid PanelSize value: %s\n", s); - } - } else - RADEONGetPanelInfo(pScrn); - } - - 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->DisplayType == MT_CRT); - clockRanges->doubleScanAllowed = (info->DisplayType == MT_CRT); - - /* 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 (info->DisplayType == MT_CRT && !info->ddc_mode) { - - modesFound = - xf86ValidateModes(pScrn, - pScrn->monitor->Modes, - pScrn->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - info->allowColorTiling ? 2048 : - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - - if (modesFound < 1 && info->FBDev) { - fbdevHWUseBuildinMode(pScrn); - pScrn->displayWidth = fbdevHWGetLineLength(pScrn) - / info->CurrentLayout.pixel_bytes; - modesFound = 1; - } - - if (modesFound == -1) return FALSE; - - xf86PruneDriverModes(pScrn); - if (!modesFound || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); - return FALSE; - } - - } else { - /* First, free any allocated modes during configuration, since - * we don't need them - */ - while (pScrn->modes) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - - /* Next try to add DDC modes */ - modesFound = RADEONValidateDDCModes(pScrn, pScrn->display->modes, - info->DisplayType, 0); - - /* If that fails and we're connect to a flat panel, then try to - * add the flat panel modes - */ - if (info->DisplayType != 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 (pScrn->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; - } - } - - 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, - pScrn->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - info->allowColorTiling ? 2048 : - 64 * pScrn->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn->display->virtualX, - pScrn->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - else if (!info->IsSecondary) - modesFound = RADEONValidateFPModes(pScrn, pScrn->display->modes); - } - } - - /* 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; - } - - /* Fail if we still don't have any valid modes */ - if (modesFound < 1) { - if (info->DisplayType == 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 FALSE; - } - } - - xf86SetCrtcForModes(pScrn, 0); - - if (pRADEONEnt->HasCRTC2) { - if (pRADEONEnt->Controller[1]->binding == 1) { - - /* 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); - } - } - } - - pScrn->currentMode = pScrn->modes; - if(info->MergedFB) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Modes for CRT1: ********************\n"); - } - xf86PrintModes(pScrn); - - - if (pRADEONEnt->HasCRTC2) { - if(pRADEONEnt->Controller[1]->binding == 1) { - - 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); - info->CRT2pScrn = NULL; - } - 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); */ - - if (info->MergedFB) { - RADEONMergedFBSetDpi(pScrn, info->CRT2pScrn, info->CRT2Position); - } else { - xf86SetDpi(pScrn, 0, 0); - info->RADEONDPIVX = pScrn->virtualX; - info->RADEONDPIVY = pScrn->virtualY; - } - - /* Get ScreenInit function */ - if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; - - xf86LoaderReqSymLists(fbSymbols, NULL); - - info->CurrentLayout.displayWidth = pScrn->displayWidth; - info->CurrentLayout.mode = pScrn->currentMode; - - return TRUE; -} - /* This is called by RADEONPreInit to initialize the hardware cursor */ static Bool RADEONPreInitCursor(ScrnInfoPtr pScrn) { @@ -2500,18 +2022,6 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) info->pLibDRMVersion = NULL; info->pKernelDRMVersion = NULL; - if (xf86IsEntityShared(info->pEnt->index)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "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"); - return FALSE; - } - if (info->IsSecondary) - return FALSE; - if (info->Chipset == PCI_CHIP_RN50_515E || info->Chipset == PCI_CHIP_RN50_5969) { if (xf86ReturnOptValBool(info->Options, OPTION_DRI, FALSE)) { @@ -2526,18 +2036,6 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) } } - if (info->Chipset == PCI_CHIP_RS400_5A41 || - info->Chipset == PCI_CHIP_RS400_5A42 || - info->Chipset == PCI_CHIP_RC410_5A61 || - info->Chipset == PCI_CHIP_RC410_5A62 || - info->Chipset == PCI_CHIP_RS480_5954 || - info->Chipset == PCI_CHIP_RS480_5955 || - info->Chipset == PCI_CHIP_RS482_5974 || - info->Chipset == PCI_CHIP_RS482_5975) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Direct rendering broken on XPRESS 200 and 200M\n"); - return FALSE; - } if (!xf86ReturnOptValBool(info->Options, OPTION_DRI, TRUE)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -2564,6 +2062,24 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) info->pKernelDRMVersion->version_minor, info->pKernelDRMVersion->version_patchlevel); + if (info->Chipset == PCI_CHIP_RS400_5A41 || + info->Chipset == PCI_CHIP_RS400_5A42 || + info->Chipset == PCI_CHIP_RC410_5A61 || + info->Chipset == PCI_CHIP_RC410_5A62 || + info->Chipset == PCI_CHIP_RS480_5954 || + info->Chipset == PCI_CHIP_RS480_5955 || + info->Chipset == PCI_CHIP_RS482_5974 || + info->Chipset == PCI_CHIP_RS482_5975) { + + if (info->pKernelDRMVersion->version_minor < 27) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Direct rendering broken on XPRESS 200 and 200M with DRI less than 1.27\n"); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Direct rendering experimental on RS400/Xpress 200 enabled\n"); + } + if (xf86ReturnOptValBool(info->Options, OPTION_CP_PIO, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing CP into PIO mode\n"); info->CPMode = RADEON_DEFAULT_CP_PIO_MODE; @@ -2702,6 +2218,7 @@ static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) info->allowColorTiling = xf86ReturnOptValBool(info->Options, OPTION_COLOR_TILING, TRUE); if (IS_R300_VARIANT) { + /* this may be 4096 on r4xx -- need to double check */ info->MaxSurfaceWidth = 3968; /* one would have thought 4096...*/ info->MaxLines = 4096; } else { @@ -2728,19 +2245,7 @@ static void RADEONPreInitColorTiling(ScrnInfoPtr pScrn) } #endif /* XF86DRI */ - if ((info->allowColorTiling) && (info->IsSecondary)) { - /* can't have tiling on the 2nd head (as long as it can't use drm). - * We'd never get the surface save/restore (vt switching) right... - */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled for 2nd head\n"); - info->allowColorTiling = FALSE; - } - else if ((info->allowColorTiling) && (info->FBDev)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Color tiling not supported with UseFBDev option\n"); - info->allowColorTiling = FALSE; - } - else if (info->allowColorTiling) { + if (info->allowColorTiling) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling enabled by default\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Color tiling disabled\n"); @@ -2935,28 +2440,39 @@ static Bool RADEONPreInitXv(ScrnInfoPtr pScrn) return TRUE; } -static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) +static void RADEONPreInitBIOS(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) { - RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONGetBIOSInfo(pScrn, pInt10); +#if 0 + RADEONGetBIOSInitTableOffsets(pScrn); + RADEONPostCardFromBIOSTables(pScrn); +#endif +} - if (!info->IsSecondary) { - if (!RADEONAllocateConnectors(pScrn)) - return FALSE; +static Bool RADEONPreInitControllers(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - if (!RADEONAllocateControllers(pScrn)) + if (!RADEONAllocateControllers(pScrn)) return FALSE; - - } - RADEONGetBIOSInfo(pScrn, pInt10); + RADEONGetClockInfo(pScrn); - RADEONSetupConnectors(pScrn); - RADEONMapControllers(pScrn); + if (!RADEONSetupConnectors(pScrn)) { + return FALSE; + } + + RADEONPrintPortMap(pScrn); - RADEONGetClockInfo(pScrn); - RADEONGetPanelInfo(pScrn); - RADEONGetTVDacAdjInfo(pScrn); - + for (i = 0; i < config->num_output; i++) + { + xf86OutputPtr output = config->output[i]; + + output->status = (*output->funcs->detect) (output); + ErrorF("finished output detect: %d\n", i); + } + ErrorF("finished all detect\n"); return TRUE; } @@ -2971,24 +2487,36 @@ RADEONProbeDDC(ScrnInfoPtr pScrn, int indx) } } +static Bool +RADEONCRTCResize(ScrnInfoPtr scrn, int width, int height) +{ + scrn->virtualX = width; + scrn->virtualY = height; + /* RADEONSetPitch(scrn); */ + return TRUE; +} + +static const xf86CrtcConfigFuncsRec RADEONCRTCResizeFuncs = { + RADEONCRTCResize +}; + _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) { + xf86CrtcConfigPtr xf86_config; RADEONInfoPtr info; xf86Int10InfoPtr pInt10 = NULL; void *int10_save = NULL; const char *s; MessageType from; + int crtc_max_X, crtc_max_Y; - RADEONTRACE(("RADEONPreInit\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONPreInit\n"); if (pScrn->numEntities != 1) return FALSE; if (!RADEONGetRec(pScrn)) return FALSE; info = RADEONPTR(pScrn); - info->IsSecondary = FALSE; - info->IsPrimary = FALSE; - info->MergedFB = FALSE; - info->IsSwitching = FALSE; info->MMIO = NULL; info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); @@ -3032,30 +2560,6 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) RADEONPreInt10Save(pScrn, &int10_save); #endif - if (xf86IsEntityShared(info->pEnt->index)) { - if (xf86IsPrimInitDone(info->pEnt->index)) { - - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - info->IsSecondary = TRUE; - if (!pRADEONEnt->HasSecondary) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Only one monitor detected, Second screen " - "will NOT be created\n"); - goto fail2; - } - pRADEONEnt->pSecondaryScrn = pScrn; - } else { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - info->IsPrimary = TRUE; - - xf86SetPrimInitDone(info->pEnt->index); - - pRADEONEnt->pPrimaryScrn = pScrn; - } - } - if (flags & PROBE_DETECT) { RADEONProbeDDC(pScrn, info->pEnt->index); RADEONPostInt10Check(pScrn, int10_save); @@ -3079,6 +2583,11 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; pScrn->monitor = pScrn->confScreen->monitor; + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + if (!RADEONPreInitVisual(pScrn)) goto fail; @@ -3153,63 +2662,94 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) "X server will %skeep DPI constant for all screen sizes\n", info->constantDPI ? "" : "not "); - if (xf86ReturnOptValBool(info->Options, OPTION_FBDEV, FALSE)) { - /* check for Linux framebuffer device */ - - if (xf86LoadSubModule(pScrn, "fbdevhw")) { - xf86LoaderReqSymLists(fbdevHWSymbols, NULL); - - if (fbdevHWInit(pScrn, info->PciInfo, NULL)) { - pScrn->ValidMode = fbdevHWValidModeWeak(); - info->FBDev = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "Using framebuffer device\n"); - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "fbdevHWInit failed, not using framebuffer device\n"); - } - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Couldn't load fbdevhw module, not using framebuffer device\n"); - } - } - - if (!info->FBDev) - if (!RADEONPreInitInt10(pScrn, &pInt10)) - goto fail; + if (!RADEONPreInitInt10(pScrn, &pInt10)) + goto fail; RADEONPostInt10Check(pScrn, int10_save); if (!RADEONPreInitChipType(pScrn)) goto fail; + RADEONPreInitBIOS(pScrn, pInt10); + #ifdef XF86DRI /* PreInit DRI first of all since we need that for getting a proper * memory map */ info->directRenderingEnabled = RADEONPreInitDRI(pScrn); #endif - if (!RADEONPreInitVRAM(pScrn)) goto fail; RADEONPreInitColorTiling(pScrn); + /* we really need an FB manager... */ + if (pScrn->display->virtualX) { + crtc_max_X = pScrn->display->virtualX; + crtc_max_Y = pScrn->display->virtualY; + if (info->allowColorTiling) { + if (crtc_max_X > info->MaxSurfaceWidth) + crtc_max_X = info->MaxSurfaceWidth; + if (crtc_max_Y > info->MaxLines) + crtc_max_Y = info->MaxLines; + } else { + if (crtc_max_X > 8192) + crtc_max_X = 8192; + if (crtc_max_Y > 8192) + crtc_max_Y = 8192; + } + } else { + if (pScrn->videoRam < 16384) { + crtc_max_X = 1600; + crtc_max_Y = 1200; + } else if (pScrn->videoRam <= 32768) { + crtc_max_X = 2048; + crtc_max_Y = 1200; + } else if (pScrn->videoRam > 32768) { + if (IS_R300_VARIANT) { + crtc_max_X = 2560; + crtc_max_Y = 2048; + } else { + crtc_max_X = 2048; + crtc_max_Y = 2048; + } + } + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n", + crtc_max_X, crtc_max_Y); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n"); + + /*xf86CrtcSetSizeRange (pScrn, 320, 200, info->MaxSurfaceWidth, info->MaxLines);*/ + xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y); + RADEONPreInitDDC(pScrn); - if (!RADEONPreInitControllers(pScrn, pInt10)) + if (!RADEONPreInitControllers(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; + ErrorF("before xf86InitialConfiguration\n"); + + if (!xf86InitialConfiguration (pScrn, FALSE)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + goto fail; + } + + ErrorF("after xf86InitialConfiguration\n"); - if (!RADEONPreInitModes(pScrn, pInt10)) goto fail; + RADEONSetPitch(pScrn); + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + /* Get ScreenInit function */ + if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; + + xf86LoaderReqSymLists(fbSymbols, NULL); + + if (!RADEONPreInitGamma(pScrn)) goto fail; if (!RADEONPreInitCursor(pScrn)) goto fail; @@ -3217,6 +2757,17 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONPreInitXv(pScrn)) goto fail; + if (!xf86RandR12PreInit (pScrn)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); + goto fail; + } + + if (pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); + goto fail; + } + /* Free the video bios (if applicable) */ if (info->VBIOS) { xfree(info->VBIOS); @@ -3238,10 +2789,6 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) fail: /* Pre-init failed. */ - if (info->IsSecondary) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - pRADEONEnt->HasSecondary = FALSE; - } /* Free the video bios (if applicable) */ if (info->VBIOS) { xfree(info->VBIOS); @@ -3257,7 +2804,6 @@ fail: vgaHWFreeHWRec(pScrn); #endif - fail2: if(info->MMIO) RADEONUnmapMMIO(pScrn); info->MMIO = NULL; @@ -3272,10 +2818,11 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) { RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int i; - int idx, j; - unsigned char r, g, b; + int index, j; + CARD16 lut_r[256], lut_g[256], lut_b[256]; + int c; #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); @@ -3284,112 +2831,60 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors, if (info->accelOn && pScrn->pScreen) RADEON_SYNC(info, pScrn); - if (info->FBDev) { - fbdevHWLoadPalette(pScrn, numColors, indices, colors, pVisual); - } else { - /* If the second monitor is connected, we also need to deal with - * the secondary palette - */ - if (info->IsSecondary) j = 1; - else j = 0; - - PAL_SELECT(j); - - if (info->CurrentLayout.depth == 15) { - /* 15bpp mode. This sends 32 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - g = colors[idx].green; - b = colors[idx].blue; - OUTPAL(idx * 8, r, g, b); - } - } else if (info->CurrentLayout.depth == 16) { - /* 16bpp mode. This sends 64 values. - * - * There are twice as many green values as there are values - * for red and blue. So, we take each red and blue pair, - * and combine it with each of the two green values. - */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx / 2].red; - g = colors[idx].green; - b = colors[idx / 2].blue; - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL(idx * 4, r, g, b); - - /* AH - Added to write extra green data - How come this isn't - * needed on R128? We didn't load the extra green data in the - * other routine - */ - if (idx <= 31) { - r = colors[idx].red; - g = colors[(idx * 2) + 1].green; - b = colors[idx].blue; - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL(idx * 8, r, g, b); - } - } - } else { - /* 8bpp mode. This sends 256 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - b = colors[idx].blue; - g = colors[idx].green; - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL(idx, r, g, b); - } - } + { - if (info->MergedFB) { - PAL_SELECT(1); - if (info->CurrentLayout.depth == 15) { - /* 15bpp mode. This sends 32 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - g = colors[idx].green; - b = colors[idx].blue; - OUTPAL(idx * 8, r, g, b); - } - } else if (info->CurrentLayout.depth == 16) { - /* 16bpp mode. This sends 64 values. - * - * There are twice as many green values as there are values - * for red and blue. So, we take each red and blue pair, - * and combine it with each of the two green values. - */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx / 2].red; - g = colors[idx].green; - b = colors[idx / 2].blue; - OUTPAL(idx * 4, r, g, b); - - /* AH - Added to write extra green data - How come - * this isn't needed on R128? We didn't load the - * extra green data in the other routine. - */ - if (idx <= 31) { - r = colors[idx].red; - g = colors[(idx * 2) + 1].green; - b = colors[idx].blue; - OUTPAL(idx * 8, r, g, b); - } - } - } else { - /* 8bpp mode. This sends 256 values. */ - for (i = 0; i < numColors; i++) { - idx = indices[i]; - r = colors[idx].red; - b = colors[idx].blue; - g = colors[idx].green; - OUTPAL(idx, r, g, b); - } - } - } + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + for (i = 0 ; i < 256; i++) { + lut_r[i] = radeon_crtc->lut_r[i] << 8; + lut_g[i] = radeon_crtc->lut_g[i] << 8; + lut_b[i] = radeon_crtc->lut_b[i] << 8; + } + + switch (info->CurrentLayout.depth) { + case 15: + for (i = 0; i < numColors; i++) { + index = indices[i]; + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_g[index * 8 + j] = colors[index].green << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + case 16: + for (i = 0; i < numColors; i++) { + index = indices[i]; + + if (i <= 31) { + for (j = 0; j < 8; j++) { + lut_r[index * 8 + j] = colors[index].red << 8; + lut_b[index * 8 + j] = colors[index].blue << 8; + } + } + + for (j = 0; j < 4; j++) { + lut_g[index * 4 + j] = colors[index].green << 8; + } + } + default: + for (i = 0; i < numColors; i++) { + index = indices[i]; + lut_r[index] = colors[index].red << 8; + lut_g[index] = colors[index].green << 8; + lut_b[index] = colors[index].blue << 8; + } + break; + } + + /* Make the change through RandR */ +#ifdef RANDR_12_INTERFACE + RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b); +#else + crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256); +#endif + } } #ifdef XF86DRI @@ -3404,14 +2899,6 @@ static void RADEONBlockHandler(int i, pointer blockData, ScrnInfoPtr pScrn = xf86Screens[i]; RADEONInfoPtr info = RADEONPTR(pScrn); -#ifdef XF86DRI - if (info->directRenderingInited) { - FLUSH_RING(); - } -#endif -#ifdef USE_EXA - info->engineMode = EXA_ENGINEMODE_UNKNOWN; -#endif pScreen->BlockHandler = info->BlockHandler; (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); pScreen->BlockHandler = RADEONBlockHandler; @@ -3423,6 +2910,10 @@ static void RADEONBlockHandler(int i, pointer blockData, if(info->RenderCallback) (*info->RenderCallback)(pScrn); #endif + +#ifdef USE_EXA + info->engineMode = EXA_ENGINEMODE_UNKNOWN; +#endif } @@ -3682,8 +3173,8 @@ Bool RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen) info->depthOffset); if (info->cardType==CARD_PCIE) xf86DrvMsg(scrnIndex, X_INFO, - "Will use %d kb for PCI GART table at offset 0x%lx\n", - info->pciGartSize/1024, info->pciGartOffset); + "Will use %d kb for PCI GART table at offset 0x%x\n", + info->pciGartSize/1024, (unsigned)info->pciGartOffset); xf86DrvMsg(scrnIndex, X_INFO, "Will use %d kb for textures at offset 0x%x\n", info->textureSize/1024, info->textureOffset); @@ -3762,27 +3253,65 @@ Bool RADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen) } #endif /* USE_XAA */ +static void +RADEONPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + RADEONInfoPtr info = RADEONPTR(pScrn); + int newX = x, newY = y; + + switch (info->rotation) { + case RR_Rotate_0: + break; + case RR_Rotate_90: + newX = y; + newY = pScrn->pScreen->width - x - 1; + break; + case RR_Rotate_180: + newX = pScrn->pScreen->width - x - 1; + newY = pScrn->pScreen->height - y - 1; + break; + case RR_Rotate_270: + newX = pScrn->pScreen->height - y - 1; + newY = x; + break; + } + + (*info->PointerMoved)(index, newX, newY); +} + /* Called at the start of each server generation. */ -_X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, +Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int hasDRI = 0; + int i; #ifdef RENDER int subPixelOrder = SubPixelUnknown; char* s; #endif - RADEONTRACE(("RADEONScreenInit %lx %ld %d\n", - pScrn->memPhysBase, pScrn->fbOffset, info->frontOffset)); +#ifdef XF86DRI + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONScreenInit %lx %ld %d\n", + pScrn->memPhysBase, pScrn->fbOffset, info->frontOffset); +#else + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONScreenInit %lx %ld\n", + pScrn->memPhysBase, pScrn->fbOffset); +#endif info->accelOn = FALSE; #ifdef USE_XAA info->accel = NULL; #endif +#ifdef XF86DRI pScrn->fbOffset = info->frontOffset; - if (info->IsSecondary) pScrn->fbOffset = pScrn->videoRam * 1024; +#endif + if (!RADEONMapMem(pScrn)) return FALSE; #ifdef XF86DRI @@ -3792,9 +3321,14 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->PaletteSavedOnVT = FALSE; + info->crtc_on = FALSE; + info->crtc2_on = FALSE; + RADEONSave(pScrn); - if ((!info->IsSecondary) && info->IsMobility) { + RADEONDisableDisplays(pScrn); + + if (info->IsMobility) { if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { RADEONSetDynamicClock(pScrn, 1); } else { @@ -3802,8 +3336,8 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } - if ((!info->IsSecondary) && (IS_R300_VARIANT || IS_RV100_VARIANT)) - RADEONForceSomeClocks(pScrn); + if (IS_R300_VARIANT || IS_RV100_VARIANT) + RADEONForceSomeClocks(pScrn); if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -3812,17 +3346,7 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->allowColorTiling = FALSE; } if (info->allowColorTiling) { - if (info->MergedFB) { - if ((((RADEONMergedDisplayModePtr)pScrn->currentMode->Private)->CRT1->Flags & - (V_DBLSCAN | V_INTERLACE)) || - (((RADEONMergedDisplayModePtr)pScrn->currentMode->Private)->CRT2->Flags & - (V_DBLSCAN | V_INTERLACE))) - info->tilingEnabled = FALSE; - else info->tilingEnabled = TRUE; - } - else { - info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; - } + info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; } /* Visual setup */ @@ -3863,15 +3387,13 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, */ RADEONInitMemoryMap(pScrn); - if (!info->IsSecondary) { - /* empty the surfaces */ - unsigned char *RADEONMMIO = info->MMIO; - unsigned int i; - for (i = 0; i < 8; i++) { - OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0); - OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0); - OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0); - } + /* empty the surfaces */ + unsigned char *RADEONMMIO = info->MMIO; + unsigned int j; + for (j = 0; j < 8; j++) { + OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0); } #ifdef XF86DRI @@ -3891,14 +3413,14 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif /* Initial setup of surfaces */ - if (!info->IsSecondary) { - RADEONTRACE(("Setting up initial surfaces\n")); - RADEONChangeSurfaces(pScrn); - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Setting up initial surfaces\n"); + RADEONChangeSurfaces(pScrn); /* Memory manager setup */ - RADEONTRACE(("Setting up accel memmap\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Setting up accel memmap\n"); #ifdef USE_EXA if (info->useEXA) { @@ -3969,6 +3491,7 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* Setup DRI after visuals have been established, but before fbScreenInit is * called. fbScreenInit will eventually call the driver's InitGLXVisuals * call back. */ +#ifdef XF86DRI if (info->directRenderingEnabled) { /* FIXME: When we move to dynamic allocation of back and depth * buffers, we will want to revisit the following check for 3 @@ -3992,7 +3515,6 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } -#if defined(XF86DRI) /* Tell DRI about new memory map */ if (info->directRenderingEnabled && info->newMemoryMap) { if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { @@ -4003,7 +3525,8 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } #endif - RADEONTRACE(("Initializing fb layer\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing fb layer\n"); /* Init fb layer */ if (!fbScreenInit(pScreen, info->FB + pScrn->fbOffset, @@ -4040,38 +3563,34 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, else if (strcmp(s, "NONE") == 0) subPixelOrder = SubPixelNone; PictureSetSubpixelOrder (pScreen, subPixelOrder); } +#endif - if (PictureGetSubpixelOrder (pScreen) == SubPixelUnknown) { - switch (info->DisplayType) { - case MT_NONE: subPixelOrder = SubPixelUnknown; break; - case MT_LCD: subPixelOrder = SubPixelHorizontalRGB; break; - case MT_DFP: subPixelOrder = SubPixelHorizontalRGB; break; - default: subPixelOrder = SubPixelNone; break; + pScrn->vtSema = TRUE; + + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) { + crtc->desiredMode = *RADEONCrtcFindClosestMode (crtc, pScrn->currentMode); + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredX = 0; + crtc->desiredY = 0; } - PictureSetSubpixelOrder (pScreen, subPixelOrder); - } -#endif - if (info->FBDev) { - unsigned char *RADEONMMIO = info->MMIO; + if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, crtc->desiredX, crtc->desiredY)) + return FALSE; - if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; - pScrn->displayWidth = fbdevHWGetLineLength(pScrn) - / info->CurrentLayout.pixel_bytes; - RADEONSaveMemMapRegisters(pScrn, &info->ModeReg); - info->fbLocation = (info->ModeReg.mc_fb_location & 0xffff) << 16; - info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); - info->ModeReg.surface_cntl &= ~RADEON_SURF_TRANSLATION_DIS; - } else { - if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; } RADEONSaveScreen(pScreen, SCREEN_SAVER_ON); - pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + // pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); /* Backing store setup */ - RADEONTRACE(("Initializing backing store\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing backing store\n"); miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); @@ -4091,7 +3610,8 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } if (info->directRenderingEnabled) { - RADEONTRACE(("DRI Finishing init !\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "DRI Finishing init !\n"); info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); } if (info->directRenderingEnabled) { @@ -4120,18 +3640,15 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif /* Make sure surfaces are allright since DRI setup may have changed them */ - if (!info->IsSecondary) { - RADEONTRACE(("Setting up final surfaces\n")); - RADEONChangeSurfaces(pScrn); - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Setting up final surfaces\n"); - if(info->MergedFB) - /* need this here to fix up sarea values */ - RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + RADEONChangeSurfaces(pScrn); /* Enable aceleration */ if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { - RADEONTRACE(("Initializing Acceleration\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Acceleration\n"); if (RADEONAccelInit(pScreen)) { xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n"); info->accelOn = TRUE; @@ -4147,10 +3664,12 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } /* Init DPMS */ - RADEONTRACE(("Initializing DPMS\n")); - xf86DPMSInit(pScreen, RADEONDisplayPowerManagementSet, 0); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing DPMS\n"); + xf86DPMSInit(pScreen, xf86DPMSSet, 0); - RADEONTRACE(("Initializing Cursor\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Cursor\n"); /* Set Silken Mouse */ xf86SetSilkenMouse(pScreen); @@ -4166,9 +3685,9 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int width, height; xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Using hardware cursor (scanline %ld)\n", - info->cursor_offset / pScrn->displayWidth - / info->CurrentLayout.pixel_bytes); + "Using hardware cursor (scanline %u)\n", + (unsigned)(info->cursor_offset / pScrn->displayWidth + / info->CurrentLayout.pixel_bytes)); if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 0, 0, 0)) { xf86DrvMsg(scrnIndex, X_INFO, @@ -4187,42 +3706,16 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, xf86DrvMsg(scrnIndex, X_INFO, "Using software cursor\n"); } - /* Colormap setup */ - RADEONTRACE(("Initializing color map\n")); - if (!miCreateDefColormap(pScreen)) return FALSE; - if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, - RADEONLoadPalette, NULL, - CMAP_PALETTED_TRUECOLOR -#if 0 /* This option messes up text mode! (eich@suse.de) */ - | CMAP_LOAD_EVEN_IF_OFFSCREEN -#endif - | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE; - /* DGA setup */ - RADEONTRACE(("Initializing DGA\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing DGA\n"); RADEONDGAInit(pScreen); - /* Wrap some funcs for MergedFB */ - if(info->MergedFB) { - info->PointerMoved = pScrn->PointerMoved; - pScrn->PointerMoved = RADEONMergePointerMoved; - /* Psuedo xinerama */ - if(info->UseRADEONXinerama) { - RADEONnoPanoramiXExtension = FALSE; - RADEONXineramaExtensionInit(pScrn); - } else { - info->MouseRestrictions = FALSE; - } - } - /* Init Xv */ - RADEONTRACE(("Initializing Xv\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Xv\n"); RADEONInitVideo(pScreen); - if(info->MergedFB) - /* need this here to fix up sarea values */ - RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ /* Wrap CloseScreen */ info->CloseScreen = pScreen->CloseScreen; @@ -4231,17 +3724,37 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; + if (!xf86CrtcScreenInit (pScreen)) + return FALSE; + + /* Wrap pointer motion to flip touch screen around */ + info->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = RADEONPointerMoved; + + /* Colormap setup */ + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing color map\n"); + if (!miCreateDefColormap(pScreen)) return FALSE; + if (!xf86HandleColormaps(pScreen, 256, info->dac6bits ? 6 : 8, + RADEONLoadPalette, NULL, + CMAP_PALETTED_TRUECOLOR +#if 0 /* This option messes up text mode! (eich@suse.de) */ + | CMAP_LOAD_EVEN_IF_OFFSCREEN +#endif + | CMAP_RELOAD_ON_MODE_SWITCH)) return FALSE; + /* Note unused options */ if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); - RADEONTRACE(("RADEONScreenInit finished\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONScreenInit finished\n"); return TRUE; } /* Write memory mapping registers */ -static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, +void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -4249,9 +3762,14 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, unsigned char *RADEONMMIO = info->MMIO; int timeout; - RADEONTRACE(("RADEONRestoreMemMapRegisters() : \n")); - RADEONTRACE((" MC_FB_LOCATION : 0x%08lx\n", restore->mc_fb_location)); - RADEONTRACE((" MC_AGP_LOCATION : 0x%08lx\n", restore->mc_agp_location)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "RADEONRestoreMemMapRegisters() : \n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_FB_LOCATION : 0x%08x\n", + (unsigned)restore->mc_fb_location); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + " MC_AGP_LOCATION : 0x%08x\n", + (unsigned)restore->mc_agp_location); /* Write memory mapping registers only if their value change * since we must ensure no access is done while they are @@ -4262,7 +3780,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, CARD32 crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl=0, ov0_scale_cntl; CARD32 old_mc_status, status_idle; - RADEONTRACE((" Map Changed ! Applying ...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + " Map Changed ! Applying ...\n"); /* Make sure engine is idle. We assume the CCE is stopped * at this point @@ -4335,7 +3854,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, /* Make sure map fully reached the chip */ (void)INREG(RADEON_MC_FB_LOCATION); - RADEONTRACE((" Map applied, resetting engine ...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + " Map applied, resetting engine ...\n"); /* Reset the engine and HDP */ RADEONEngineReset(pScrn); @@ -4372,7 +3892,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, } } - RADEONTRACE(("Updating display base addresses...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Updating display base addresses...\n"); OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); if (pRADEONEnt->HasCRTC2) @@ -4383,7 +3904,8 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, /* More paranoia delays, wait 100ms */ usleep(100000); - RADEONTRACE(("Memory map updated.\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Memory map updated.\n"); } #ifdef XF86DRI @@ -4392,21 +3914,19 @@ static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 fb, agp; - int fb_loc_changed; fb = INREG(RADEON_MC_FB_LOCATION); agp = INREG(RADEON_MC_AGP_LOCATION); - fb_loc_changed = (fb != info->mc_fb_location); - if (fb_loc_changed || agp != info->mc_agp_location) { + if (fb != info->mc_fb_location || agp != info->mc_agp_location) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI init changed memory map, adjusting ...\n"); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - " MC_FB_LOCATION was: 0x%08lx is: 0x%08lx\n", - info->mc_fb_location, fb); + " MC_FB_LOCATION was: 0x%08x is: 0x%08x\n", + (unsigned)info->mc_fb_location, (unsigned)fb); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - " MC_AGP_LOCATION was: 0x%08lx is: 0x%08lx\n", - info->mc_agp_location, agp); + " MC_AGP_LOCATION was: 0x%08x is: 0x%08x\n", + (unsigned)info->mc_agp_location, (unsigned)agp); info->mc_fb_location = fb; info->mc_agp_location = agp; info->fbLocation = (save->mc_fb_location & 0xffff) << 16; @@ -4417,9 +3937,8 @@ static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONInitMemMapRegisters(pScrn, save, info); - /* If MC_FB_LOCATION was changed, adjust the various offsets */ - if (fb_loc_changed) - RADEONRestoreMemMapRegisters(pScrn, save); + /* Adjust the various offsets */ + RADEONRestoreMemMapRegisters(pScrn, save); } #ifdef USE_EXA @@ -4447,7 +3966,7 @@ static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) #endif /* Write common registers */ -static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, +void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -4472,55 +3991,62 @@ static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, * CRT are connected. */ if (pRADEONEnt->HasCRTC2 && - !info->IsSwitching && info->ChipFamily != CHIP_FAMILY_R200 && !IS_R300_VARIANT) { CARD32 tmp; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - if (pRADEONEnt->HasSecondary || info->MergedFB) { - tmp = INREG(RADEON_DAC_CNTL2); - OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); - usleep(100000); - } + tmp = INREG(RADEON_DAC_CNTL2); + OUTREG(RADEON_DAC_CNTL2, tmp & ~RADEON_DAC2_DAC_CLK_SEL); + usleep(100000); } } -/* Write miscellaneous registers which might have been destroyed by an fbdevHW - * call - */ -static void RADEONRestoreFBDevRegisters(ScrnInfoPtr pScrn, - RADEONSavePtr restore) +void RADEONRestoreDACRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore) { -#ifdef XF86DRI RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; - /* Restore register for vertical blank interrupts */ - if (info->irq) { - OUTREG(RADEON_GEN_INT_CNTL, restore->gen_int_cntl); - } + if (IS_R300_VARIANT) + OUTREGP(RADEON_GPIOPAD_A, restore->gpiopad_a, ~1); - /* Restore registers for page flipping */ - if (info->allowPageFlip) { - OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); - if (pRADEONEnt->HasCRTC2) { - OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); - } + OUTREGP(RADEON_DAC_CNTL, + restore->dac_cntl, + RADEON_DAC_RANGE_CNTL | + RADEON_DAC_BLANKING); + + OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); + + if ((info->ChipFamily != CHIP_FAMILY_RADEON) && + (info->ChipFamily != CHIP_FAMILY_R200)) + OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); + + if ((info->ChipFamily == CHIP_FAMILY_R200) || + IS_R300_VARIANT) { + OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl); + } else { + OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); } -#endif + + OUTREG(RADEON_DAC_MACRO_CNTL, restore->dac_macro_cntl); + + /* R200 DAC connected via DVO */ + if (info->ChipFamily == CHIP_FAMILY_R200) + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); } /* Write CRTC registers */ -static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, +void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - RADEONTRACE(("Programming CRTC1, offset: 0x%08lx\n", - restore->crtc_offset)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Programming CRTC1, offset: 0x%08x\n", + (unsigned)restore->crtc_offset); /* We prevent the CRTC from hitting the memory controller until * fully programmed @@ -4534,11 +4060,6 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, RADEON_CRTC_HSYNC_DIS | RADEON_CRTC_DISPLAY_DIS); - OUTREGP(RADEON_DAC_CNTL, - restore->dac_cntl, - RADEON_DAC_RANGE_CNTL | - RADEON_DAC_BLANKING); - OUTREG(RADEON_CRTC_H_TOTAL_DISP, restore->crtc_h_total_disp); OUTREG(RADEON_CRTC_H_SYNC_STRT_WID, restore->crtc_h_sync_strt_wid); OUTREG(RADEON_CRTC_V_TOTAL_DISP, restore->crtc_v_total_disp); @@ -4549,8 +4070,11 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, OUTREG(RADEON_FP_CRTC_H_TOTAL_DISP, restore->fp_crtc_h_total_disp); OUTREG(RADEON_FP_CRTC_V_TOTAL_DISP, restore->fp_crtc_v_total_disp); - OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); + if (IS_R300_VARIANT) + OUTREG(R300_CRTC_TILE_X0_Y0, restore->crtc_tile_x0_y0); OUTREG(RADEON_CRTC_OFFSET_CNTL, restore->crtc_offset_cntl); + OUTREG(RADEON_CRTC_OFFSET, restore->crtc_offset); + 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); @@ -4566,42 +4090,24 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn, } /* Write CRTC2 registers */ -static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, +void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - CARD32 crtc2_gen_cntl; + /* CARD32 crtc2_gen_cntl;*/ - RADEONTRACE(("Programming CRTC2, offset: 0x%08lx\n", - restore->crtc2_offset)); - - crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) & - (RADEON_CRTC2_VSYNC_DIS | - RADEON_CRTC2_HSYNC_DIS | - RADEON_CRTC2_DISP_DIS); - crtc2_gen_cntl |= restore->crtc2_gen_cntl; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Programming CRTC2, offset: 0x%08x\n", + (unsigned)restore->crtc2_offset); /* We prevent the CRTC from hitting the memory controller until * fully programmed */ OUTREG(RADEON_CRTC2_GEN_CNTL, - crtc2_gen_cntl | RADEON_CRTC2_DISP_REQ_EN_B); - - OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); - - //OUTREG(RADEON_TV_DAC_CNTL, 0x00280203); - if ((info->ChipFamily != CHIP_FAMILY_RADEON) && - (info->ChipFamily != CHIP_FAMILY_R200)) - OUTREG (RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); - - if ((info->ChipFamily == CHIP_FAMILY_R200) || - IS_R300_VARIANT) { - OUTREG(RADEON_DISP_OUTPUT_CNTL, restore->disp_output_cntl); - OUTREG(RADEON_DISP_TV_OUT_CNTL, restore->disp_tv_out_cntl); - } else { - OUTREG(RADEON_DISP_HW_DEBUG, restore->disp_hw_debug); - } + restore->crtc2_gen_cntl | RADEON_CRTC2_VSYNC_DIS | + RADEON_CRTC2_HSYNC_DIS | RADEON_CRTC2_DISP_DIS | + RADEON_CRTC2_DISP_REQ_EN_B); OUTREG(RADEON_CRTC2_H_TOTAL_DISP, restore->crtc2_h_total_disp); OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, restore->crtc2_h_sync_strt_wid); @@ -4611,17 +4117,26 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn, OUTREG(RADEON_FP_H2_SYNC_STRT_WID, restore->fp_h2_sync_strt_wid); OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp_v2_sync_strt_wid); - OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); + if (IS_R300_VARIANT) + OUTREG(R300_CRTC2_TILE_X0_Y0, restore->crtc2_tile_x0_y0); OUTREG(RADEON_CRTC2_OFFSET_CNTL, restore->crtc2_offset_cntl); + OUTREG(RADEON_CRTC2_OFFSET, restore->crtc2_offset); + OUTREG(RADEON_CRTC2_PITCH, restore->crtc2_pitch); OUTREG(RADEON_DISP2_MERGE_CNTL, restore->disp2_merge_cntl); - OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + if (info->ChipFamily == CHIP_FAMILY_RS400) { + OUTREG(RADEON_RS480_UNK_e30, restore->rs480_unk_e30); + OUTREG(RADEON_RS480_UNK_e34, restore->rs480_unk_e34); + OUTREG(RADEON_RS480_UNK_e38, restore->rs480_unk_e38); + OUTREG(RADEON_RS480_UNK_e3c, restore->rs480_unk_e3c); + } + OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl); } -/* Write flat panel registers */ -static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +/* Write TMDS registers */ +void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); @@ -4629,8 +4144,6 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) OUTREG(RADEON_TMDS_PLL_CNTL, restore->tmds_pll_cntl); OUTREG(RADEON_TMDS_TRANSMITTER_CNTL,restore->tmds_transmitter_cntl); - OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch); - OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch); OUTREG(RADEON_FP_GEN_CNTL, restore->fp_gen_cntl); /* old AIW Radeon has some BIOS initialization problem @@ -4640,7 +4153,38 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) OUTREG(RADEON_GRPH_BUFFER_CNTL, INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000); +} + +/* Write FP2 registers */ +void RADEONRestoreFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl); + +} + +/* Write RMX registers */ +void RADEONRestoreRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_FP_HORZ_STRETCH, restore->fp_horz_stretch); + OUTREG(RADEON_FP_VERT_STRETCH, restore->fp_vert_stretch); + +} + +/* Write LVDS registers */ +void RADEONRestoreLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + if (info->IsMobility) { + OUTREG(RADEON_LVDS_GEN_CNTL, restore->lvds_gen_cntl); + /*OUTREG(RADEON_LVDS_PLL_CNTL, restore->lvds_pll_cntl);*/ 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); @@ -4648,6 +4192,262 @@ static void RADEONRestoreFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) } +/* Write to TV FIFO RAM */ +static void RADEONWriteTVFIFO(ScrnInfoPtr pScrn, CARD16 addr, + CARD32 value) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp; + int i = 0; + + OUTREG(RADEON_TV_HOST_WRITE_DATA, value); + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr); + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT); + + do { + tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL); + if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0) + break; + i++; + } + while (i < 10000); + /*while ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0);*/ + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0); +} + +/* Read from TV FIFO RAM */ +static CARD32 RADEONReadTVFIFO(ScrnInfoPtr pScrn, CARD16 addr) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp; + int i = 0; + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr); + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD); + + do { + tmp = INREG(RADEON_TV_HOST_RD_WT_CNTL); + if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0) + break; + i++; + } + while (i < 10000); + /*while ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0);*/ + + OUTREG(RADEON_TV_HOST_RD_WT_CNTL, 0); + + return INREG(RADEON_TV_HOST_READ_DATA); +} + +/* Get FIFO addresses of horizontal & vertical code timing tables from + * settings of uv_adr register. + */ +static CARD16 RADEONGetHTimingTablesAddr(CARD32 tv_uv_adr) +{ + CARD16 hTable; + + switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) { + case 0: + hTable = RADEON_TV_MAX_FIFO_ADDR_INTERNAL; + break; + case 1: + hTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2; + break; + case 2: + hTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2; + break; + default: + /* Of course, this should never happen */ + hTable = 0; + break; + } + return hTable; +} + +static CARD16 RADEONGetVTimingTablesAddr(CARD32 tv_uv_adr) +{ + CARD16 vTable; + + switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) { + case 0: + vTable = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1; + break; + case 1: + vTable = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1; + break; + case 2: + vTable = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1; + break; + default: + /* Of course, this should never happen */ + vTable = 0; + break; + } + return vTable; +} + +/* Restore horizontal/vertical timing code tables */ +void RADEONRestoreTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 hTable; + CARD16 vTable; + CARD32 tmp; + unsigned i; + + OUTREG(RADEON_TV_UV_ADR, restore->tv_uv_adr); + hTable = RADEONGetHTimingTablesAddr(restore->tv_uv_adr); + vTable = RADEONGetVTimingTablesAddr(restore->tv_uv_adr); + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, hTable--) { + tmp = ((CARD32)restore->h_code_timing[ i ] << 14) | ((CARD32)restore->h_code_timing[ i + 1 ]); + RADEONWriteTVFIFO(pScrn, hTable, tmp); + if (restore->h_code_timing[ i ] == 0 || restore->h_code_timing[ i + 1 ] == 0) + break; + } + + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, vTable++) { + tmp = ((CARD32)restore->v_code_timing[ i + 1 ] << 14) | ((CARD32)restore->v_code_timing[ i ]); + RADEONWriteTVFIFO(pScrn, vTable, tmp); + if (restore->v_code_timing[ i ] == 0 || restore->v_code_timing[ i + 1 ] == 0) + break; + } +} + +/* restore TV PLLs */ +static void RADEONRestoreTVPLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL); + OUTPLL(pScrn, RADEON_TV_PLL_CNTL, restore->tv_pll_cntl); + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET); + + RADEONWaitPLLLock(pScrn, 200, 800, 135); + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET); + + RADEONWaitPLLLock(pScrn, 300, 160, 27); + RADEONWaitPLLLock(pScrn, 200, 800, 135); + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~0xf); + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL); + + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK); + OUTPLLP(pScrn, RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP); +} + +/* Restore TV horizontal/vertical settings */ +static void RADEONRestoreTVHVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_TV_RGB_CNTL, restore->tv_rgb_cntl); + + OUTREG(RADEON_TV_HTOTAL, restore->tv_htotal); + OUTREG(RADEON_TV_HDISP, restore->tv_hdisp); + OUTREG(RADEON_TV_HSTART, restore->tv_hstart); + + OUTREG(RADEON_TV_VTOTAL, restore->tv_vtotal); + OUTREG(RADEON_TV_VDISP, restore->tv_vdisp); + + OUTREG(RADEON_TV_FTOTAL, restore->tv_ftotal); + + OUTREG(RADEON_TV_VSCALER_CNTL1, restore->tv_vscaler_cntl1); + OUTREG(RADEON_TV_VSCALER_CNTL2, restore->tv_vscaler_cntl2); + + OUTREG(RADEON_TV_Y_FALL_CNTL, restore->tv_y_fall_cntl); + OUTREG(RADEON_TV_Y_RISE_CNTL, restore->tv_y_rise_cntl); + OUTREG(RADEON_TV_Y_SAW_TOOTH_CNTL, restore->tv_y_saw_tooth_cntl); +} + +/* restore TV RESTART registers */ +void RADEONRestoreTVRestarts(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_TV_FRESTART, restore->tv_frestart); + OUTREG(RADEON_TV_HRESTART, restore->tv_hrestart); + OUTREG(RADEON_TV_VRESTART, restore->tv_vrestart); +} + +/* restore tv standard & output muxes */ +static void RADEONRestoreTVOutputStd(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + OUTREG(RADEON_TV_SYNC_CNTL, restore->tv_sync_cntl); + + OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl); + + OUTREG(RADEON_TV_MODULATOR_CNTL1, restore->tv_modulator_cntl1); + OUTREG(RADEON_TV_MODULATOR_CNTL2, restore->tv_modulator_cntl2); + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, restore->tv_pre_dac_mux_cntl); + + OUTREG(RADEON_TV_CRC_CNTL, restore->tv_crc_cntl); +} + +/* Restore TV out regs */ +void RADEONRestoreTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr restore) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + ErrorF("Entering Restore TV\n"); + + OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl + | RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST + | RADEON_TV_FIFO_ASYNC_RST)); + + /* Temporarily turn the TV DAC off */ + OUTREG(RADEON_TV_DAC_CNTL, ((restore->tv_dac_cntl & ~RADEON_TV_DAC_NBLANK) + | RADEON_TV_DAC_BGSLEEP + | RADEON_TV_DAC_RDACPD + | RADEON_TV_DAC_GDACPD + | RADEON_TV_DAC_BDACPD)); + + ErrorF("Restore TV PLL\n"); + RADEONRestoreTVPLLRegisters(pScrn, restore); + + ErrorF("Restore TVHV\n"); + RADEONRestoreTVHVRegisters(pScrn, restore); + + OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl + | RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST)); + + ErrorF("Restore TV Restarts\n"); + RADEONRestoreTVRestarts(pScrn, restore); + + ErrorF("Restore Timing Tables\n"); + RADEONRestoreTVTimingTables(pScrn, restore); + + + OUTREG(RADEON_TV_MASTER_CNTL, (restore->tv_master_cntl + | RADEON_TV_ASYNC_RST)); + + ErrorF("Restore TV standard\n"); + RADEONRestoreTVOutputStd(pScrn, restore); + + OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl); + + OUTREG(RADEON_TV_GAIN_LIMIT_SETTINGS, restore->tv_gain_limit_settings); + OUTREG(RADEON_TV_LINEAR_GAIN_SETTINGS, restore->tv_linear_gain_settings); + + OUTREG(RADEON_TV_DAC_CNTL, restore->tv_dac_cntl); + + ErrorF("Leaving Restore TV\n"); +} + static void RADEONPLLWaitForReadUpdateComplete(ScrnInfoPtr pScrn) { int i = 0; @@ -4694,12 +4494,81 @@ static void RADEONPLL2WriteUpdate(ScrnInfoPtr pScrn) ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); } +static CARD8 RADEONComputePLLGain(CARD16 reference_freq, CARD16 ref_div, + CARD16 fb_div) +{ + unsigned vcoFreq; + + if (!ref_div) + return 1; + + vcoFreq = ((unsigned)reference_freq * fb_div) / ref_div; + + /* + * This is horribly crude: the VCO frequency range is divided into + * 3 parts, each part having a fixed PLL gain value. + */ + if (vcoFreq >= 30000) + /* + * [300..max] MHz : 7 + */ + return 7; + else if (vcoFreq >= 18000) + /* + * [180..300) MHz : 4 + */ + return 4; + else + /* + * [0..180) MHz : 1 + */ + return 1; +} + +/* Wait for PLLs to lock */ +static void RADEONWaitPLLLock(ScrnInfoPtr pScrn, unsigned nTests, + unsigned nWaitLoops, unsigned cntThreshold) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 savePLLTest; + unsigned i; + unsigned j; + + OUTREG(RADEON_TEST_DEBUG_MUX, (INREG(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100); + + savePLLTest = INPLL(pScrn, RADEON_PLL_TEST_CNTL); + + OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest & ~RADEON_PLL_MASK_READ_B); + + /* XXX: these should probably be OUTPLL to avoid various PLL errata */ + + OUTREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL); + + for (i = 0; i < nTests; i++) { + OUTREG8(RADEON_CLOCK_CNTL_DATA + 3, 0); + + for (j = 0; j < nWaitLoops; j++) + if (INREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cntThreshold) + break; + } + + OUTPLL(pScrn, RADEON_PLL_TEST_CNTL, savePLLTest); + + OUTREG(RADEON_TEST_DEBUG_MUX, INREG(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff); +} + /* Write PLL registers */ -static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, - RADEONSavePtr restore) +void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + CARD8 pllGain; + + pllGain = RADEONComputePLLGain(info->pll.reference_freq, + restore->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + restore->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK); if (info->IsMobility) { /* A temporal workaround for the occational blanking on certain laptop panels. @@ -4727,10 +4596,12 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEON_PPLL_CNTL, RADEON_PPLL_RESET | RADEON_PPLL_ATOMIC_UPDATE_EN - | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN, + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | ((CARD32)pllGain << RADEON_PPLL_PVG_SHIFT), ~(RADEON_PPLL_RESET | RADEON_PPLL_ATOMIC_UPDATE_EN - | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); + | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN + | RADEON_PPLL_PVG_MASK)); OUTREGP(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_DIV_SEL, @@ -4738,7 +4609,8 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, RADEONPllErrataAfterIndex(info); if (IS_R300_VARIANT || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + (info->ChipFamily == CHIP_FAMILY_RS300) || + (info->ChipFamily == CHIP_FAMILY_RS400)) { if (restore->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { /* When restoring console mode, use saved PPLL_REF_DIV * setting. @@ -4778,28 +4650,42 @@ static void RADEONRestorePLLRegisters(ScrnInfoPtr pScrn, | RADEON_PPLL_ATOMIC_UPDATE_EN | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); - RADEONTRACE(("Wrote: 0x%08x 0x%08x 0x%08lx (0x%08x)\n", - restore->ppll_ref_div, - restore->ppll_div_3, - restore->htotal_cntl, - INPLL(pScrn, RADEON_PPLL_CNTL))); - RADEONTRACE(("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)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + restore->ppll_ref_div, + restore->ppll_div_3, + (unsigned)restore->htotal_cntl, + INPLL(pScrn, RADEON_PPLL_CNTL)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "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); usleep(50000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, + /* OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, RADEON_VCLK_SRC_SEL_PPLLCLK, - ~(RADEON_VCLK_SRC_SEL_MASK)); + ~(RADEON_VCLK_SRC_SEL_MASK));*/ + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, restore->vclk_ecp_cntl); + + ErrorF("finished PLL1\n"); + } /* Write PLL2 registers */ -static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, - RADEONSavePtr restore) +void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, + RADEONSavePtr restore) { + RADEONInfoPtr info = RADEONPTR(pScrn); + CARD8 pllGain; + + pllGain = RADEONComputePLLGain(info->pll.reference_freq, + restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK); + + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, RADEON_PIX2CLK_SRC_SEL_CPUCLK, ~(RADEON_PIX2CLK_SRC_SEL_MASK)); @@ -4808,10 +4694,11 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, RADEON_P2PLL_CNTL, RADEON_P2PLL_RESET | RADEON_P2PLL_ATOMIC_UPDATE_EN - | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN, + | ((CARD32)pllGain << RADEON_P2PLL_PVG_SHIFT), ~(RADEON_P2PLL_RESET | RADEON_P2PLL_ATOMIC_UPDATE_EN - | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN)); + | RADEON_P2PLL_PVG_MASK)); + OUTPLLP(pScrn, RADEON_P2PLL_REF_DIV, restore->p2pll_ref_div, @@ -4834,24 +4721,30 @@ static void RADEONRestorePLL2Registers(ScrnInfoPtr pScrn, 0, ~(RADEON_P2PLL_RESET | RADEON_P2PLL_SLEEP - | RADEON_P2PLL_ATOMIC_UPDATE_EN - | RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN)); - - RADEONTRACE(("Wrote: 0x%08lx 0x%08lx 0x%08lx (0x%08x)\n", - restore->p2pll_ref_div, - restore->p2pll_div_0, - restore->htotal_cntl2, - INPLL(pScrn, RADEON_P2PLL_CNTL))); - RADEONTRACE(("Wrote: rd=%ld, fd=%ld, pd=%ld\n", - restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, - restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, - (restore->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >>16)); + | RADEON_P2PLL_ATOMIC_UPDATE_EN)); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", + (unsigned)restore->p2pll_ref_div, + (unsigned)restore->p2pll_div_0, + (unsigned)restore->htotal_cntl2, + INPLL(pScrn, RADEON_P2PLL_CNTL)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Wrote2: rd=%u, fd=%u, pd=%u\n", + (unsigned)restore->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, + (unsigned)restore->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, + (unsigned)((restore->p2pll_div_0 & + RADEON_P2PLL_POST0_DIV_MASK) >>16)); usleep(5000); /* Let the clock to lock */ - OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, + /*OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, - ~(RADEON_PIX2CLK_SRC_SEL_MASK)); + ~(RADEON_PIX2CLK_SRC_SEL_MASK));*/ + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, restore->pixclks_cntl); + + ErrorF("finished PLL2\n"); + } @@ -5018,156 +4911,24 @@ void RADEONChangeSurfaces(ScrnInfoPtr pScrn) unsigned int surf_info = swap_pattern; unsigned char *RADEONMMIO = info->MMIO; /* we don't need anything like WaitForFifo, no? */ - if (!info->IsSecondary) { - if (info->tilingEnabled) { - if (IS_R300_VARIANT) - surf_info |= (width_bytes / 8) | color_pattern; - else - surf_info |= (width_bytes / 16) | color_pattern; - } - OUTREG(RADEON_SURFACE0_INFO, surf_info); - OUTREG(RADEON_SURFACE0_LOWER_BOUND, 0); - OUTREG(RADEON_SURFACE0_UPPER_BOUND, bufferSize - 1); + if (info->tilingEnabled) { + if (IS_R300_VARIANT) + surf_info |= (width_bytes / 8) | color_pattern; + else + surf_info |= (width_bytes / 16) | color_pattern; + } + OUTREG(RADEON_SURFACE0_INFO, surf_info); + OUTREG(RADEON_SURFACE0_LOWER_BOUND, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND, bufferSize - 1); /* xf86DrvMsg(pScrn->scrnIndex, X_INFO, "surface0 set to %x, LB 0x%x UB 0x%x\n", surf_info, 0, bufferSize - 1024);*/ - } } /* Update surface images */ RADEONSaveSurfaces(pScrn, &info->ModeReg); } -#if 0 -/* Write palette data */ -static void RADEONRestorePalette(ScrnInfoPtr pScrn, RADEONSavePtr restore) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - int i; - - if (!restore->palette_valid) return; - - PAL_SELECT(1); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette2[i]); - } - - PAL_SELECT(0); - OUTPAL_START(0); - for (i = 0; i < 256; i++) { - RADEONWaitForFifo(pScrn, 32); /* delay */ - OUTPAL_NEXT_CARD32(restore->palette[i]); - } -} -#endif - -/* Write out state to define a new video mode */ -static void RADEONRestoreMode(ScrnInfoPtr pScrn, RADEONSavePtr restore) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONController* pCRTC1 = pRADEONEnt->Controller[0]; - RADEONController* pCRTC2 = pRADEONEnt->Controller[1]; - RADEONConnector *pPort; - RADEONTRACE(("RADEONRestoreMode(%p)\n", restore)); - - /* For Non-dual head card, we don't have private field in the Entity */ - if (!pRADEONEnt->HasCRTC2) { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - return; - } - - /* Disable all outputs at initial mode set. the ones we want will - get set by RADEONEnableDisplay() - */ - if (!info->IsSwitching && !info->IsSecondary) - RADEONDisableDisplays(pScrn); - - /* When changing mode with Dual-head card, care must be taken for - * the special order in setting registers. CRTC2 has to be set - * before changing CRTC_EXT register. In the dual-head setup, X - * server calls this routine twice with primary and secondary pScrn - * pointers respectively. The calls can come with different - * order. Regardless the order of X server issuing the calls, we - * have to ensure we set registers in the right order!!! Otherwise - * we may get a blank screen. - * - * We always restore MemMap first, the saverec should be up to date - * in all cases - */ - if (info->IsSwitching) { - if (info->IsSecondary) { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC2->IsActive = TRUE; - } - } else { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - if (pCRTC2->binding == 1) { - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - } - - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC1->IsActive = TRUE; - } - if (pCRTC2->binding == 1) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC2->IsActive = TRUE; - } - } - } - } else { - RADEONRestoreMemMapRegisters(pScrn, restore); - RADEONRestoreCommonRegisters(pScrn, restore); - if ((pCRTC2->binding == 1) || pRADEONEnt->HasSecondary) { - RADEONRestoreCrtc2Registers(pScrn, restore); - RADEONRestorePLL2Registers(pScrn, restore); - } - - RADEONRestoreCrtcRegisters(pScrn, restore); - RADEONRestorePLLRegisters(pScrn, restore); - RADEONRestoreFPRegisters(pScrn, restore); - pPort = RADEONGetCrtcConnector(pScrn, 1); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC1->IsActive = TRUE; - } - if ((pCRTC2->binding == 1) || pRADEONEnt->HasSecondary) { - pPort = RADEONGetCrtcConnector(pScrn, 2); - if (pPort) { - RADEONEnableDisplay(pScrn, pPort, TRUE); - pCRTC2->IsActive = TRUE; - } - } - } - -#if 0 - RADEONRestorePalette(pScrn, &info->SavedReg); -#endif -} - /* Read memory map */ static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { @@ -5203,29 +4964,6 @@ static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->grph2_buffer_cntl = INREG(RADEON_GRPH2_BUFFER_CNTL); } -/* Read miscellaneous registers which might be destroyed by an fbdevHW call */ -static void RADEONSaveFBDevRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) -{ -#ifdef XF86DRI - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - unsigned char *RADEONMMIO = info->MMIO; - - /* Save register for vertical blank interrupts */ - if (info->irq) { - save->gen_int_cntl = INREG(RADEON_GEN_INT_CNTL); - } - - /* Save registers for page flipping */ - if (info->allowPageFlip) { - save->crtc_offset_cntl = INREG(RADEON_CRTC_OFFSET_CNTL); - if (pRADEONEnt->HasCRTC2) { - save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); - } - } -#endif -} - /* Read CRTC registers */ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) { @@ -5234,7 +4972,6 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); save->crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); - save->dac_cntl = INREG(RADEON_DAC_CNTL); save->crtc_h_total_disp = INREG(RADEON_CRTC_H_TOTAL_DISP); save->crtc_h_sync_strt_wid = INREG(RADEON_CRTC_H_SYNC_STRT_WID); save->crtc_v_total_disp = INREG(RADEON_CRTC_V_TOTAL_DISP); @@ -5251,12 +4988,39 @@ static void RADEONSaveCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->disp_merge_cntl = INREG(RADEON_DISP_MERGE_CNTL); save->crtc_more_cntl = INREG(RADEON_CRTC_MORE_CNTL); + if (IS_R300_VARIANT) + save->crtc_tile_x0_y0 = INREG(R300_CRTC_TILE_X0_Y0); + 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); } + + /* track if the crtc is enabled for text restore */ + if (save->crtc_ext_cntl & RADEON_CRTC_DISPLAY_DIS) + info->crtc_on = FALSE; + else + info->crtc_on = TRUE; + +} + +/* Read DAC registers */ +static void RADEONSaveDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + save->dac_cntl = INREG(RADEON_DAC_CNTL); + save->dac2_cntl = INREG(RADEON_DAC_CNTL2); + save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + save->disp_tv_out_cntl = INREG(RADEON_DISP_TV_OUT_CNTL); + save->disp_hw_debug = INREG(RADEON_DISP_HW_DEBUG); + save->dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + save->gpiopad_a = INREG(RADEON_GPIOPAD_A); + } /* Read flat panel registers */ @@ -5289,12 +5053,6 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - save->dac2_cntl = INREG(RADEON_DAC_CNTL2); - save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); - save->disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); - save->disp_tv_out_cntl = INREG(RADEON_DISP_TV_OUT_CNTL); - save->disp_hw_debug = INREG (RADEON_DISP_HW_DEBUG); - save->crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); save->crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); save->crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); @@ -5304,10 +5062,120 @@ static void RADEONSaveCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->crtc2_offset_cntl = INREG(RADEON_CRTC2_OFFSET_CNTL); save->crtc2_pitch = INREG(RADEON_CRTC2_PITCH); + if (IS_R300_VARIANT) + save->crtc2_tile_x0_y0 = INREG(R300_CRTC2_TILE_X0_Y0); + save->fp_h2_sync_strt_wid = INREG (RADEON_FP_H2_SYNC_STRT_WID); save->fp_v2_sync_strt_wid = INREG (RADEON_FP_V2_SYNC_STRT_WID); + if (info->ChipFamily == CHIP_FAMILY_RS400) { + save->rs480_unk_e30 = INREG(RADEON_RS480_UNK_e30); + save->rs480_unk_e34 = INREG(RADEON_RS480_UNK_e34); + save->rs480_unk_e38 = INREG(RADEON_RS480_UNK_e38); + save->rs480_unk_e3c = INREG(RADEON_RS480_UNK_e3c); + } + save->disp2_merge_cntl = INREG(RADEON_DISP2_MERGE_CNTL); + + /* track if the crtc is enabled for text restore */ + if (save->crtc2_gen_cntl & RADEON_CRTC2_DISP_DIS) + info->crtc2_on = FALSE; + else + info->crtc2_on = TRUE; + +} + +/* Save horizontal/vertical timing code tables */ +static void RADEONSaveTVTimingTables(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD16 hTable; + CARD16 vTable; + CARD32 tmp; + unsigned i; + + save->tv_uv_adr = INREG(RADEON_TV_UV_ADR); + hTable = RADEONGetHTimingTablesAddr(save->tv_uv_adr); + vTable = RADEONGetVTimingTablesAddr(save->tv_uv_adr); + + /* + * Reset FIFO arbiter in order to be able to access FIFO RAM + */ + + OUTREG(RADEON_TV_MASTER_CNTL, (RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST + | RADEON_RESTART_PHASE_FIX + | RADEON_CRT_FIFO_CE_EN + | RADEON_TV_FIFO_CE_EN + | RADEON_TV_ON)); + + /*OUTREG(RADEON_TV_MASTER_CNTL, save->tv_master_cntl | RADEON_TV_ON);*/ + + ErrorF("saveTimingTables: reading timing tables\n"); + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2) { + tmp = RADEONReadTVFIFO(pScrn, hTable--); + save->h_code_timing[ i ] = (CARD16)((tmp >> 14) & 0x3fff); + save->h_code_timing[ i + 1 ] = (CARD16)(tmp & 0x3fff); + + if (save->h_code_timing[ i ] == 0 || save->h_code_timing[ i + 1 ] == 0) + break; + } + + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2) { + tmp = RADEONReadTVFIFO(pScrn, vTable++); + save->v_code_timing[ i ] = (CARD16)(tmp & 0x3fff); + save->v_code_timing[ i + 1 ] = (CARD16)((tmp >> 14) & 0x3fff); + + if (save->v_code_timing[ i ] == 0 || save->v_code_timing[ i + 1 ] == 0) + break; + } +} + +/* read TV regs */ +static void RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + + ErrorF("Entering TV Save\n"); + + save->tv_crc_cntl = INREG(RADEON_TV_CRC_CNTL); + save->tv_frestart = INREG(RADEON_TV_FRESTART); + save->tv_hrestart = INREG(RADEON_TV_HRESTART); + save->tv_vrestart = INREG(RADEON_TV_VRESTART); + save->tv_gain_limit_settings = INREG(RADEON_TV_GAIN_LIMIT_SETTINGS); + save->tv_hdisp = INREG(RADEON_TV_HDISP); + save->tv_hstart = INREG(RADEON_TV_HSTART); + save->tv_htotal = INREG(RADEON_TV_HTOTAL); + save->tv_linear_gain_settings = INREG(RADEON_TV_LINEAR_GAIN_SETTINGS); + save->tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); + save->tv_rgb_cntl = INREG(RADEON_TV_RGB_CNTL); + save->tv_modulator_cntl1 = INREG(RADEON_TV_MODULATOR_CNTL1); + save->tv_modulator_cntl2 = INREG(RADEON_TV_MODULATOR_CNTL2); + save->tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + save->tv_sync_cntl = INREG(RADEON_TV_SYNC_CNTL); + save->tv_timing_cntl = INREG(RADEON_TV_TIMING_CNTL); + save->tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + save->tv_upsamp_and_gain_cntl = INREG(RADEON_TV_UPSAMP_AND_GAIN_CNTL); + save->tv_vdisp = INREG(RADEON_TV_VDISP); + save->tv_ftotal = INREG(RADEON_TV_FTOTAL); + save->tv_vscaler_cntl1 = INREG(RADEON_TV_VSCALER_CNTL1); + save->tv_vscaler_cntl2 = INREG(RADEON_TV_VSCALER_CNTL2); + save->tv_vtotal = INREG(RADEON_TV_VTOTAL); + save->tv_y_fall_cntl = INREG(RADEON_TV_Y_FALL_CNTL); + save->tv_y_rise_cntl = INREG(RADEON_TV_Y_RISE_CNTL); + save->tv_y_saw_tooth_cntl = INREG(RADEON_TV_Y_SAW_TOOTH_CNTL); + + save->tv_pll_cntl = INPLL(pScrn, RADEON_TV_PLL_CNTL); + save->tv_pll_cntl1 = INPLL(pScrn, RADEON_TV_PLL_CNTL1); + + ErrorF("Save TV timing tables\n"); + + RADEONSaveTVTimingTables(pScrn, save); + + ErrorF("TV Save done\n"); } /* Read PLL registers */ @@ -5316,16 +5184,18 @@ static void RADEONSavePLLRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) save->ppll_ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV); save->ppll_div_3 = INPLL(pScrn, RADEON_PPLL_DIV_3); save->htotal_cntl = INPLL(pScrn, RADEON_HTOTAL_CNTL); - save->vclk_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); - - RADEONTRACE(("Read: 0x%08x 0x%08x 0x%08lx\n", - save->ppll_ref_div, - save->ppll_div_3, - save->htotal_cntl)); - RADEONTRACE(("Read: rd=%d, fd=%d, pd=%d\n", - save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, - save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, - (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16)); + save->vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: 0x%08x 0x%08x 0x%08x\n", + save->ppll_ref_div, + save->ppll_div_3, + (unsigned)save->htotal_cntl); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: rd=%d, fd=%d, pd=%d\n", + save->ppll_ref_div & RADEON_PPLL_REF_DIV_MASK, + save->ppll_div_3 & RADEON_PPLL_FB3_DIV_MASK, + (save->ppll_div_3 & RADEON_PPLL_POST3_DIV_MASK) >> 16); } /* Read PLL registers */ @@ -5336,14 +5206,17 @@ static void RADEONSavePLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save) save->htotal_cntl2 = INPLL(pScrn, RADEON_HTOTAL2_CNTL); save->pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); - RADEONTRACE(("Read: 0x%08lx 0x%08lx 0x%08lx\n", - save->p2pll_ref_div, - save->p2pll_div_0, - save->htotal_cntl2)); - RADEONTRACE(("Read: rd=%ld, fd=%ld, pd=%ld\n", - save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, - save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK, - (save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) >> 16)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: 0x%08x 0x%08x 0x%08x\n", + (unsigned)save->p2pll_ref_div, + (unsigned)save->p2pll_div_0, + (unsigned)save->htotal_cntl2); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Read: rd=%u, fd=%u, pd=%u\n", + (unsigned)(save->p2pll_ref_div & RADEON_P2PLL_REF_DIV_MASK), + (unsigned)(save->p2pll_div_0 & RADEON_P2PLL_FB0_DIV_MASK), + (unsigned)((save->p2pll_div_0 & RADEON_P2PLL_POST0_DIV_MASK) + >> 16)); } /* Read palette data */ @@ -5369,27 +5242,25 @@ static void RADEONSavePalette(ScrnInfoPtr pScrn, RADEONSavePtr save) /* Save state that defines current video mode */ static void RADEONSaveMode(ScrnInfoPtr pScrn, RADEONSavePtr save) { - RADEONInfoPtr info = RADEONPTR(pScrn); - - RADEONTRACE(("RADEONSaveMode(%p)\n", save)); + RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->IsSecondary) { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONInfoPtr info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); - memcpy(&info->SavedReg, &info0->SavedReg, sizeof(RADEONSaveRec)); - } else { - RADEONSaveMemMapRegisters(pScrn, save); - RADEONSaveCommonRegisters(pScrn, save); - RADEONSavePLLRegisters (pScrn, save); - RADEONSaveCrtcRegisters (pScrn, save); - RADEONSaveFPRegisters (pScrn, save); - RADEONSaveCrtc2Registers (pScrn, save); - RADEONSavePLL2Registers (pScrn, save); - /*RADEONSavePalette(pScrn, save);*/ - /*memcpy(&info->ModeReg, &info->SavedReg, sizeof(RADEONSaveRec));*/ - } - - RADEONTRACE(("RADEONSaveMode returns %p\n", save)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSaveMode(%p)\n", save); + + RADEONSaveMemMapRegisters(pScrn, save); + RADEONSaveCommonRegisters(pScrn, save); + RADEONSavePLLRegisters(pScrn, save); + RADEONSaveCrtcRegisters(pScrn, save); + RADEONSaveFPRegisters(pScrn, save); + RADEONSaveDACRegisters(pScrn, save); + RADEONSaveCrtc2Registers(pScrn, save); + RADEONSavePLL2Registers(pScrn, save); + if (info->InternalTVOut) + RADEONSaveTVRegisters(pScrn, save); + /*RADEONSavePalette(pScrn, save);*/ + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSaveMode returns %p\n", save); } /* Save everything needed to restore the original VC state */ @@ -5399,62 +5270,55 @@ static void RADEONSave(ScrnInfoPtr pScrn) unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr save = &info->SavedReg; - RADEONTRACE(("RADEONSave\n")); - if (info->FBDev) { - RADEONSaveMemMapRegisters(pScrn, save); - fbdevHWSave(pScrn); - return; - } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSave\n"); - if (!info->IsSecondary) { #ifdef WITH_VGAHW - if (info->VGAAccess) { - vgaHWPtr hwp = VGAHWPTR(pScrn); + if (info->VGAAccess) { + vgaHWPtr hwp = VGAHWPTR(pScrn); - vgaHWUnlock(hwp); + vgaHWUnlock(hwp); # if defined(__powerpc__) - /* temporary hack to prevent crashing on PowerMacs when trying to - * read VGA fonts and colormap, will find a better solution - * in the future. TODO: Check if there's actually some VGA stuff - * setup in the card at all !! - */ - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ + /* temporary hack to prevent crashing on PowerMacs when trying to + * read VGA fonts and colormap, will find a better solution + * in the future. TODO: Check if there's actually some VGA stuff + * setup in the card at all !! + */ + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE); /* Save mode only */ # else - /* Save mode * & fonts & cmap */ - vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); + /* Save mode * & fonts & cmap */ + vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS); # endif - vgaHWLock(hwp); - } -#endif - save->dp_datatype = INREG(RADEON_DP_DATATYPE); - save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); - save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); - RADEONPllErrataAfterIndex(info); + vgaHWLock(hwp); } +#endif + save->dp_datatype = INREG(RADEON_DP_DATATYPE); + save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); + save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); + RADEONPllErrataAfterIndex(info); RADEONSaveMode(pScrn, save); - if (!info->IsSecondary) - RADEONSaveSurfaces(pScrn, save); + RADEONSaveSurfaces(pScrn, save); } /* Restore the original (text) mode */ -static void RADEONRestore(ScrnInfoPtr pScrn) +void RADEONRestore(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); unsigned char *RADEONMMIO = info->MMIO; RADEONSavePtr restore = &info->SavedReg; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc; - RADEONTRACE(("RADEONRestore\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONRestore\n"); #if X_BYTE_ORDER == X_BIG_ENDIAN RADEONWaitForFifo(pScrn, 1); OUTREG(RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_NONE); #endif - if (info->FBDev) { - fbdevHWRestore(pScrn); - return; - } RADEONBlank(pScrn); OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index); @@ -5473,11 +5337,27 @@ static void RADEONRestore(ScrnInfoPtr pScrn) OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl); #endif - RADEONRestoreMode(pScrn, restore); - if (!info->IsSecondary) - RADEONRestoreSurfaces(pScrn, restore); + RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); -#if 0 + if (pRADEONEnt->HasCRTC2) { + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + } + + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); + RADEONRestoreRMXRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + RADEONRestoreFP2Registers(pScrn, restore); + RADEONRestoreLVDSRegisters(pScrn, restore); + + if (info->InternalTVOut) + RADEONRestoreTVRegisters(pScrn, restore); + + RADEONRestoreSurfaces(pScrn, restore); + +#if 1 /* Temp fix to "solve" VT switch problems. When switching VTs on * some systems, the console can either hang or the fonts can be * corrupted. This hack solves the problem 99% of the time. A @@ -5489,830 +5369,36 @@ static void RADEONRestore(ScrnInfoPtr pScrn) #ifdef WITH_VGAHW if (info->VGAAccess) { vgaHWPtr hwp = VGAHWPTR(pScrn); - if (!info->IsSecondary) { - vgaHWUnlock(hwp); + vgaHWUnlock(hwp); # if defined(__powerpc__) - /* Temporary hack to prevent crashing on PowerMacs when trying to - * write VGA fonts, will find a better solution in the future - */ - vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE ); + /* Temporary hack to prevent crashing on PowerMacs when trying to + * write VGA fonts, will find a better solution in the future + */ + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE ); # else - vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); + vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); # endif - vgaHWLock(hwp); - } else { - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - ScrnInfoPtr pScrn0 = pRADEONEnt->pPrimaryScrn; - RADEONInfoPtr info0 = RADEONPTR(pScrn0); - vgaHWPtr hwp0; - - if (info0->VGAAccess) { - hwp0 = VGAHWPTR(pScrn0); - vgaHWUnlock(hwp0); -#if defined(__powerpc__) - vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE); -#else - vgaHWRestore(pScrn0, &hwp0->SavedReg, VGA_SR_MODE | VGA_SR_FONTS ); -#endif - vgaHWLock(hwp0); - } - } - } -#endif - RADEONUnblank(pScrn); - -#if 0 - RADEONWaitForVerticalSync(pScrn); -#endif -} - -/* Define common registers for requested video mode */ -static void RADEONInitCommonRegisters(RADEONSavePtr save, RADEONInfoPtr info) -{ - save->ovr_clr = 0; - save->ovr_wid_left_right = 0; - save->ovr_wid_top_bottom = 0; - save->ov0_scale_cntl = 0; - save->subpic_cntl = 0; - save->viph_control = 0; - save->i2c_cntl_1 = 0; - save->rbbm_soft_reset = 0; - save->cap0_trig_cntl = 0; - save->cap1_trig_cntl = 0; - save->bus_cntl = info->BusCntl; - /* - * If bursts are enabled, turn on discards - * Radeon doesn't have write bursts - */ - if (save->bus_cntl & (RADEON_BUS_READ_BURST)) - save->bus_cntl |= RADEON_BUS_RD_DISCARD_EN; -} - -/* XXX: fix me */ -static void RADEONInitTvDacCntl(ScrnInfoPtr pScrn, RADEONSavePtr save) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->ChipFamily == CHIP_FAMILY_R420 || - info->ChipFamily == CHIP_FAMILY_RV410) { - save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & - ~(RADEON_TV_DAC_STD_MASK | - RADEON_TV_DAC_BGADJ_MASK | - R420_TV_DAC_DACADJ_MASK | - R420_TV_DAC_RDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_GDACPD | - R420_TV_DAC_TVENABLE); - } else { - save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & - ~(RADEON_TV_DAC_STD_MASK | - RADEON_TV_DAC_BGADJ_MASK | - RADEON_TV_DAC_DACADJ_MASK | - RADEON_TV_DAC_RDACPD | - RADEON_TV_DAC_GDACPD | - RADEON_TV_DAC_GDACPD); - } - /* FIXME: doesn't make sense, this just replaces the previous value... */ - save->tv_dac_cntl = (RADEON_TV_DAC_NBLANK | - RADEON_TV_DAC_NHOLD | - RADEON_TV_DAC_STD_PS2 | - info->tv_dac_adj); -} - -static void RADEONInitFPRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - int i; - CARD32 tmp = info->SavedReg.tmds_pll_cntl & 0xfffff; - - for (i=0; i<4; i++) { - if (info->tmds_pll[i].freq == 0) break; - if ((CARD32)(mode->Clock/10) < info->tmds_pll[i].freq) { - tmp = info->tmds_pll[i].value ; - break; - } - } - - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { - if (tmp & 0xfff00000) - save->tmds_pll_cntl = tmp; - else { - save->tmds_pll_cntl = info->SavedReg.tmds_pll_cntl & 0xfff00000; - save->tmds_pll_cntl |= tmp; - } - } else save->tmds_pll_cntl = tmp; - - save->tmds_transmitter_cntl = info->SavedReg.tmds_transmitter_cntl & - ~(RADEON_TMDS_TRANSMITTER_PLLRST); - - if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2) - save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); - else /* weird, RV chips got this bit reversed? */ - save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); - - save->fp_gen_cntl = info->SavedReg.fp_gen_cntl | - (RADEON_FP_CRTC_DONT_SHADOW_VPAR | - RADEON_FP_CRTC_DONT_SHADOW_HEND ); - - if (pScrn->rgbBits == 8) - save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ - else - save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ - - - if (IsPrimary) { - 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; - } else { - if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { - save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; - } else - save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; - } - -} - -static void RADEONInitFP2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (pScrn->rgbBits == 8) - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | - RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ - else - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & - ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ - - if (IsPrimary) { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_EN | - RADEON_FP2_DVO_RATE_SEL_SDR); - if (mode->Flags & RADEON_USE_RMX) - save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; - } else { - save->fp2_gen_cntl &= ~(RADEON_FP2_SRC_SEL_CRTC2 | - RADEON_FP2_DVO_RATE_SEL_SDR); - } - /*save->fp2_gen_cntl |= ( RADEON_FP2_ON | - RADEON_FP2_BLANK_EN | - RADEON_FP2_DVO_EN);*/ - } else { - if ((info->ChipFamily == CHIP_FAMILY_R200) || 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_PANEL_FORMAT | - RADEON_FP2_BLANK_EN | - RADEON_FP2_ON | - RADEON_FP2_DVO_EN*/); - } else { - save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_RATE_SEL_SDR); - save->fp2_gen_cntl |= (RADEON_FP2_SRC_SEL_CRTC2 /*| - RADEON_FP2_PANEL_FORMAT | - RADEON_FP2_BLANK_EN | - RADEON_FP2_ON | - RADEON_FP2_DVO_EN*/); - } - } - -} - -static void RADEONInitLVDSRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); -/* XXX saved but never used??? */ - if (IsPrimary) - save->lvds_gen_cntl = info->SavedReg.lvds_gen_cntl & - ~RADEON_LVDS_SEL_CRTC2; - else - save->lvds_gen_cntl = info->SavedReg.lvds_gen_cntl | - RADEON_LVDS_SEL_CRTC2; - -} - -static void RADEONInitRMXRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - int xres = mode->HDisplay; - int yres = mode->VDisplay; - float Hratio, Vratio; - - - if (info->PanelXRes == 0 || info->PanelYRes == 0) { - Hratio = 1.0; - Vratio = 1.0; - } else { - if (xres > info->PanelXRes) xres = info->PanelXRes; - if (yres > info->PanelYRes) yres = info->PanelYRes; - - Hratio = (float)xres/(float)info->PanelXRes; - Vratio = (float)yres/(float)info->PanelYRes; - } - - save->fp_vert_stretch = info->SavedReg.fp_vert_stretch & - RADEON_VERT_STRETCH_RESERVED; - save->fp_horz_stretch = info->SavedReg.fp_horz_stretch & - (RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC); - - if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_horz_stretch |= ((xres/8-1)<<16); - } else { - save->fp_horz_stretch |= ((((unsigned long)(Hratio * RADEON_HORZ_STRETCH_RATIO_MAX + - 0.5)) & RADEON_HORZ_STRETCH_RATIO_MASK) | - RADEON_HORZ_STRETCH_BLEND | - RADEON_HORZ_STRETCH_ENABLE | - ((info->PanelXRes/8-1)<<16)); - } - - if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { - save->fp_vert_stretch |= ((yres-1)<<12); - } else { - save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX + - 0.5)) & RADEON_VERT_STRETCH_RATIO_MASK) | - RADEON_VERT_STRETCH_ENABLE | - RADEON_VERT_STRETCH_BLEND | - ((info->PanelYRes-1)<<12)); - } - -} - -static void RADEONInitDACRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (IsPrimary) { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_DAC_SOURCE_MASK; - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL); - } - save->dac_cntl = (RADEON_DAC_MASK_ALL - | RADEON_DAC_VGA_ADR_EN - | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); - - } else { - if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_DAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC_CLK_SEL; - } - } -} - -static void RADEONInitDAC2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, BOOL IsPrimary) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - /*0x0028023;*/ - RADEONInitTvDacCntl(pScrn, save); - - if (IsPrimary) { - /*save->crtc2_gen_cntl = info->SavedReg.crtc2_gen_cntl | RADEON_CRTC2_CRT2_ON;*/ - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - if (IS_R300_VARIANT) { - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_TVDAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; - } else if (info->ChipFamily == CHIP_FAMILY_R200) { - save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & - ~(R200_FP2_SOURCE_SEL_MASK | - RADEON_FP2_DVO_RATE_SEL_SDR); - /*save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | - (RADEON_FP2_ON | - RADEON_FP2_BLANK_EN | - RADEON_FP2_DVO_EN);*/ - } else { - save->disp_hw_debug = info->SavedReg.disp_hw_debug | RADEON_CRT2_DISP1_SEL; - } - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - if (IS_R300_VARIANT) { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - save->disp_output_cntl = info->SavedReg.disp_output_cntl & - ~RADEON_DISP_TVDAC_SOURCE_MASK; - save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; - } else if (info->ChipFamily == CHIP_FAMILY_R200) { - save->fp2_gen_cntl = info->SavedReg.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_BLANK_EN | - RADEON_FP2_ON | - RADEON_FP2_DVO_EN*/); - /*save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; - save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid;*/ - } else { - save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; - save->disp_hw_debug = info->SavedReg.disp_hw_debug & - ~RADEON_CRT2_DISP1_SEL; - } - } -} - -static void RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, DisplayModePtr mode, RADEONConnector *pPort, int crtc_num) -{ - Bool IsPrimary = crtc_num == 1 ? TRUE : FALSE; - - if (pPort->MonType == MT_CRT) { - if (pPort->DACType == DAC_PRIMARY) { - RADEONInitDACRegisters(pScrn, save, mode, IsPrimary); - } else { - RADEONInitDAC2Registers(pScrn, save, mode, IsPrimary); - } - } else if (pPort->MonType == MT_LCD) { - if (crtc_num == 1) - RADEONInitRMXRegisters(pScrn, save, mode); - RADEONInitLVDSRegisters(pScrn, save, mode, IsPrimary); - } else if (pPort->MonType == MT_DFP) { - if (crtc_num == 1) - RADEONInitRMXRegisters(pScrn, save, mode); - if (pPort->TMDSType == TMDS_INT) { - RADEONInitFPRegisters(pScrn, save, mode, IsPrimary); - } else { - RADEONInitFP2Registers(pScrn, save, mode, IsPrimary); - } - } -} - -/* Define CRTC registers for requested video mode */ -static Bool RADEONInitCrtcRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, RADEONInfoPtr info) -{ - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - - pRADEONEnt->Controller[0]->IsUsed = TRUE; - pRADEONEnt->Controller[0]->IsActive = TRUE; - pRADEONEnt->Controller[0]->pCurMode = mode; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - save->bios_4_scratch = info->SavedReg.bios_4_scratch; - save->crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN - | RADEON_CRTC_EN - | (format << 8) - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC_INTERLACE_EN - : 0)); - - save->crtc_ext_cntl |= (RADEON_CRTC_CRT_ON | - RADEON_CRTC_VSYNC_DIS | - RADEON_CRTC_HSYNC_DIS | - RADEON_CRTC_DISPLAY_DIS); - - save->surface_cntl = 0; - save->disp_merge_cntl = info->SavedReg.disp_merge_cntl; - save->disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; - -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* We must set both apertures as they can be both used to map the entire - * video memory. -BenH. - */ - switch (pScrn->bitsPerPixel) { - case 16: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; - break; - - case 32: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; - break; + vgaHWLock(hwp); } #endif - 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; + /* need to make sure we don't enable a crtc by accident or we may get a hang */ + if (info->crtc2_on) { + crtc = xf86_config->crtc[1]; + crtc->funcs->dpms(crtc, DPMSModeOn); } - - if (mode->Flags & RADEON_USE_RMX) { - mode->CrtcHTotal = mode->CrtcHDisplay + info->HBlank; - mode->CrtcHSyncStart = mode->CrtcHDisplay + info->HOverPlus; - mode->CrtcHSyncEnd = mode->CrtcHSyncStart + info->HSyncWidth; - mode->CrtcVTotal = mode->CrtcVDisplay + info->VBlank; - mode->CrtcVSyncStart = mode->CrtcVDisplay + info->VOverPlus; - mode->CrtcVSyncEnd = mode->CrtcVSyncStart + info->VSyncWidth; - mode->Clock = info->DotClock; - mode->Flags = info->Flags | RADEON_USE_RMX; + if (info->crtc_on) { + crtc = xf86_config->crtc[0]; + crtc->funcs->dpms(crtc, DPMSModeOn); } - - - - save->crtc_h_total_disp = ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) - << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - if (hsync_wid > 0x3f) hsync_wid = 0x3f; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) - | (hsync_wid << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - /* This works for double scan mode. */ - save->crtc_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - if (vsync_wid > 0x1f) vsync_wid = 0x1f; - - save->crtc_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | (vsync_wid << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC_V_SYNC_POL - : 0)); - - save->crtc_offset = pScrn->fbOffset; - if (info->tilingEnabled) { - if (IS_R300_VARIANT) - save->crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc_offset_cntl |= RADEON_CRTC_TILE_EN; - } - else { - if (IS_R300_VARIANT) - save->crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; - } - - save->crtc_pitch = (((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / - (pScrn->bitsPerPixel * 8)); - save->crtc_pitch |= save->crtc_pitch << 16; - - save->fp_h_sync_strt_wid = save->crtc_h_sync_strt_wid; - save->fp_v_sync_strt_wid = save->crtc_v_sync_strt_wid; - save->fp_crtc_h_total_disp = save->crtc_h_total_disp; - save->fp_crtc_v_total_disp = save->crtc_v_total_disp; - - /* Set following registers for all cases first, if a DFP/LCD is connected on - internal TMDS/LVDS port, they will be set by RADEONInitFPRegister - */ - if (!info->IsSwitching) { - save->fp_gen_cntl = 0; - save->fp_vert_stretch = info->SavedReg.fp_vert_stretch & - RADEON_VERT_STRETCH_RESERVED; - save->fp_horz_stretch = info->SavedReg.fp_horz_stretch & - (RADEON_HORZ_FP_LOOP_STRETCH | - RADEON_HORZ_AUTO_RATIO_INC); - } - - /* get the output connected to this CRTC */ - if (pRADEONEnt->PortInfo[0]->crtc_num == 1) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[0], 1); - } else if (pRADEONEnt->PortInfo[1]->crtc_num == 1) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[1], 1); - } - - 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)); - } - - return TRUE; -} - -/* Define CRTC2 registers for requested video mode */ -static Bool RADEONInitCrtc2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - DisplayModePtr mode, RADEONInfoPtr info) -{ - int format; - int hsync_start; - int hsync_wid; - int vsync_wid; - - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - RADEONInfoPtr info0 = NULL; - if (info->IsSecondary) - info0 = RADEONPTR(pRADEONEnt->pPrimaryScrn); - - pRADEONEnt->Controller[1]->IsUsed = TRUE; - pRADEONEnt->Controller[1]->IsActive = TRUE; - pRADEONEnt->Controller[1]->pCurMode = mode; - - switch (info->CurrentLayout.pixel_code) { - case 4: format = 1; break; - case 8: format = 2; break; - case 15: format = 3; break; /* 555 */ - case 16: format = 4; break; /* 565 */ - case 24: format = 5; break; /* RGB */ - case 32: format = 6; break; /* xRGB */ - default: - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Unsupported pixel depth (%d)\n", - info->CurrentLayout.bitsPerPixel); - return FALSE; - } - - save->crtc2_h_total_disp = - ((((mode->CrtcHTotal / 8) - 1) & 0x3ff) - | ((((mode->CrtcHDisplay / 8) - 1) & 0x1ff) << 16)); - - hsync_wid = (mode->CrtcHSyncEnd - mode->CrtcHSyncStart) / 8; - if (!hsync_wid) hsync_wid = 1; - if (hsync_wid > 0x3f) hsync_wid = 0x3f; - hsync_start = mode->CrtcHSyncStart - 8; - - save->crtc2_h_sync_strt_wid = ((hsync_start & 0x1fff) - | (hsync_wid << 16) - | ((mode->Flags & V_NHSYNC) - ? RADEON_CRTC_H_SYNC_POL - : 0)); - - /* This works for double scan mode. */ - save->crtc2_v_total_disp = (((mode->CrtcVTotal - 1) & 0xffff) - | ((mode->CrtcVDisplay - 1) << 16)); - - vsync_wid = mode->CrtcVSyncEnd - mode->CrtcVSyncStart; - if (!vsync_wid) vsync_wid = 1; - if (vsync_wid > 0x1f) vsync_wid = 0x1f; - - save->crtc2_v_sync_strt_wid = (((mode->CrtcVSyncStart - 1) & 0xfff) - | (vsync_wid << 16) - | ((mode->Flags & V_NVSYNC) - ? RADEON_CRTC2_V_SYNC_POL - : 0)); - - /* It seems all fancy options apart from pflip can be safely disabled - */ - save->crtc2_offset = pScrn->fbOffset; - save->crtc2_offset_cntl &= RADEON_CRTC_OFFSET_FLIP_CNTL; - if (info->tilingEnabled) { - if (IS_R300_VARIANT) - save->crtc2_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc2_offset_cntl |= RADEON_CRTC_TILE_EN; - } - else { - if (IS_R300_VARIANT) - save->crtc2_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | - R300_CRTC_MICRO_TILE_BUFFER_DIS | - R300_CRTC_MACRO_TILE_EN); - else - save->crtc2_offset_cntl &= ~RADEON_CRTC_TILE_EN; - } - - save->crtc2_pitch = ((pScrn->displayWidth * pScrn->bitsPerPixel) + - ((pScrn->bitsPerPixel * 8) -1)) / (pScrn->bitsPerPixel * 8); - save->crtc2_pitch |= save->crtc2_pitch << 16; - - save->crtc2_gen_cntl = (RADEON_CRTC2_EN - | RADEON_CRTC2_CRT2_ON - | (format << 8) - | RADEON_CRTC2_VSYNC_DIS - | RADEON_CRTC2_HSYNC_DIS - | RADEON_CRTC2_DISP_DIS - | ((mode->Flags & V_DBLSCAN) - ? RADEON_CRTC2_DBL_SCAN_EN - : 0) - | ((mode->Flags & V_CSYNC) - ? RADEON_CRTC2_CSYNC_EN - : 0) - | ((mode->Flags & V_INTERLACE) - ? RADEON_CRTC2_INTERLACE_EN - : 0)); - - save->disp2_merge_cntl = info->SavedReg.disp2_merge_cntl; - save->disp2_merge_cntl &= ~(RADEON_DISP2_RGB_OFFSET_EN); - - save->fp_h2_sync_strt_wid = save->crtc2_h_sync_strt_wid; - save->fp_v2_sync_strt_wid = save->crtc2_v_sync_strt_wid; - - /* get the output connected to this CRTC */ - if (pRADEONEnt->PortInfo[0]->crtc_num == 2) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[0], 2); - } else if (pRADEONEnt->PortInfo[1]->crtc_num == 2) { - RADEONInitOutputRegisters(pScrn, save, mode, pRADEONEnt->PortInfo[1], 2); - } - - /* We must set SURFACE_CNTL properly on the second screen too */ - save->surface_cntl = 0; -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* We must set both apertures as they can be both used to map the entire - * video memory. -BenH. + /* to restore console mode, DAC registers should be set after every other registers are set, + * otherwise,we may get blank screen */ - switch (pScrn->bitsPerPixel) { - case 16: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_16BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_16BPP; - break; + RADEONRestoreDACRegisters(pScrn, restore); - case 32: - save->surface_cntl |= RADEON_NONSURF_AP0_SWP_32BPP; - save->surface_cntl |= RADEON_NONSURF_AP1_SWP_32BPP; - break; - } +#if 0 + RADEONWaitForVerticalSync(pScrn); #endif - - return TRUE; -} - - -/* Define PLL registers for requested video mode */ -static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info, - RADEONSavePtr save, RADEONPLLPtr pll, - double dot_clock) -{ - unsigned long freq = dot_clock * 100; - - struct { - int divider; - int bitvalue; - } *post_div, post_divs[] = { - /* From RAGE 128 VR/RAGE 128 GL Register - * Reference Manual (Technical Reference - * Manual P/N RRG-G04100-C Rev. 0.04), page - * 3-17 (PLL_DIV_[3:0]). - */ - { 1, 0 }, /* VCLK_SRC */ - { 2, 1 }, /* VCLK_SRC/2 */ - { 4, 2 }, /* VCLK_SRC/4 */ - { 8, 3 }, /* VCLK_SRC/8 */ - { 3, 4 }, /* VCLK_SRC/3 */ - { 16, 5 }, /* VCLK_SRC/16 */ - { 6, 6 }, /* VCLK_SRC/6 */ - { 12, 7 }, /* VCLK_SRC/12 */ - { 0, 0 } - }; - - if (info->UseBiosDividers) { - save->ppll_ref_div = info->RefDivider; - save->ppll_div_3 = info->FeedbackDivider | (info->PostDivider << 16); - save->htotal_cntl = 0; - return; - } - - if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; - if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; - - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - save->pll_output_freq = post_div->divider * freq; - - if (save->pll_output_freq >= pll->min_pll_freq - && save->pll_output_freq <= pll->max_pll_freq) break; - } - - if (!post_div->divider) { - save->pll_output_freq = freq; - post_div = &post_divs[0]; - } - - save->dot_clock_freq = freq; - save->feedback_div = RADEONDiv(pll->reference_div - * save->pll_output_freq, - pll->reference_freq); - save->post_div = post_div->divider; - - RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n", - save->dot_clock_freq, - save->pll_output_freq, - save->feedback_div, - save->post_div)); - - save->ppll_ref_div = pll->reference_div; - save->ppll_div_3 = (save->feedback_div | (post_div->bitvalue << 16)); - save->htotal_cntl = 0; - - save->vclk_cntl = (info->SavedReg.vclk_cntl & - ~RADEON_VCLK_SRC_SEL_MASK) | RADEON_VCLK_SRC_SEL_PPLLCLK; - -} - -/* Define PLL2 registers for requested video mode */ -static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save, - RADEONPLLPtr pll, double dot_clock, - int no_odd_postdiv) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - unsigned long freq = dot_clock * 100; - - struct { - int divider; - int bitvalue; - } *post_div, post_divs[] = { - /* From RAGE 128 VR/RAGE 128 GL Register - * Reference Manual (Technical Reference - * Manual P/N RRG-G04100-C Rev. 0.04), page - * 3-17 (PLL_DIV_[3:0]). - */ - { 1, 0 }, /* VCLK_SRC */ - { 2, 1 }, /* VCLK_SRC/2 */ - { 4, 2 }, /* VCLK_SRC/4 */ - { 8, 3 }, /* VCLK_SRC/8 */ - { 3, 4 }, /* VCLK_SRC/3 */ - { 6, 6 }, /* VCLK_SRC/6 */ - { 12, 7 }, /* VCLK_SRC/12 */ - { 0, 0 } - }; - - if (freq > pll->max_pll_freq) freq = pll->max_pll_freq; - if (freq * 12 < pll->min_pll_freq) freq = pll->min_pll_freq / 12; - - for (post_div = &post_divs[0]; post_div->divider; ++post_div) { - /* Odd post divider value don't work properly on the second digital - * output - */ - if (no_odd_postdiv && (post_div->divider & 1)) - continue; - save->pll_output_freq_2 = post_div->divider * freq; - if (save->pll_output_freq_2 >= pll->min_pll_freq - && save->pll_output_freq_2 <= pll->max_pll_freq) break; - } - - if (!post_div->divider) { - save->pll_output_freq_2 = freq; - post_div = &post_divs[0]; - } - - save->dot_clock_freq_2 = freq; - save->feedback_div_2 = RADEONDiv(pll->reference_div - * save->pll_output_freq_2, - pll->reference_freq); - save->post_div_2 = post_div->divider; - - RADEONTRACE(("dc=%ld, of=%ld, fd=%d, pd=%d\n", - save->dot_clock_freq_2, - save->pll_output_freq_2, - save->feedback_div_2, - save->post_div_2)); - - save->p2pll_ref_div = pll->reference_div; - save->p2pll_div_0 = (save->feedback_div_2 | - (post_div->bitvalue << 16)); - save->htotal_cntl2 = 0; - - save->pixclks_cntl = ((info->SavedReg.pixclks_cntl & - ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | - RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); - } #if 0 @@ -6325,177 +5411,22 @@ static void RADEONInitPalette(RADEONSavePtr save) } #endif -/* Define registers for a requested video mode */ -static Bool RADEONInit2(ScrnInfoPtr pScrn, DisplayModePtr crtc1, - DisplayModePtr crtc2, int crtc_mask, - RADEONSavePtr save) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - double dot_clock = crtc1->Clock/1000.0; - RADEONInfoPtr info0 = NULL; - ScrnInfoPtr pScrn0 = NULL; - -#if RADEON_DEBUG - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - crtc1->name, - dot_clock, - - crtc1->HDisplay, - crtc1->HSyncStart, - crtc1->HSyncEnd, - crtc1->HTotal, - - crtc1->VDisplay, - crtc1->VSyncStart, - crtc1->VSyncEnd, - crtc1->VTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); - if (crtc1->Flags & V_CSYNC) ErrorF(" C"); - if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); - if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); - if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); - if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); - if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); - ErrorF("%-12.12s %7.2f %4d %4d %4d %4d %4d %4d %4d %4d (%d,%d)", - crtc1->name, - dot_clock, - - crtc1->CrtcHDisplay, - crtc1->CrtcHSyncStart, - crtc1->CrtcHSyncEnd, - crtc1->CrtcHTotal, - - crtc1->CrtcVDisplay, - crtc1->CrtcVSyncStart, - crtc1->CrtcVSyncEnd, - crtc1->CrtcVTotal, - pScrn->depth, - pScrn->bitsPerPixel); - if (crtc1->Flags & V_DBLSCAN) ErrorF(" D"); - if (crtc1->Flags & V_CSYNC) ErrorF(" C"); - if (crtc1->Flags & V_INTERLACE) ErrorF(" I"); - if (crtc1->Flags & V_PHSYNC) ErrorF(" +H"); - if (crtc1->Flags & V_NHSYNC) ErrorF(" -H"); - if (crtc1->Flags & V_PVSYNC) ErrorF(" +V"); - if (crtc1->Flags & V_NVSYNC) ErrorF(" -V"); - ErrorF("\n"); -#endif - - info->Flags = crtc1->Flags; - - RADEONInitMemMapRegisters(pScrn, save, info); - RADEONInitCommonRegisters(save, info); - - switch(crtc_mask) { - case 1: - if (!RADEONInitCrtcRegisters(pScrn, save, crtc1, info)) - return FALSE; - dot_clock = crtc1->Clock/1000.0; - if (dot_clock) { - RADEONInitPLLRegisters(pScrn, info, 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; - } - if (pRADEONEnt->HasSecondary) { - pScrn0 = pRADEONEnt->pSecondaryScrn; - info0 = RADEONPTR(pScrn0); - /* carry over to secondary screen */ - memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); - } - - /* Not used for now: */ - /* if (!info->PaletteSavedOnVT) RADEONInitPalette(save); */ - break; - case 2: - pScrn0 = pRADEONEnt->pPrimaryScrn; - info0 = RADEONPTR(pScrn0); - dot_clock = crtc2->Clock/1000.0; - if (!RADEONInitCrtc2Registers(pScrn, save, crtc2, info)) - return FALSE; - RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT); - /* Make sure primary has the same copy */ - memcpy(&info0->ModeReg, save, sizeof(RADEONSaveRec)); - break; - case 3: - if (!RADEONInitCrtcRegisters(pScrn, save, - crtc1, info)) - return FALSE; - dot_clock = crtc1->Clock / 1000.0; - if (dot_clock) { - RADEONInitPLLRegisters(pScrn, info, 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, crtc2, info); - dot_clock = crtc2->Clock / 1000.0; - RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->MergeType != MT_CRT); - break; - default: - return FALSE; - } - - RADEONTRACE(("RADEONInit returns %p\n", save)); - return TRUE; -} - -static Bool RADEONInit(ScrnInfoPtr pScrn, DisplayModePtr mode, - RADEONSavePtr save) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if (info->IsSecondary) { - return RADEONInit2(pScrn, NULL, mode, 2, save); - } else if (info->MergedFB) { - return RADEONInit2(pScrn, ((RADEONMergedDisplayModePtr)mode->Private)->CRT1, - ((RADEONMergedDisplayModePtr)mode->Private)->CRT2, 3, save); - } else { - return RADEONInit2(pScrn, mode, NULL, 1, save); - } -} - -/* Initialize a new mode */ -static Bool RADEONModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - RADEONTRACE(("RADEONModeInit()\n")); - - if (!RADEONInit(pScrn, mode, &info->ModeReg)) return FALSE; - - pScrn->vtSema = TRUE; - RADEONBlank(pScrn); - RADEONRestoreMode(pScrn, &info->ModeReg); - RADEONUnblank(pScrn); - - info->CurrentLayout.mode = mode; - - if (info->DispPriority) - RADEONInitDispBandwidth(pScrn); - - return TRUE; -} - static Bool RADEONSaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; Bool unblank; - RADEONTRACE(("RADEONSaveScreen(%d)\n", mode)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSaveScreen(%d)\n", mode); unblank = xf86IsUnblank(mode); if (unblank) SetTimeSinceLastInputEvent(); if ((pScrn != NULL) && pScrn->vtSema) { - if (unblank) RADEONUnblank(pScrn); - else RADEONBlank(pScrn); + if (unblank) + RADEONUnblank(pScrn); + else + RADEONBlank(pScrn); } return TRUE; } @@ -6520,7 +5451,7 @@ RADEONResetDPI(ScrnInfoPtr pScrn, Bool force) } } -_X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); @@ -6535,20 +5466,11 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #endif - RADEONTRACE(("RADEONSwitchMode() !n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONSwitchMode() !n"); if (info->allowColorTiling) { - if (info->MergedFB) { - if ((((RADEONMergedDisplayModePtr)mode->Private)->CRT1->Flags & - (V_DBLSCAN | V_INTERLACE)) || - (((RADEONMergedDisplayModePtr)mode->Private)->CRT2->Flags & - (V_DBLSCAN | V_INTERLACE))) - info->tilingEnabled = FALSE; - else info->tilingEnabled = TRUE; - } - else { - info->tilingEnabled = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; - } + info->tilingEnabled = (mode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; #ifdef XF86DRI if (info->directRenderingEnabled && (info->tilingEnabled != tilingOld)) { RADEONSAREAPrivPtr pSAREAPriv; @@ -6564,19 +5486,7 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) if (info->accelOn) RADEON_SYNC(info, pScrn); - if (info->FBDev) { - RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); - - ret = fbdevHWSwitchMode(scrnIndex, mode, flags); - pScrn->displayWidth = fbdevHWGetLineLength(pScrn) - / info->CurrentLayout.pixel_bytes; - - RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); - } else { - info->IsSwitching = TRUE; - ret = RADEONModeInit(xf86Screens[scrnIndex], mode); - info->IsSwitching = FALSE; - } + ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0); if (info->tilingEnabled != tilingOld) { /* need to redraw front buffer, I guess this can be considered a hack ? */ @@ -6601,10 +5511,7 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) /* Since RandR (indirectly) uses SwitchMode(), we need to * update our Xinerama info here, too, in case of resizing */ - if (info->MergedFB) { - RADEONMergedFBResetDpi(pScrn, FALSE); - RADEONUpdateXineramaScreenInfo(pScrn); - } else if(info->constantDPI) { + if(info->constantDPI) { RADEONResetDPI(pScrn, FALSE); } @@ -6614,7 +5521,7 @@ _X_EXPORT Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) } #ifdef X_XF86MiscPassMessage -_X_EXPORT Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, +Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, const char* msgval, char** retmsg) { ErrorF("RADEONHandleMessage(%d, \"%s\", \"%s\", retmsg)\n", scrnIndex, @@ -6625,7 +5532,7 @@ _X_EXPORT Bool RADEONHandleMessage(int scrnIndex, const char* msgtype, #endif /* Used to disallow modes that are not supported by the hardware */ -_X_EXPORT ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, +ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flag) { /* There are problems with double scan mode at high clocks @@ -6642,18 +5549,19 @@ _X_EXPORT ModeStatus RADEONValidMode(int scrnIndex, DisplayModePtr mode, /* Adjust viewport into virtual desktop such that (0,0) in viewport * space is (x,y) in virtual space. */ -void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) +void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, Bool crtc2) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; - int reg, Base, regcntl, crtcoffsetcntl, xytilereg, crtcxytile = 0; + int Base, reg, regcntl, crtcoffsetcntl, xytilereg, crtcxytile = 0; #ifdef XF86DRI RADEONSAREAPrivPtr pSAREAPriv; XF86DRISAREAPtr pSAREA; #endif #if 0 /* Verbose */ - RADEONTRACE(("RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone); #endif if (info->showCache && y) { @@ -6673,12 +5581,12 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) pick up the new offset value at the end of each scanline, but the new offset_cntl value only after a vsync. We'd probably need to wait (in drm) for vsync and only then update OFFSET and OFFSET_CNTL, if the y coord has changed. Seems hard to fix. */ - if (clone || info->IsSecondary) { - reg = RADEON_CRTC2_OFFSET; + if (crtc2) { + reg = RADEON_CRTC2_OFFSET; regcntl = RADEON_CRTC2_OFFSET_CNTL; xytilereg = R300_CRTC2_TILE_X0_Y0; } else { - reg = RADEON_CRTC_OFFSET; + reg = RADEON_CRTC_OFFSET; regcntl = RADEON_CRTC_OFFSET_CNTL; xytilereg = R300_CRTC_TILE_X0_Y0; } @@ -6730,7 +5638,7 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) /* can't get at sarea in a semi-sane way? */ pSAREA = (void *)((char*)pSAREAPriv - sizeof(XF86DRISAREARec)); - if (clone || info->IsSecondary) { + if (crtc2) { pSAREAPriv->crtc2_base = Base; } else { @@ -6748,20 +5656,23 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone) } #endif - OUTREG(reg, Base); - if (IS_R300_VARIANT) { - OUTREG(xytilereg, crtcxytile); + OUTREG(xytilereg, crtcxytile); } else { - OUTREG(regcntl, crtcoffsetcntl); + OUTREG(regcntl, crtcoffsetcntl); } + OUTREG(reg, Base); } -_X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) +void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); @@ -6770,14 +5681,16 @@ _X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) if (info->accelOn) RADEON_SYNC(info, pScrn); - if(info->MergedFB) { - RADEONAdjustFrameMerged(scrnIndex, x, y, flags); - } else if (info->FBDev) { - fbdevHWAdjustFrame(scrnIndex, x, y, flags); - } else { - RADEONDoAdjustFrame(pScrn, x, y, FALSE); + if (crtc && crtc->enabled) { + if (crtc == pRADEONEnt->pCrtc[0]) + RADEONDoAdjustFrame(pScrn, crtc->desiredX + x, crtc->desiredY + y, FALSE); + else + RADEONDoAdjustFrame(pScrn, crtc->desiredX + x, crtc->desiredY + y, TRUE); + crtc->x = output->initial_x + x; + crtc->y = output->initial_y + y; } + #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen); #endif @@ -6786,15 +5699,18 @@ _X_EXPORT void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) /* Called when VT switching back to the X server. Reinitialize the * video mode. */ -_X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) +Bool RADEONEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - RADEONTRACE(("RADEONEnterVT\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONEnterVT\n"); - if (INREG(RADEON_CONFIG_MEMSIZE) == 0) { /* Softboot V_BIOS */ + if ((INREG(RADEON_CONFIG_MEMSIZE)) == 0) { /* Softboot V_BIOS */ xf86Int10InfoPtr pInt; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "zero MEMSIZE, probably at D3cold. Re-POSTing via int10.\n"); @@ -6809,18 +5725,25 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) /* Makes sure the engine is idle before doing anything */ RADEONWaitForIdleMMIO(pScrn); - if (info->FBDev) { - unsigned char *RADEONMMIO = info->MMIO; - if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE; - info->PaletteSavedOnVT = FALSE; - info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); + pScrn->vtSema = TRUE; + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) { + crtc->desiredMode = *RADEONCrtcFindClosestMode (crtc, pScrn->currentMode); + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredX = 0; + crtc->desiredY = 0; + } - RADEONRestoreFBDevRegisters(pScrn, &info->ModeReg); - } else - if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, + crtc->desiredX, crtc->desiredY)) + return FALSE; - if (!info->IsSecondary) - RADEONRestoreSurfaces(pScrn, &info->ModeReg); + } + + RADEONRestoreSurfaces(pScrn, &info->ModeReg); #ifdef XF86DRI if (info->directRenderingEnabled) { if (info->cardType == CARD_PCIE && info->pKernelDRMVersion->version_minor >= 19 && info->FbSecureSize) @@ -6830,8 +5753,10 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) } /* get the DRI back into shape after resume */ + RADEONDRISetVBlankInterrupt (pScrn, TRUE); RADEONDRIResume(pScrn->pScreen); RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg); + } #endif /* this will get XVideo going again, but only if XVideo was initialised @@ -6849,7 +5774,7 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) } #endif - pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + // pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); return TRUE; } @@ -6857,15 +5782,17 @@ _X_EXPORT Bool RADEONEnterVT(int scrnIndex, int flags) /* Called when VT switching away from the X server. Restore the * original text mode. */ -_X_EXPORT void RADEONLeaveVT(int scrnIndex, int flags) +void RADEONLeaveVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONSavePtr save = &info->ModeReg; - RADEONTRACE(("RADEONLeaveVT\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONLeaveVT\n"); #ifdef XF86DRI if (RADEONPTR(pScrn)->directRenderingInited) { + + RADEONDRISetVBlankInterrupt (pScrn, FALSE); DRILock(pScrn->pScreen, 0); RADEONCP_STOP(pScrn, info); @@ -6874,21 +5801,26 @@ _X_EXPORT void RADEONLeaveVT(int scrnIndex, int flags) /* we need to backup the PCIE GART TABLE from fb memory */ memcpy(info->pciGartBackup, (info->FB + info->pciGartOffset), info->pciGartSize); } - } -#endif - - if (info->FBDev) { - RADEONSavePalette(pScrn, save); - info->PaletteSavedOnVT = TRUE; - RADEONSaveFBDevRegisters(pScrn, &info->ModeReg); - - fbdevHWLeaveVT(scrnIndex,flags); + /* Make sure 3D clients will re-upload textures to video RAM */ + if (info->textureSize) { + RADEONSAREAPrivPtr pSAREAPriv = + (RADEONSAREAPrivPtr)DRIGetSAREAPrivate(pScrn->pScreen); + drmTextureRegionPtr list = pSAREAPriv->texList[0]; + int age = ++pSAREAPriv->texAge[0], i = 0; + + do { + list[i].age = age; + i = list[i].next; + } while (i != 0); + } } +#endif RADEONRestore(pScrn); - RADEONTRACE(("Ok, leaving now...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Ok, leaving now...\n"); } /* Called at the end of each server generation. Restore the original @@ -6900,7 +5832,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONTRACE(("RADEONCloseScreen\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "RADEONCloseScreen\n"); /* Mark acceleration as stopped or we might try to access the engine at * wrong times, especially if we had DRI, after DRI has been stopped @@ -6929,11 +5862,11 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) #endif /* USE_XAA */ if (pScrn->vtSema) { - RADEONDisplayPowerManagementSet(pScrn, DPMSModeOn, 0); RADEONRestore(pScrn); } - RADEONTRACE(("Disposing accel...\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Disposing accel...\n"); #ifdef USE_EXA if (info->exa) { exaDriverFini(pScreen); @@ -6953,14 +5886,17 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) } #endif /* USE_XAA */ - RADEONTRACE(("Disposing cusor info\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Disposing cusor info\n"); if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); info->cursor = NULL; - RADEONTRACE(("Disposing DGA\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Disposing DGA\n"); if (info->DGAModes) xfree(info->DGAModes); info->DGAModes = NULL; - RADEONTRACE(("Unmapping memory\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Unmapping memory\n"); RADEONUnmapMem(pScrn); pScrn->vtSema = FALSE; @@ -6972,50 +5908,17 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) return (*pScreen->CloseScreen)(scrnIndex, pScreen); } -_X_EXPORT void RADEONFreeScreen(int scrnIndex, int flags) +void RADEONFreeScreen(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONTRACE(("RADEONFreeScreen\n")); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "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; - } - } - #ifdef WITH_VGAHW if (info->VGAAccess && xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); @@ -7023,235 +5926,6 @@ _X_EXPORT void RADEONFreeScreen(int scrnIndex, int flags) RADEONFreeRec(pScrn); } -static void -RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - RADEONConnector *connector; - 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; - info->CRT1XOffs = info->CRT1YOffs = info->CRT2XOffs = info->CRT2YOffs = 0; - info->NonRect = info->HaveNonRect = info->HaveOffsRegions = FALSE; - info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; - info->MouseRestrictions = TRUE; - - 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 ((connector = RADEONGetCrtcConnector(pScrn, 2))) { - if (!connector->MonInfo) { - 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) { - int result, ival; - Bool valid = FALSE; - char *tempstr; - strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2POS); - if (strptr) { - tempstr = xalloc(strlen(strptr) + 1); - result = sscanf(strptr, "%s %d", tempstr, &ival); - } else { /* Not specified - default is "Clone" */ - tempstr = NULL; - result = 0; - info->CRT2Position = radeonClone; - valid = TRUE; - } - if(result >= 1) { - if(!xf86NameCmp(tempstr,"LeftOf")) { - info->CRT2Position = radeonLeftOf; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1YOffs = -ival; - else info->CRT2YOffs = ival; - } - info->CRT2IsScrn0 = TRUE; - } else if(!xf86NameCmp(tempstr,"RightOf")) { - info->CRT2Position = radeonRightOf; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1YOffs = -ival; - else info->CRT2YOffs = ival; - } - info->CRT2IsScrn0 = FALSE; - } else if(!xf86NameCmp(tempstr,"Above")) { - info->CRT2Position = radeonAbove; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1XOffs = -ival; - else info->CRT2XOffs = ival; - } - info->CRT2IsScrn0 = FALSE; - } else if(!xf86NameCmp(tempstr,"Below")) { - info->CRT2Position = radeonBelow; - valid = TRUE; - if(result == 2) { - if(ival < 0) info->CRT1XOffs = -ival; - else info->CRT2XOffs = ival; - } - info->CRT2IsScrn0 = TRUE; - } else if(!xf86NameCmp(tempstr,"Clone")) { - info->CRT2Position = radeonClone; - if(result == 1) valid = TRUE; - /*info->CRT2IsScrn0 = TRUE;*/ - } - } - if(!valid) { - 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"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Except for \"Clone\", the parameter may be followed by an integer.\n"); - } - xfree(tempstr); - - 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_RADEONXINERAMA, &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; - } - if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBNONRECT, &val)) { - info->NonRect = val ? TRUE : FALSE; - } - if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBMOUSER, &val)) { - info->MouseRestrictions = val ? TRUE : 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); */ - - connector = RADEONGetCrtcConnector(pScrn, 2); - info->CRT2pScrn->monitor->DDC = connector ? connector->MonInfo : NULL; - - 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 RADEONForceSomeClocks(ScrnInfoPtr pScrn) { /* It appears from r300 and rv100 may need some clocks forced-on */ @@ -7610,21 +6284,3 @@ static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode) break; } } - -_X_EXPORT 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_exa.c b/src/radeon_exa.c index f9bcaceb..d074f08a 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -496,3 +496,20 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen) return TRUE; } + +#ifdef XF86DRI + +#ifndef ExaOffscreenMarkUsed +extern void ExaOffscreenMarkUsed(PixmapPtr); +#endif + +unsigned long long +RADEONTexOffsetStart(PixmapPtr pPix) +{ + exaMoveInPixmap(pPix); + ExaOffscreenMarkUsed(pPix); + + return RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation + + exaGetPixmapOffset(pPix); +} +#endif diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index 0d847d1c..c356de7c 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -59,14 +59,30 @@ #include "exa.h" +static int +FUNC_NAME(RADEONMarkSync)(ScreenPtr pScreen) +{ + RINFO_FROM_SCREEN(pScreen); + + TRACE; + + return ++info->exaSyncMarker; +} + static void FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + TRACE; - FUNC_NAME(RADEONWaitForIdle)(xf86Screens[pScreen->myNum]); + if (info->exaMarkerSynced != marker) { + FUNC_NAME(RADEONWaitForIdle)(pScrn); + info->exaMarkerSynced = marker; + } - RADEONPTR(xf86Screens[pScreen->myNum])->engineMode = EXA_ENGINEMODE_UNKNOWN; + RADEONPTR(pScrn)->engineMode = EXA_ENGINEMODE_UNKNOWN; } static Bool @@ -444,6 +460,8 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT, &indirect, sizeof(drmRadeonIndirect)); + info->exaMarkerSynced = info->exaSyncMarker; + return TRUE; } #endif @@ -504,6 +522,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) info->exa->Copy = FUNC_NAME(RADEONCopy); info->exa->DoneCopy = FUNC_NAME(RADEONDoneCopy); + info->exa->MarkSync = FUNC_NAME(RADEONMarkSync); info->exa->WaitMarker = FUNC_NAME(RADEONSync); info->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen); info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); diff --git a/src/radeon_mergedfb.c b/src/radeon_mergedfb.c deleted file mode 100644 index 820ba4ba..00000000 --- a/src/radeon_mergedfb.c +++ /dev/null @@ -1,2089 +0,0 @@ -/* - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* - * Authors: - * Alex Deucher <agd5f@yahoo.com> - * Based, in large part, on the sis driver by Thomas Winischhofer. - */ - -#include <string.h> -#include <stdio.h> - -#include "xf86.h" -#include "xf86Priv.h" -#include "xf86Resources.h" -#include "xf86_OSproc.h" -#include "extnsionst.h" /* required */ -#include <X11/extensions/panoramiXproto.h> /* required */ -#include "dixstruct.h" -#include "vbe.h" - - -#include "radeon.h" -#include "radeon_reg.h" -#include "radeon_macros.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 (i, j) for merged-fb mode - * (Taken from mga, sis drivers) - * Copys mode i, merges j to copy of 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; - - /* Provide a fake VRefresh/DotClock in order to trick the vidmode - * extension to allow selecting among a number of modes whose merged result - * looks identical but consists of different modes for CRT1 and CRT2 - */ - mode->VRefresh = (float)((i->Clock * 1000.0 / i->HTotal / i->VTotal) * 100 + - (j->Clock * 1000.0 / j->HTotal / j->VTotal)); - - mode->Clock = (int)(mode->VRefresh * 0.001 * mode->HTotal * mode->VTotal); - - if( ((mode->HDisplay * ((pScrn->bitsPerPixel + 7) / 8) * mode->VDisplay) > - (pScrn->videoRam * 1024)) || - (mode->HDisplay > 8191) || - (mode->VDisplay > 8191) ) { - - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Skipped \"%s\" (%dx%d), not enough video RAM or beyond hardware specs\n", - mode->name, mode->HDisplay, mode->VDisplay); - xfree(mode->Private); - xfree(mode); - - return dest; - } - - if(srel != radeonClone) { - info->AtLeastOneNonClone = TRUE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Merged \"%s\" (%dx%d) and \"%s\" (%dx%d) to %dx%d%s\n", - i->name, i->HDisplay, i->VDisplay, j->name, 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, sis drivers) - */ -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 void -RADEONFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, - DisplayModePtr *a, DisplayModePtr *b) -{ - DisplayModePtr c = i, d; - int max = 0; - Bool foundone; - - (*a) = (*b) = NULL; - - if(!i || !j) return; - - do { - d = j; - foundone = FALSE; - do { - if( (c->HDisplay == d->HDisplay) && - (c->VDisplay == d->VDisplay) ) { - foundone = TRUE; - break; - } - d = d->next; - } while(d != j); - if(foundone) { - if(tallest) { - if(c->VDisplay > max) { - max = c->VDisplay; - (*a) = c; - (*b) = d; - } - } else { - if(c->HDisplay > max) { - max = c->HDisplay; - (*a) = c; - (*b) = d; - } - } - } - c = c->next; - } while(c != i); -} - -static DisplayModePtr -RADEONGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel) -{ - - RADEONInfoPtr info = RADEONPTR(pScrn); - DisplayModePtr mode1 = NULL; - DisplayModePtr mode2 = NULL; - DisplayModePtr mode3 = NULL; - DisplayModePtr mode4 = NULL; - DisplayModePtr result = NULL; - - info->AtLeastOneNonClone = FALSE; - - /* Now build a default list of MetaModes. - * - Non-clone: If the user enabled NonRectangular, we use the - * largest mode for each CRT1 and CRT2. If not, we use the largest - * common mode for CRT1 and CRT2 (if available). Additionally, and - * regardless if the above, we produce a clone mode consisting of - * the largest common mode (if available) in order to use DGA. - * - Clone: If the (global) CRT2Position is Clone, we use the - * largest common mode if available, otherwise the first two modes - * in each list. - */ - - switch(srel) { - case radeonLeftOf: - case radeonRightOf: - mode1 = RADEONFindWidestTallestMode(i, FALSE); - mode2 = RADEONFindWidestTallestMode(j, FALSE); - RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); - break; - case radeonAbove: - case radeonBelow: - mode1 = RADEONFindWidestTallestMode(i, TRUE); - mode2 = RADEONFindWidestTallestMode(j, TRUE); - RADEONFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); - break; - case radeonClone: - RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); - if(mode3 && mode4) { - mode1 = mode3; - mode2 = mode4; - } else { - mode1 = i; - mode2 = j; - } - } - - if(srel != radeonClone) { - if(mode3 && mode4 && !info->NonRect) { - mode1 = mode3; - mode2 = mode2; - } - } - - if(mode1 && mode2) { - result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel); - } - - if(srel != radeonClone) { - if(mode3 && mode4) { - result = RADEONCopyModeNLink(pScrn, result, mode3, mode4, radeonClone); - } - } - return result; -} - -/* Generate the merged-fb mode modelist - * (Taken from mga, sis drivers) - */ -static DisplayModePtr -RADEONGenerateModeListFromMetaModes(ScrnInfoPtr pScrn, char* str, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel) -{ - char* strmode = str; - char modename[256]; - Bool gotdash = FALSE; - char gotsep = 0; - RADEONScrn2Rel sr; - DisplayModePtr mode1 = NULL; - DisplayModePtr mode2 = NULL; - DisplayModePtr result = NULL; - int myslen; - RADEONInfoPtr info = RADEONPTR(pScrn); - - info->AtLeastOneNonClone = FALSE; - - do { - switch(*str) { - case 0: - case '-': - case '+': - case ' ': - case ',': - case ';': - if(strmode != str) { - - myslen = str - strmode; - if(myslen > 255) myslen = 255; - strncpy(modename, strmode, myslen); - modename[myslen] = 0; - - if(gotdash) { - if(mode1 == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Error parsing MetaModes parameter\n"); - 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, - "\t(Skipping metamode \"%s%c%s\")\n", mode1->name, gotsep, modename); - mode1 = NULL; - gotsep = 0; - } - } 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); - while(*tmps == ' ' || *tmps == ';') tmps++; - /* skip the next mode */ - if(*tmps == '-' || *tmps == '+' || *tmps == ',') { - tmps++; - /* skip spaces */ - while(*tmps == ' ' || *tmps == ';') tmps++; - /* skip modename */ - while(*tmps && *tmps != ' ' && *tmps != ';' && *tmps != '-' && *tmps != '+' && *tmps != ',') tmps++; - myslen = tmps - strmode; - if(myslen > 255) myslen = 255; - strncpy(modename,strmode,myslen); - modename[myslen] = 0; - str = tmps-1; - } - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "\t(Skipping metamode \"%s\")\n", modename); - mode1 = NULL; - gotsep = 0; - } - } - gotdash = FALSE; - } - strmode = str + 1; - gotdash |= (*str == '-' || *str == '+' || *str == ','); - if (*str == '-' || *str == '+' || *str == ',') - gotsep = *str; - - if(*str != 0) break; - /* Fall through otherwise */ - - default: - if(!gotdash && mode1) { - sr = srel; - if(gotsep == '+') sr = radeonClone; - 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, - "\t(Skipping metamode \"%s\")\n", modename); - mode1 = NULL; - } else { - result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, sr); - mode1 = NULL; - mode2 = NULL; - } - gotsep = 0; - } - break; - - } - - } while(*(str++) != 0); - - return result; -} - -DisplayModePtr -RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, - DisplayModePtr i, DisplayModePtr j, - RADEONScrn2Rel srel) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - - if(str != NULL) { - return(RADEONGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); - } else { - if (srel == radeonClone ) { - DisplayModePtr p, q, result = NULL; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Clone mode, list all common modes\n"); - for (p = i; p->next != i; p = p->next) - for (q = j; q->next != j; q = q->next) - if ((p->HDisplay == q->HDisplay) && - (p->VDisplay == q->VDisplay)) - result = RADEONCopyModeNLink(pScrn, result, p, q, srel); - return result; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No MetaModes given, linking %s modes by default\n", - (info->NonRect ? - (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest" : "tallest") - : - (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest common" : "tallest common")) ); - return(RADEONGenerateModeListFromLargestModes(pScrn, i, j, srel)); - } - } -} - -void -RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - DisplayModePtr mode, bmode; - int maxh, maxv; - static const char *str = "MergedFB: Virtual %s %d\n"; - static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; - - mode = bmode = pScrn->modes; - maxh = maxv = 0; - do { - if(mode->HDisplay > maxh) maxh = mode->HDisplay; - if(mode->VDisplay > maxv) maxv = mode->VDisplay; - mode = mode->next; - } while(mode != bmode); - maxh += info->CRT1XOffs + info->CRT2XOffs; - maxv += info->CRT1YOffs + info->CRT2YOffs; - - if(!(pScrn->display->virtualX)) { - if(maxh > 8191) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Virtual width with CRT2Position offset beyond hardware specs\n"); - info->CRT1XOffs = info->CRT2XOffs = 0; - maxh -= (info->CRT1XOffs + info->CRT2XOffs); - } - pScrn->virtualX = maxh; - pScrn->displayWidth = maxh; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); - } else { - if(maxh < pScrn->display->virtualX) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); - info->CRT1XOffs = info->CRT2XOffs = 0; - } - } - - if(!(pScrn->display->virtualY)) { - pScrn->virtualY = maxv; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); - } else { - if(maxv < pScrn->display->virtualY) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); - info->CRT1YOffs = info->CRT2YOffs = 0; - } - } -} - -/* 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; - int realvirtX, realvirtY; - DisplayModePtr currentMode, firstMode; - Bool infochanged = FALSE; - Bool usenonrect = info->NonRect; - const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; - - info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; - info->HaveNonRect = info->HaveOffsRegions = 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) - */ - - /* "Real" virtual: Virtual without the Offset */ - realvirtX = pScrn1->virtualX - info->CRT1XOffs - info->CRT2XOffs; - realvirtY = pScrn1->virtualY - info->CRT1YOffs - info->CRT2YOffs; - - 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((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && - (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && - (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { - - if(srel != radeonClone) { - if(info->maxCRT1_X1 == i->HDisplay) { - if(info->maxCRT1_X2 < j->HDisplay) { - info->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ - } - } else if(info->maxCRT1_X1 < i->HDisplay) { - info->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ - info->maxCRT1_X2 = j->HDisplay; - } - if(info->maxCRT2_X2 == j->HDisplay) { - if(info->maxCRT2_X1 < i->HDisplay) { - info->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ - } - } else if(info->maxCRT2_X2 < j->HDisplay) { - info->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ - info->maxCRT2_X1 = i->HDisplay; - } - if(info->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ - if(info->maxCRT1_Y2 < j->VDisplay) { - info->maxCRT1_Y2 = j->VDisplay; - } - } else if(info->maxCRT1_Y1 < i->VDisplay) { - info->maxCRT1_Y1 = i->VDisplay; - info->maxCRT1_Y2 = j->VDisplay; - } - if(info->maxCRT2_Y2 == j->VDisplay) { - if(info->maxCRT2_Y1 < i->VDisplay) { - info->maxCRT2_Y1 = i->VDisplay; - } - } else if(info->maxCRT2_Y2 < j->VDisplay) { - info->maxCRT2_Y2 = j->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; - - } - - if((usenonrect) && (info->CRT2Position != radeonClone) && info->maxCRT1_X1) { - switch(info->CRT2Position) { - case radeonLeftOf: - case radeonRightOf: - if((info->maxCRT1_Y1 != realvirtY) && (info->maxCRT2_Y2 != realvirtY)) { - usenonrect = FALSE; - } - break; - case radeonAbove: - case radeonBelow: - if((info->maxCRT1_X1 != realvirtX) && (info->maxCRT2_X2 != realvirtX)) { - usenonrect = FALSE; - } - break; - case radeonClone: - break; - } - - if(infochanged && !usenonrect) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Virtual screen size does not match maximum display modes...\n"); - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); - - } - } else if(infochanged && usenonrect) { - usenonrect = FALSE; - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Only clone modes available for this virtual screen size...\n"); - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); - } - - if(info->maxCRT1_X1) { /* Means we have at least one non-clone mode */ - switch(info->CRT2Position) { - case radeonLeftOf: - x1 = min(info->maxCRT1_X2, pScrn1->virtualX - info->maxCRT1_X1); - if(x1 < 0) x1 = 0; - y1 = info->CRT1YOffs; - w1 = pScrn1->virtualX - x1; - h1 = realvirtY; - if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { - h1 = info->MBXNR1YMAX = info->maxCRT1_Y1; - info->NonRectDead.x0 = x1; - info->NonRectDead.x1 = x1 + w1 - 1; - info->NonRectDead.y0 = y1 + h1; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - x2 = 0; - y2 = info->CRT2YOffs; - w2 = max(info->maxCRT2_X2, pScrn1->virtualX - info->maxCRT2_X1); - if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; - h2 = realvirtY; - if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { - h2 = info->MBXNR2YMAX = info->maxCRT2_Y2; - info->NonRectDead.x0 = x2; - info->NonRectDead.x1 = x2 + w2 - 1; - info->NonRectDead.y0 = y2 + h2; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - break; - case radeonRightOf: - x1 = 0; - y1 = info->CRT1YOffs; - w1 = max(info->maxCRT1_X1, pScrn1->virtualX - info->maxCRT1_X2); - if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; - h1 = realvirtY; - if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { - h1 = info->MBXNR1YMAX = info->maxCRT1_Y1; - info->NonRectDead.x0 = x1; - info->NonRectDead.x1 = x1 + w1 - 1; - info->NonRectDead.y0 = y1 + h1; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - x2 = min(info->maxCRT2_X1, pScrn1->virtualX - info->maxCRT2_X2); - if(x2 < 0) x2 = 0; - y2 = info->CRT2YOffs; - w2 = pScrn1->virtualX - x2; - h2 = realvirtY; - if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { - h2 = info->MBXNR2YMAX = info->maxCRT2_Y2; - info->NonRectDead.x0 = x2; - info->NonRectDead.x1 = x2 + w2 - 1; - info->NonRectDead.y0 = y2 + h2; - info->NonRectDead.y1 = pScrn1->virtualY - 1; - info->HaveNonRect = TRUE; - } - break; - case radeonAbove: - x1 = info->CRT1XOffs; - y1 = min(info->maxCRT1_Y2, pScrn1->virtualY - info->maxCRT1_Y1); - if(y1 < 0) y1 = 0; - w1 = realvirtX; - h1 = pScrn1->virtualY - y1; - if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { - w1 = info->MBXNR1XMAX = info->maxCRT1_X1; - info->NonRectDead.x0 = x1 + w1; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y1; - info->NonRectDead.y1 = y1 + h1 - 1; - info->HaveNonRect = TRUE; - } - x2 = info->CRT2XOffs; - y2 = 0; - w2 = realvirtX; - h2 = max(info->maxCRT2_Y2, pScrn1->virtualY - info->maxCRT2_Y1); - if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; - if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { - w2 = info->MBXNR2XMAX = info->maxCRT2_X2; - info->NonRectDead.x0 = x2 + w2; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y2; - info->NonRectDead.y1 = y2 + h2 - 1; - info->HaveNonRect = TRUE; - } - break; - case radeonBelow: - x1 = info->CRT1XOffs; - y1 = 0; - w1 = realvirtX; - h1 = max(info->maxCRT1_Y1, pScrn1->virtualY - info->maxCRT1_Y2); - if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; - if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { - w1 = info->MBXNR1XMAX = info->maxCRT1_X1; - info->NonRectDead.x0 = x1 + w1; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y1; - info->NonRectDead.y1 = y1 + h1 - 1; - info->HaveNonRect = TRUE; - } - x2 = info->CRT2XOffs; - y2 = min(info->maxCRT2_Y1, pScrn1->virtualY - info->maxCRT2_Y2); - if(y2 < 0) y2 = 0; - w2 = realvirtX; - h2 = pScrn1->virtualY - y2; - if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { - w2 = info->MBXNR2XMAX = info->maxCRT2_X2; - info->NonRectDead.x0 = x2 + w2; - info->NonRectDead.x1 = pScrn1->virtualX - 1; - info->NonRectDead.y0 = y2; - info->NonRectDead.y1 = y2 + h2 - 1; - info->HaveNonRect = TRUE; - } - default: - break; - } - - switch(info->CRT2Position) { - case radeonLeftOf: - case radeonRightOf: - if(info->CRT1YOffs) { - info->OffDead1.x0 = x1; - info->OffDead1.x1 = x1 + w1 - 1; - info->OffDead1.y0 = 0; - info->OffDead1.y1 = y1 - 1; - info->OffDead2.x0 = x2; - info->OffDead2.x1 = x2 + w2 - 1; - info->OffDead2.y0 = y2 + h2; - info->OffDead2.y1 = pScrn1->virtualY - 1; - info->HaveOffsRegions = TRUE; - } else if(info->CRT2YOffs) { - info->OffDead1.x0 = x2; - info->OffDead1.x1 = x2 + w2 - 1; - info->OffDead1.y0 = 0; - info->OffDead1.y1 = y2 - 1; - info->OffDead2.x0 = x1; - info->OffDead2.x1 = x1 + w1 - 1; - info->OffDead2.y0 = y1 + h1; - info->OffDead2.y1 = pScrn1->virtualY - 1; - info->HaveOffsRegions = TRUE; - } - break; - case radeonAbove: - case radeonBelow: - if(info->CRT1XOffs) { - info->OffDead1.x0 = x2 + w2; - info->OffDead1.x1 = pScrn1->virtualX - 1; - info->OffDead1.y0 = y2; - info->OffDead1.y1 = y2 + h2 - 1; - info->OffDead2.x0 = 0; - info->OffDead2.x1 = x1 - 1; - info->OffDead2.y0 = y1; - info->OffDead2.y1 = y1 + h1 - 1; - info->HaveOffsRegions = TRUE; - } else if(info->CRT2XOffs) { - info->OffDead1.x0 = x1 + w1; - info->OffDead1.x1 = pScrn1->virtualX - 1; - info->OffDead1.y0 = y1; - info->OffDead1.y1 = y1 + h1 - 1; - info->OffDead2.x0 = 0; - info->OffDead2.x1 = x2 - 1; - info->OffDead2.y0 = y2; - info->OffDead2.y1 = y2 + h2 - 1; - info->HaveOffsRegions = TRUE; - } - default: - break; - } - - } else { /* Only clone-modes left */ - - x1 = x2 = 0; - y1 = y2 = 0; - w1 = w2 = max(info->maxClone_X1, info->maxClone_X2); - h1 = h2 = max(info->maxClone_Y1, info->maxClone_Y2); - - } - - 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); - if(info->HaveNonRect) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", - info->NonRectDead.x0, info->NonRectDead.y0, - info->NonRectDead.x1, info->NonRectDead.y1); - } - if(info->HaveOffsRegions) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", - info->OffDead1.x0, info->OffDead1.y0, - info->OffDead1.x1, info->OffDead1.y1); - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", - info->OffDead2.x0, info->OffDead2.y0, - info->OffDead2.x1, info->OffDead2.y1); - } - if(info->HaveNonRect || info->HaveOffsRegions) { - xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Mouse restriction for inaccessible areas is %s\n", - info->MouseRestrictions ? "enabled" : "disabled"); - } - } -} -/* 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; - info->MouseRestrictions = FALSE; - return; - } - -#ifdef PANORAMIX - if(!noPanoramiXExtension) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Xinerama active, not initializing Radeon Pseudo-Xinerama\n"); - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - return; - } -#endif - - if(RADEONnoPanoramiXExtension) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Radeon Pseudo-Xinerama disabled\n"); - info->MouseRestrictions = FALSE; - return; - } - - if(info->CRT2Position == radeonClone) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Running MergedFB in Clone mode, Radeon Pseudo-Xinerama disabled\n"); - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - return; - } - - if(!(info->AtLeastOneNonClone)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Only Clone modes defined, Radeon Pseudo-Xinerama disabled\n"); - RADEONnoPanoramiXExtension = TRUE; - info->MouseRestrictions = FALSE; - 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; - info->MouseRestrictions = FALSE; - 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; - int temp1, temp2; - int old1x0, old1y0, old2x0, old2y0; - int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; - int HVirt = pScrn1->virtualX; - int VVirt = pScrn1->virtualY; - int sigstate; - Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; - RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; - - if(info->DGAactive) { - return; - /* DGA: There is no cursor and no panning while DGA is active. */ - /* If it were, we would need to do: */ - /* HVirt = info->CurrentLayout.displayWidth; - VVirt = info->CurrentLayout.displayHeight; - BOUND(x, info->CurrentLayout.DGAViewportX, HVirt); - BOUND(y, info->CurrentLayout.DGAViewportY, VVirt); */ - } else { - CRT1XOffs = info->CRT1XOffs; - CRT1YOffs = info->CRT1YOffs; - CRT2XOffs = info->CRT2XOffs; - CRT2YOffs = info->CRT2YOffs; - HaveNonRect = info->HaveNonRect; - HaveOffsRegions = info->HaveOffsRegions; - } - - /* Check if the pointer is inside our dead areas */ - if((info->MouseRestrictions) && (srel != radeonClone) && !RADEONnoPanoramiXExtension) { - if(HaveNonRect) { - if(InRegion(x, y, info->NonRectDead)) { - switch(srel) { - case radeonLeftOf: - case radeonRightOf: y = info->NonRectDead.y0 - 1; - doit = TRUE; - break; - case radeonAbove: - case radeonBelow: x = info->NonRectDead.x0 - 1; - doit = TRUE; - default: break; - } - } - } - if(HaveOffsRegions) { - if(InRegion(x, y, info->OffDead1)) { - switch(srel) { - case radeonLeftOf: - case radeonRightOf: y = info->OffDead1.y1; - doit = TRUE; - break; - case radeonAbove: - case radeonBelow: x = info->OffDead1.x1; - doit = TRUE; - default: break; - } - } else if(InRegion(x, y, info->OffDead2)) { - switch(srel) { - case radeonLeftOf: - case radeonRightOf: y = info->OffDead2.y0 - 1; - doit = TRUE; - break; - case radeonAbove: - case radeonBelow: x = info->OffDead2.x0 - 1; - doit = TRUE; - default: break; - } - } - } - if(doit) { - UpdateCurrentTime(); - sigstate = xf86BlockSIGIO(); - miPointerAbsoluteCursor(x, y, currentTime.milliseconds); - xf86UnblockSIGIO(sigstate); - return; - } - } - - f1.x0 = old1x0 = info->CRT1frameX0; - f1.x1 = info->CRT1frameX1; - f1.y0 = old1y0 = info->CRT1frameY0; - f1.y1 = info->CRT1frameY1; - f2.x0 = old2x0 = pScrn2->frameX0; - f2.x1 = pScrn2->frameX1; - f2.y0 = old2y0 = 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(srel) { - 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(srel) { - 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; - - switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) { - case radeonLeftOf: - case radeonRightOf: - if(info->CRT1YOffs || info->CRT2YOffs || HaveNonRect) { - if(info->CRT1frameY0 != old1y0) { - if(info->CRT1frameY0 < info->CRT1YOffs) - info->CRT1frameY0 = info->CRT1YOffs; - temp1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay; - /*temp2 = pScrn1->virtualY - info->CRT2YOffs;*/ - temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + info->MBXNR1YMAX)); - if(temp1 > temp2) - info->CRT1frameY0 -= (temp1 - temp2); - } - if(pScrn2->frameY0 != old2y0) { - if(pScrn2->frameY0 < info->CRT2YOffs) - pScrn2->frameY0 = info->CRT2YOffs; - temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; - /*temp2 = pScrn1->virtualY - info->CRT1YOffs;*/ - temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + info->MBXNR2YMAX)); - if(temp1 > temp2) - pScrn2->frameY0 -= (temp1 - temp2); - } - } - break; - case radeonBelow: - case radeonAbove: - if(info->CRT1XOffs || info->CRT2XOffs || HaveNonRect) { - if(info->CRT1frameX0 != old1x0) { - if(info->CRT1frameX0 < info->CRT1XOffs) - info->CRT1frameX0 = info->CRT1XOffs; - temp1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay; - /*temp2 = pScrn1->virtualX - info->CRT2XOffs;*/ - temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + info->MBXNR1XMAX)); - if(temp1 > temp2) - info->CRT1frameX0 -= (temp1 - temp2); - } - if(pScrn2->frameX0 != old2x0) { - if(pScrn2->frameX0 < info->CRT2XOffs) - pScrn2->frameX0 = info->CRT2XOffs; - temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; - /*temp2 = pScrn1->virtualX - info->CRT1XOffs;*/ - temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + info->MBXNR2XMAX)); - if(temp1 > temp2) - pScrn2->frameX0 -= (temp1 - temp2); - } - } - break; - case radeonClone: - break; - } - - 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; -#if 0 - pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; - pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; -#endif - - 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; - int HVirt = pScrn1->virtualX; - int VVirt = pScrn1->virtualY; - int x1 = x, x2 = x; - int y1 = y, y2 = y; - int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; - int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; - - if(info->DGAactive) { - HVirt = info->CurrentLayout.displayWidth; - VVirt = info->CurrentLayout.displayHeight; - } else { - CRT1XOffs = info->CRT1XOffs; - CRT1YOffs = info->CRT1YOffs; - CRT2XOffs = info->CRT2XOffs; - CRT2YOffs = info->CRT2YOffs; - MBXNR1XMAX = info->MBXNR1XMAX; - MBXNR1YMAX = info->MBXNR1YMAX; - MBXNR2XMAX = info->MBXNR2XMAX; - MBXNR2YMAX = info->MBXNR2YMAX; - } - - - BOUND(x, 0, pScrn1->virtualX - HTotal); - BOUND(y, 0, pScrn1->virtualY - VTotal); - if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { -#if 0 - BOUND(x1, info->CRT1XOffs, pScrn1->virtualX - HTotal - info->CRT2XOffs); - BOUND(y1, info->CRT1YOffs, pScrn1->virtualY - VTotal - info->CRT2YOffs); - BOUND(x2, info->CRT2XOffs, pScrn1->virtualX - HTotal - info->CRT1XOffs); - BOUND(y2, info->CRT2YOffs, pScrn1->virtualY - VTotal - info->CRT1YOffs); -#endif - BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); - BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); - BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); - BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); - } - - switch(SDMPTR(pScrn1)->CRT2Position) { - case radeonLeftOf: - pScrn2->frameX0 = x2; - /*BOUND(pScrn2->frameY0, y2, y2 + VMax - CDMPTR->CRT2->VDisplay);*/ - BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); - info->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; - /*BOUND(info->CRT1frameY0, y1, y1 + VMax - CDMPTR->CRT1->VDisplay);*/ - BOUND(info->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); - break; - case radeonRightOf: - info->CRT1frameX0 = x1; - /*BOUND(info->CRT1frameY0, y1, y1 + VMax - CDMPTR->CRT1->VDisplay);*/ - BOUND(info->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); - pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; - /*BOUND(pScrn2->frameY0, y2, y2 + VMax - CDMPTR->CRT2->VDisplay);*/ - BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); - break; - case radeonAbove: - /*BOUND(pScrn2->frameX0, x2, x2 + HMax - CDMPTR->CRT2->HDisplay);*/ - BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); - pScrn2->frameY0 = y2; - /*BOUND(info->CRT1frameX0, x1, x1 + HMax - CDMPTR->CRT1->HDisplay);*/ - BOUND(info->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); - info->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; - break; - case radeonBelow: - /*BOUND(info->CRT1frameX0, x1, x1 + HMax - CDMPTR->CRT1->HDisplay);*/ - BOUND(info->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); - info->CRT1frameY0 = y1; - /*BOUND(pScrn2->frameX0, x2, x2 + HMax - CDMPTR->CRT2->HDisplay);*/ - BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); - pScrn2->frameY0 = y2 + 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; - - if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { - pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; - pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; - } - -/* - 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); -} - -static void -RADEONMergedFBCalcDPI(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel, Bool quiet) -{ - 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: %dx%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. - */ - - /* Copy user-given DisplaySize (which should regard BOTH monitors!) */ - pScrn1->widthmm = pScrn1->monitor->widthmm; - pScrn1->heightmm = pScrn1->monitor->heightmm; - - 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 (overrules DisplaySize config option) */ - 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); - } - if(!quiet) { - xf86DrvMsg(pScrn1->scrnIndex, from, dsstr, pScrn1->widthmm, pScrn1->heightmm); - } - - } else if(ddcWidthmm && ddcHeightmm) { - - /* Set values from DDC-provided display size */ - - /* 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; - } - } - - from = X_PROBED; - - if(!quiet) { - 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; - - if(!quiet) { - xf86DrvMsg(pScrn1->scrnIndex, from, "MergedFB: DPI set to (%d, %d)\n", - pScrn1->xDpi, pScrn1->yDpi); - } -} - - -void -RADEONMergedFBSetDpi(ScrnInfoPtr pScrn1, ScrnInfoPtr pScrn2, RADEONScrn2Rel srel) -{ - RADEONInfoPtr info = RADEONPTR(pScrn1); - - RADEONMergedFBCalcDPI(pScrn1, pScrn2, srel, FALSE); - - info->MergedDPISRel = srel; - info->RADEONMergedDPIVX = pScrn1->virtualX; - info->RADEONMergedDPIVY = pScrn1->virtualY; - -} - -void -RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; - RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; - - /* This does the same calculation for the DPI as - * the initial run. This means that an eventually - * given -dpi command line switch will lead to - * constant dpi values, regardless of the virtual - * screen size. - * I consider this consequent. If this is undesired, - * one should use the DisplaySize parameter in the - * config file instead of the command line switch. - * The DPI will be calculated then. - */ - - if(force || - (info->MergedDPISRel != srel) || - (info->RADEONMergedDPIVX != pScrn->virtualX) || - (info->RADEONMergedDPIVY != pScrn->virtualY) - ) { - - RADEONMergedFBCalcDPI(pScrn, info->CRT2pScrn, srel, TRUE); - - pScreen->mmWidth = (pScrn->virtualX * 254 + pScrn->xDpi * 5) / (pScrn->xDpi * 10); - pScreen->mmHeight = (pScrn->virtualY * 254 + pScrn->yDpi * 5) / (pScrn->yDpi * 10); - - info->MergedDPISRel = srel; - info->RADEONMergedDPIVX = pScrn->virtualX; - info->RADEONMergedDPIVY = pScrn->virtualY; - - } -} - -/* 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_offset + 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_offset + 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 deleted file mode 100644 index d9bcc03c..00000000 --- a/src/radeon_mergedfb.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 <X11/extensions/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 _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 -RADEONMergedFBResetDpi(ScrnInfoPtr pScrn, Bool force); -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_modes.c b/src/radeon_modes.c index 70bf1846..687e3888 100644 --- a/src/radeon_modes.c +++ b/src/radeon_modes.c @@ -42,80 +42,18 @@ #include "xf86.h" /* Driver data structures */ +#include "randrstr.h" +#include "radeon_probe.h" #include "radeon.h" #include "radeon_reg.h" #include "radeon_macros.h" -#include "radeon_probe.h" + #include "radeon_version.h" +#include "xf86Modes.h" /* DDC support */ #include "xf86DDC.h" - -/* Established timings from EDID standard */ -static struct -{ - int hsize; - int vsize; - int refresh; -} est_timings[] = { - {1280, 1024, 75}, - {1024, 768, 75}, - {1024, 768, 70}, - {1024, 768, 60}, - {1024, 768, 87}, - {832, 624, 75}, - {800, 600, 75}, - {800, 600, 72}, - {800, 600, 60}, - {800, 600, 56}, - {640, 480, 75}, - {640, 480, 72}, - {640, 480, 67}, - {640, 480, 60}, - {720, 400, 88}, - {720, 400, 70}, -}; - -/* This function will sort all modes according to their resolution. - * Highest resolution first. - */ -static void RADEONSortModes(DisplayModePtr *new, DisplayModePtr *first, - DisplayModePtr *last) -{ - DisplayModePtr p; - - p = *last; - while (p) { - if ((((*new)->HDisplay < p->HDisplay) && - ((*new)->VDisplay < p->VDisplay)) || - (((*new)->HDisplay == p->HDisplay) && - ((*new)->VDisplay == p->VDisplay) && - ((*new)->Clock < p->Clock))) { - - if (p->next) p->next->prev = *new; - (*new)->prev = p; - (*new)->next = p->next; - p->next = *new; - if (!((*new)->next)) *last = *new; - break; - } - if (!p->prev) { - (*new)->prev = NULL; - (*new)->next = p; - p->prev = *new; - *first = *new; - break; - } - p = p->prev; - } - - if (!*first) { - *first = *new; - (*new)->prev = NULL; - (*new)->next = NULL; - *last = *new; - } -} +#include <randrstr.h> void RADEONSetPitch (ScrnInfoPtr pScrn) { @@ -136,346 +74,61 @@ void RADEONSetPitch (ScrnInfoPtr pScrn) break; } pScrn->displayWidth = dummy; -} - -/* When no mode provided in config file, this will add all modes supported in - * DDC date the pScrn->modes list - */ -static DisplayModePtr RADEONDDCModes(ScrnInfoPtr pScrn, xf86MonPtr ddc) -{ - DisplayModePtr p; - DisplayModePtr last = NULL; - DisplayModePtr new = NULL; - DisplayModePtr first = NULL; - int count = 0; - int j, tmp; - char stmp[32]; - - /* Go thru detailed timing table first */ - for (j = 0; j < 4; j++) { - if (ddc->det_mon[j].type == 0) { - struct detailed_timings *d_timings = - &ddc->det_mon[j].section.d_timings; - - if (d_timings->h_active == 0 || d_timings->v_active == 0) break; - - new = xnfcalloc(1, sizeof (DisplayModeRec)); - memset(new, 0, sizeof (DisplayModeRec)); - - new->HDisplay = d_timings->h_active; - new->VDisplay = d_timings->v_active; - - sprintf(stmp, "%dx%d", new->HDisplay, new->VDisplay); - new->name = xnfalloc(strlen(stmp) + 1); - strcpy(new->name, stmp); - - new->HTotal = new->HDisplay + d_timings->h_blanking; - new->HSyncStart = new->HDisplay + d_timings->h_sync_off; - new->HSyncEnd = new->HSyncStart + d_timings->h_sync_width; - new->VTotal = new->VDisplay + d_timings->v_blanking; - new->VSyncStart = new->VDisplay + d_timings->v_sync_off; - new->VSyncEnd = new->VSyncStart + d_timings->v_sync_width; - new->Clock = d_timings->clock / 1000; - new->Flags = (d_timings->interlaced ? V_INTERLACE : 0); - new->status = MODE_OK; -#ifdef M_T_PREFERRED - if (PREFERRED_TIMING_MODE(ddc->features.msc)) - new->type = M_T_PREFERRED; - else -#endif - new->type = M_T_DEFAULT; - - if (d_timings->sync == 3) { - switch (d_timings->misc) { - case 0: new->Flags |= V_NHSYNC | V_NVSYNC; break; - case 1: new->Flags |= V_PHSYNC | V_NVSYNC; break; - case 2: new->Flags |= V_NHSYNC | V_PVSYNC; break; - case 3: new->Flags |= V_PHSYNC | V_PVSYNC; break; - } - } - count++; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Mode from Detailed timing table: %s\n", - new->name); + info->CurrentLayout.displayWidth = pScrn->displayWidth; - RADEONSortModes(&new, &first, &last); - } - } - - /* Search thru standard VESA modes from EDID */ - for (j = 0; j < 8; j++) { - if (ddc->timings2[j].hsize == 0 || ddc->timings2[j].vsize == 0) - continue; - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - /* Ignore all double scan modes */ - if ((ddc->timings2[j].hsize == p->HDisplay) && - (ddc->timings2[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - new = xnfcalloc(1, sizeof (DisplayModeRec)); - memcpy(new, p, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(p->name) + 1); - strcpy(new->name, p->name); - new->status = MODE_OK; - new->type = M_T_DEFAULT; - - count++; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Mode from standard timing table: %s\n", - new->name); - - RADEONSortModes(&new, &first, &last); - break; - } - } - } - } - - /* Search thru established modes from EDID */ - tmp = (ddc->timings1.t1 << 8) | ddc->timings1.t2; - for (j = 0; j < 16; j++) { - if (tmp & (1 << j)) { - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((est_timings[j].hsize == p->HDisplay) && - (est_timings[j].vsize == p->VDisplay)) { - float refresh = - (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; - - if (abs((float)est_timings[j].refresh - refresh) < 1.0) { - /* Is this good enough? */ - new = xnfcalloc(1, sizeof (DisplayModeRec)); - memcpy(new, p, sizeof(DisplayModeRec)); - new->name = xnfalloc(strlen(p->name) + 1); - strcpy(new->name, p->name); - new->status = MODE_OK; - new->type = M_T_DEFAULT; - - count++; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Valid Mode from established timing " - "table: %s\n", new->name); - - RADEONSortModes(&new, &first, &last); - break; - } - } - } - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total of %d mode(s) found.\n", count); - - return first; } -/* XFree86's xf86ValidateModes routine doesn't work well with DDC modes, - * so here is our own validation routine. - */ -int RADEONValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName, - RADEONMonitorType DisplayType, int crtc2) +static DisplayModePtr RADEONTVModes(xf86OutputPtr output) { - 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; - - if (crtc2) - pScrn = info->CRT2pScrn; - - pScrn->virtualX = pScrn1->display->virtualX; - pScrn->virtualY = pScrn1->display->virtualY; - - if (pScrn->monitor->DDC) { - int maxVirtX = pScrn->virtualX; - int maxVirtY = pScrn->virtualY; - - /* Collect all of the DDC modes */ - first = last = ddcModes = RADEONDDCModes(pScrn, pScrn->monitor->DDC); + DisplayModePtr new = NULL; - for (p = ddcModes; p; p = p->next) { + /* just a place holder */ + new = xf86CVTMode(800, 600, 60.00, FALSE, FALSE); + new->type = M_T_DRIVER | M_T_PREFERRED; - /* If primary head is a flat panel, use RMX by default */ - if ((!info->IsSecondary && DisplayType != MT_CRT) && - (!info->ddc_mode) && (!crtc2)) { - /* These values are effective values after expansion. - * They are not really used to set CRTC registers. - */ - p->HTotal = info->PanelXRes + info->HBlank; - p->HSyncStart = info->PanelXRes + info->HOverPlus; - p->HSyncEnd = p->HSyncStart + info->HSyncWidth; - p->VTotal = info->PanelYRes + info->VBlank; - p->VSyncStart = info->PanelYRes + info->VOverPlus; - p->VSyncEnd = p->VSyncStart + info->VSyncWidth; - p->Clock = info->DotClock; - - p->Flags |= RADEON_USE_RMX; - } - - maxVirtX = MAX(maxVirtX, p->HDisplay); - maxVirtY = MAX(maxVirtY, p->VDisplay); - count++; - - last = p; - } - - /* Match up modes that are specified in the XF86Config file */ - if (ppModeName[0]) { - DisplayModePtr next; - - /* Reset the max virtual dimensions */ - maxVirtX = pScrn->virtualX; - maxVirtY = pScrn->virtualY; - - /* Reset list */ - first = last = NULL; - - for (i = 0; ppModeName[i]; i++) { - /* FIXME: Use HDisplay and VDisplay instead of mode string */ - if (sscanf(ppModeName[i], "%dx%d", &width, &height) == 2) { - for (p = ddcModes; p; p = next) { - next = p->next; - - if (p->HDisplay == width && p->VDisplay == height) { - /* We found a DDC mode that matches the one - requested in the XF86Config file */ - p->type |= M_T_USERDEF; - - /* Update the max virtual setttings */ - maxVirtX = MAX(maxVirtX, width); - maxVirtY = MAX(maxVirtY, height); - - /* Unhook from DDC modes */ - if (p->prev) p->prev->next = p->next; - if (p->next) p->next->prev = p->prev; - if (p == ddcModes) ddcModes = p->next; - - /* Add to used modes */ - if (last) { - last->next = p; - p->prev = last; - } else { - first = p; - p->prev = NULL; - } - p->next = NULL; - last = p; - - break; - } - } - } - } - - /* - * Add remaining DDC modes if they're smaller than the user - * specified modes - */ - for (p = ddcModes; p; p = next) { - next = p->next; - if (p->HDisplay <= maxVirtX && p->VDisplay <= maxVirtY) { - /* Unhook from DDC modes */ - if (p->prev) p->prev->next = p->next; - if (p->next) p->next->prev = p->prev; - if (p == ddcModes) ddcModes = p->next; - - /* Add to used modes */ - if (last) { - last->next = p; - p->prev = last; - } else { - first = p; - p->prev = NULL; - } - p->next = NULL; - last = p; - } - } - - /* Delete unused modes */ - while (ddcModes) - xf86DeleteMode(&ddcModes, ddcModes); - } else { - /* - * No modes were configured, so we make the DDC modes - * available for the user to cycle through. - */ - for (p = ddcModes; p; p = p->next) - p->type |= M_T_USERDEF; - } - - 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 */ - if (last) { - last->next = first; - first->prev = last; - pScrn->modes = first; - RADEONSetPitch(pScrn); - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Total number of valid DDC mode(s) found: %d\n", count); - - return count; + return new; } /* This is used only when no mode is specified for FP and no ddc is * available. We force it to native mode, if possible. */ -static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) +static DisplayModePtr RADEONFPNativeMode(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; DisplayModePtr new = NULL; char stmp[32]; - if (info->PanelXRes != 0 && - info->PanelYRes != 0 && - info->DotClock != 0) { + if (radeon_output->PanelXRes != 0 && + radeon_output->PanelYRes != 0 && + radeon_output->DotClock != 0) { /* Add native panel size */ new = xnfcalloc(1, sizeof (DisplayModeRec)); - sprintf(stmp, "%dx%d", info->PanelXRes, info->PanelYRes); + sprintf(stmp, "%dx%d", radeon_output->PanelXRes, radeon_output->PanelYRes); new->name = xnfalloc(strlen(stmp) + 1); strcpy(new->name, stmp); - new->HDisplay = info->PanelXRes; - new->VDisplay = info->PanelYRes; + new->HDisplay = radeon_output->PanelXRes; + new->VDisplay = radeon_output->PanelYRes; - new->HTotal = new->HDisplay + info->HBlank; - new->HSyncStart = new->HDisplay + info->HOverPlus; - new->HSyncEnd = new->HSyncStart + info->HSyncWidth; - new->VTotal = new->VDisplay + info->VBlank; - new->VSyncStart = new->VDisplay + info->VOverPlus; - new->VSyncEnd = new->VSyncStart + info->VSyncWidth; + new->HTotal = new->HDisplay + radeon_output->HBlank; + new->HSyncStart = new->HDisplay + radeon_output->HOverPlus; + new->HSyncEnd = new->HSyncStart + radeon_output->HSyncWidth; + new->VTotal = new->VDisplay + radeon_output->VBlank; + new->VSyncStart = new->VDisplay + radeon_output->VOverPlus; + new->VSyncEnd = new->VSyncStart + radeon_output->VSyncWidth; - new->Clock = info->DotClock; + new->Clock = radeon_output->DotClock; new->Flags = 0; - new->type = M_T_USERDEF; + new->type = M_T_USERDEF | M_T_PREFERRED; new->next = NULL; new->prev = NULL; pScrn->display->virtualX = - pScrn->virtualX = MAX(pScrn->virtualX, info->PanelXRes); + pScrn->virtualX = MAX(pScrn->virtualX, radeon_output->PanelXRes); pScrn->display->virtualY = - pScrn->virtualY = MAX(pScrn->virtualY, info->PanelYRes); + pScrn->virtualY = MAX(pScrn->virtualY, radeon_output->PanelYRes); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No valid mode specified, force to native mode\n"); @@ -486,9 +139,10 @@ static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) /* FP mode initialization routine for using on-chip RMX to scale */ -int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) +int RADEONValidateFPModes(xf86OutputPtr output, char **ppModeName, DisplayModePtr *modeList) { - RADEONInfoPtr info = RADEONPTR(pScrn); + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; DisplayModePtr last = NULL; DisplayModePtr new = NULL; DisplayModePtr first = NULL; @@ -511,13 +165,13 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) * need the internal RMX unit in the video chips (and there is * only one per card), this will only apply to the primary head. */ - if (width < 320 || width > info->PanelXRes || - height < 200 || height > info->PanelYRes) { + if (width < 320 || width > radeon_output->PanelXRes || + height < 200 || height > radeon_output->PanelYRes) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Mode %s is out of range.\n", ppModeName[i]); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Valid modes must be between 320x200-%dx%d\n", - info->PanelXRes, info->PanelYRes); + radeon_output->PanelXRes, radeon_output->PanelYRes); continue; } @@ -530,17 +184,17 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* These values are effective values after expansion They are * not really used to set CRTC registers. */ - new->HTotal = info->PanelXRes + info->HBlank; - new->HSyncStart = info->PanelXRes + info->HOverPlus; - new->HSyncEnd = new->HSyncStart + info->HSyncWidth; - new->VTotal = info->PanelYRes + info->VBlank; - new->VSyncStart = info->PanelYRes + info->VOverPlus; - new->VSyncEnd = new->VSyncStart + info->VSyncWidth; - new->Clock = info->DotClock; + new->HTotal = radeon_output->PanelXRes + radeon_output->HBlank; + new->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus; + new->HSyncEnd = new->HSyncStart + radeon_output->HSyncWidth; + new->VTotal = radeon_output->PanelYRes + radeon_output->VBlank; + new->VSyncStart = radeon_output->PanelYRes + radeon_output->VOverPlus; + new->VSyncEnd = new->VSyncStart + radeon_output->VSyncWidth; + new->Clock = radeon_output->DotClock; new->Flags |= RADEON_USE_RMX; #ifdef M_T_PREFERRED - if (width == info->PanelXRes && height == info->PanelYRes) + if (width == radeon_output->PanelXRes && height == radeon_output->PanelYRes) new->type |= M_T_PREFERRED; #endif @@ -551,7 +205,7 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) if (last) last->next = new; last = new; - if (!first) first = new; + if (!first) first = new; pScrn->display->virtualX = pScrn->virtualX = MAX(pScrn->virtualX, width); @@ -564,13 +218,13 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* If all else fails, add the native mode */ if (!count) { - first = last = RADEONFPNativeMode(pScrn); + first = last = RADEONFPNativeMode(output); if (first) count = 1; } /* add in all default vesa modes smaller than panel size, used for randr*/ - for (p = pScrn->monitor->Modes; p && p->next; p = p->next->next) { - if ((p->HDisplay <= info->PanelXRes) && (p->VDisplay <= info->PanelYRes)) { + for (p = *modeList; p && p->next; p = p->next->next) { + if ((p->HDisplay <= radeon_output->PanelXRes) && (p->VDisplay <= radeon_output->PanelYRes)) { tmp = first; while (tmp) { if ((p->HDisplay == tmp->HDisplay) && (p->VDisplay == tmp->VDisplay)) break; @@ -586,22 +240,19 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* These values are effective values after expansion They are * not really used to set CRTC registers. */ - new->HTotal = info->PanelXRes + info->HBlank; - new->HSyncStart = info->PanelXRes + info->HOverPlus; - new->HSyncEnd = new->HSyncStart + info->HSyncWidth; - new->VTotal = info->PanelYRes + info->VBlank; - new->VSyncStart = info->PanelYRes + info->VOverPlus; - new->VSyncEnd = new->VSyncStart + info->VSyncWidth; - new->Clock = info->DotClock; + new->HTotal = radeon_output->PanelXRes + radeon_output->HBlank; + new->HSyncStart = radeon_output->PanelXRes + radeon_output->HOverPlus; + new->HSyncEnd = new->HSyncStart + radeon_output->HSyncWidth; + new->VTotal = radeon_output->PanelYRes + radeon_output->VBlank; + new->VSyncStart = radeon_output->PanelYRes + radeon_output->VOverPlus; + new->VSyncEnd = new->VSyncStart + radeon_output->VSyncWidth; + new->Clock = radeon_output->DotClock; new->Flags |= RADEON_USE_RMX; new->type |= M_T_DEFAULT; - new->next = NULL; - new->prev = last; - if (last) last->next = new; - last = new; + last = new; if (!first) first = new; } } @@ -609,10 +260,10 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) /* Close the doubly-linked mode list, if we found any usable modes */ if (last) { - last->next = first; - first->prev = last; - pScrn->modes = first; - RADEONSetPitch(pScrn); + last->next = NULL; //first; + first->prev = NULL; //last; + *modeList = first; + //RADEONSetPitch(pScrn); } xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -621,164 +272,66 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName) return count; } - -int RADEONValidateMergeModes(ScrnInfoPtr pScrn1) +DisplayModePtr +RADEONProbeOutputModes(xf86OutputPtr output) { - RADEONInfoPtr info = RADEONPTR(pScrn1); - ClockRangePtr clockRanges; - int modesFound; - ScrnInfoPtr pScrn = info->CRT2pScrn; - - /* 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; - - if (info->NoVirtual) { - pScrn1->display->virtualX = 0; - pScrn1->display->virtualY = 0; - } - - 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->MergeType == MT_CRT); - clockRanges->doubleScanAllowed = (info->MergeType == MT_CRT); - - /* 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 (info->MergeType == MT_CRT && !info->ddc_mode) { - - modesFound = - xf86ValidateModes(pScrn, - pScrn->monitor->Modes, - pScrn1->display->modes, - clockRanges, - NULL, /* linePitches */ - 8 * 64, /* minPitch */ - 8 * 1024, /* maxPitch */ - info->allowColorTiling ? 2048 : - 64 * pScrn1->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn1->display->virtualX ? pScrn1->virtualX : 0, - pScrn1->display->virtualY ? pScrn1->virtualY : 0, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - - if (modesFound == -1) return 0; - - xf86PruneDriverModes(pScrn); - if (!modesFound || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); - return 0; + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + DisplayModePtr mode; + xf86MonPtr edid_mon; + DisplayModePtr modes = NULL; + +#if 0 + /* force reprobe */ + radeon_output->MonType = MT_UNKNOWN; + + RADEONConnectorFindMonitor(pScrn, output); +#endif + ErrorF("in RADEONProbeOutputModes\n"); + + if (output->status == XF86OutputStatusConnected) { + if (radeon_output->type == OUTPUT_DVI || radeon_output->type == OUTPUT_VGA) { + edid_mon = xf86OutputGetEDID (output, radeon_output->pI2CBus); + xf86OutputSetEDID (output, edid_mon); + + modes = xf86OutputGetEDIDModes (output); + return modes; } - - } else { - /* First, free any allocated modes during configuration, since - * we don't need them - */ - while (pScrn->modes) - xf86DeleteMode(&pScrn->modes, pScrn->modes); - while (pScrn->modePool) - xf86DeleteMode(&pScrn->modePool, pScrn->modePool); - - /* Next try to add DDC modes */ - modesFound = RADEONValidateDDCModes(pScrn, pScrn1->display->modes, - info->MergeType, 1); - - /* If that fails and we're connect to a flat panel, then try to - * add the flat panel modes - */ - if (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; + if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) { + modes = RADEONTVModes(output); + return modes; + } + if (radeon_output->type == OUTPUT_LVDS) { + /* okay we got DDC info */ + if (output->MonInfo) { + /* Debug info for now, at least */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %d\n", radeon_output->num); + xf86PrintEDID(output->MonInfo); + + modes = xf86DDCGetModes(pScrn->scrnIndex, output->MonInfo); + + for (mode = modes; mode != NULL; mode = mode->next) { + if (mode->Flags & V_DBLSCAN) { + if ((mode->CrtcHDisplay >= 1024) || (mode->CrtcVDisplay >= 768)) + mode->status = MODE_CLOCK_RANGE; + } } + xf86PruneInvalidModes(pScrn, &modes, TRUE); + + /* do some physcial size stuff */ } - - 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 */ - info->allowColorTiling ? 2048 : - 64 * pScrn1->bitsPerPixel, /* pitchInc */ - 128, /* minHeight */ - info->MaxLines, /* maxHeight */ - pScrn1->display->virtualX, - pScrn1->display->virtualY, - info->FbMapSize, - LOOKUP_BEST_REFRESH); - - } - } - - /* 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; - } - - /* 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"); + + if (modes == NULL) { + RADEONValidateFPModes(output, pScrn->display->modes, &modes); } - return 0; } } - return modesFound; + + if (modes) { + xf86ValidateModesUserConfig(pScrn, modes); + xf86PruneInvalidModes(pScrn, &modes, FALSE); + } + + return modes; } + diff --git a/src/radeon_output.c b/src/radeon_output.c new file mode 100644 index 00000000..4df25972 --- /dev/null +++ b/src/radeon_output.c @@ -0,0 +1,2756 @@ +/* + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, 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, 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_tv.h" + + +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[4] = { + "Unknown", + "Internal", + "External", + "None" +}; + +const char *DDCTypeName[6] = { + "None", + "MONID", + "DVI_DDC", + "VGA_DDC", + "CRT2_DDC", + "LCD_DDC" +}; + +const char *DACTypeName[4] = { + "Unknown", + "Primary", + "TVDAC/ExtDAC", + "None" +}; + +const char *ConnectorTypeName[8] = { + "None", + "Proprietary/LVDS", + "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" +}; + +const char *OutputType[10] = { + "None", + "VGA", + "DVI", + "LVDS", + "S-video", + "Composite", +}; + +static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] = +{ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ + {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ + {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ + {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ + {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ + {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ + {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ + {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */ +}; + +static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output); +static void RADEONUpdatePanelSize(xf86OutputPtr output); +static RADEONMonitorType radeon_detect_tv(ScrnInfoPtr pScrn); +static RADEONMonitorType radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color); +static RADEONMonitorType radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color); +static RADEONMonitorType radeon_detect_ext_dac(ScrnInfoPtr pScrn); +static void RADEONGetTMDSInfoFromTable(xf86OutputPtr output); + +void RADEONPrintPortMap(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONOutputPrivatePtr radeon_output; + xf86OutputPtr output; + int o; + + for (o = 0; o < xf86_config->num_output; o++) { + output = xf86_config->output[o]; + radeon_output = output->driver_private; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Port%d:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n", + o, + MonTypeName[radeon_output->MonType+1], + info->IsAtomBios ? + ConnectorTypeNameATOM[radeon_output->ConnectorType]: + ConnectorTypeName[radeon_output->ConnectorType], + DACTypeName[radeon_output->DACType+1], + TMDSTypeName[radeon_output->TMDSType+1], + DDCTypeName[radeon_output->DDCType]); + } + +} + +static RADEONMonitorType +RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + unsigned long DDCReg; + RADEONMonitorType MonType = MT_NONE; + xf86MonPtr* MonInfo = &output->MonInfo; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONDDCType DDCType = radeon_output->DDCType; + int i, j; + + DDCReg = radeon_output->DDCReg; + + /* Read and output monitor info using DDC2 over I2C bus */ + if (radeon_output->pI2CBus && info->ddc2 && (DDCReg != RADEON_LCD_GPIO_MASK)) { + OUTREG(DDCReg, INREG(DDCReg) & + (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); + + /* For some old monitors (like Compaq Presario FP500), we need + * following process to initialize/stop DDC + */ + OUTREG(DDCReg, INREG(DDCReg) & ~(RADEON_GPIO_EN_1)); + for (j = 0; j < 3; j++) { + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(13000); + + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 10; i++) { + usleep(15000); + if (INREG(DDCReg) & RADEON_GPIO_Y_1) + break; + } + if (i == 10) continue; + + usleep(15000); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1); + usleep(15000); + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, radeon_output->pI2CBus); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1); + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_1)); + for (i = 0; i < 5; i++) { + usleep(15000); + if (INREG(DDCReg) & RADEON_GPIO_Y_1) + break; + } + usleep(15000); + OUTREG(DDCReg, + INREG(DDCReg) & ~(RADEON_GPIO_EN_0)); + usleep(15000); + + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_1); + OUTREG(DDCReg, INREG(DDCReg) | RADEON_GPIO_EN_0); + usleep(15000); + if(*MonInfo) break; + } + } else if (radeon_output->pI2CBus && info->ddc2 && DDCReg == RADEON_LCD_GPIO_MASK) { + *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, radeon_output->pI2CBus); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); + MonType = MT_NONE; + } + + OUTREG(DDCReg, INREG(DDCReg) & + ~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1)); + + if (*MonInfo) { + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_LVDS_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_PROPRIETARY)) { + MonType = MT_LCD; + } else if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D)) { + MonType = MT_DFP; + } else if ((*MonInfo)->rawData[0x14] & 0x80) { /* if it's digital */ + MonType = MT_DFP; + } else { + MonType = MT_CRT; + } + } else MonType = MT_NONE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "DDC Type: %d, Detected Monitor Type: %d\n", DDCType, MonType); + + return MonType; +} + +#if 0 +static RADEONMonitorType +RADEONCrtIsPhysicallyConnected(ScrnInfoPtr pScrn, int IsCrtDac) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + int bConnected = 0; + + /* the monitor either wasn't connected or it is a non-DDC CRT. + * try to probe it + */ + if(IsCrtDac) { + unsigned long ulOrigVCLK_ECP_CNTL; + unsigned long ulOrigDAC_CNTL; + unsigned long ulOrigDAC_MACRO_CNTL; + unsigned long ulOrigDAC_EXT_CNTL; + unsigned long ulOrigCRTC_EXT_CNTL; + unsigned long ulData; + unsigned long ulMask; + + ulOrigVCLK_ECP_CNTL = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + + ulData = ulOrigVCLK_ECP_CNTL; + ulData &= ~(RADEON_PIXCLK_ALWAYS_ONb + | RADEON_PIXCLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIXCLK_ALWAYS_ONb + |RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + ulOrigCRTC_EXT_CNTL = INREG(RADEON_CRTC_EXT_CNTL); + ulData = ulOrigCRTC_EXT_CNTL; + ulData |= RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, ulData); + + ulOrigDAC_EXT_CNTL = INREG(RADEON_DAC_EXT_CNTL); + ulData = ulOrigDAC_EXT_CNTL; + ulData &= ~RADEON_DAC_FORCE_DATA_MASK; + ulData |= (RADEON_DAC_FORCE_BLANK_OFF_EN + |RADEON_DAC_FORCE_DATA_EN + |RADEON_DAC_FORCE_DATA_SEL_MASK); + if ((info->ChipFamily == CHIP_FAMILY_RV250) || + (info->ChipFamily == CHIP_FAMILY_RV280)) + ulData |= (0x01b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + ulData |= (0x01ac << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, ulData); + + /* turn on power so testing can go through */ + ulOrigDAC_CNTL = INREG(RADEON_DAC_CNTL); + ulOrigDAC_CNTL &= ~RADEON_DAC_PDWN; + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL); + + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + + /* Enable comparators and set DAC range to PS2 (VGA) output level */ + ulData = ulOrigDAC_CNTL; + ulData |= RADEON_DAC_CMP_EN; + ulData &= ~RADEON_DAC_RANGE_CNTL_MASK; + ulData |= 0x2; + OUTREG(RADEON_DAC_CNTL, ulData); + + /* Settle down */ + usleep(10000); + + /* Read comparators */ + ulData = INREG(RADEON_DAC_CNTL); + bConnected = (RADEON_DAC_CMP_OUTPUT & ulData)?1:0; + + /* Restore things */ + ulData = ulOrigVCLK_ECP_CNTL; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL, ulData, ulMask); + + OUTREG(RADEON_DAC_CNTL, ulOrigDAC_CNTL ); + OUTREG(RADEON_DAC_EXT_CNTL, ulOrigDAC_EXT_CNTL ); + OUTREG(RADEON_CRTC_EXT_CNTL, ulOrigCRTC_EXT_CNTL); + + if (!bConnected) { + /* Power DAC down if CRT is not connected */ + ulOrigDAC_MACRO_CNTL = INREG(RADEON_DAC_MACRO_CNTL); + ulOrigDAC_MACRO_CNTL |= (RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + OUTREG(RADEON_DAC_MACRO_CNTL, ulOrigDAC_MACRO_CNTL); + + ulData = INREG(RADEON_DAC_CNTL); + ulData |= RADEON_DAC_PDWN; + OUTREG(RADEON_DAC_CNTL, ulData); + } + } else { /* TV DAC */ + + /* This doesn't seem to work reliably (maybe worse on some OEM cards), + for now we always return false. If one wants to connected a + non-DDC monitor on the DVI port when CRT port is also connected, + he will need to explicitly tell the driver in the config file + with Option MonitorLayout. + */ + bConnected = FALSE; + +#if 0 + if (info->ChipFamily == CHIP_FAMILY_R200) { + unsigned long ulOrigGPIO_MONID; + unsigned long ulOrigFP2_GEN_CNTL; + unsigned long ulOrigDISP_OUTPUT_CNTL; + unsigned long ulOrigCRTC2_GEN_CNTL; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_A; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_B; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_C; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_D; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_E; + unsigned long ulOrigDISP_LIN_TRANS_GRPH_F; + unsigned long ulOrigCRTC2_H_TOTAL_DISP; + unsigned long ulOrigCRTC2_V_TOTAL_DISP; + unsigned long ulOrigCRTC2_H_SYNC_STRT_WID; + unsigned long ulOrigCRTC2_V_SYNC_STRT_WID; + unsigned long ulData, i; + + ulOrigGPIO_MONID = INREG(RADEON_GPIO_MONID); + ulOrigFP2_GEN_CNTL = INREG(RADEON_FP2_GEN_CNTL); + ulOrigDISP_OUTPUT_CNTL = INREG(RADEON_DISP_OUTPUT_CNTL); + ulOrigCRTC2_GEN_CNTL = INREG(RADEON_CRTC2_GEN_CNTL); + ulOrigDISP_LIN_TRANS_GRPH_A = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + ulOrigDISP_LIN_TRANS_GRPH_B = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + ulOrigDISP_LIN_TRANS_GRPH_C = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + ulOrigDISP_LIN_TRANS_GRPH_D = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + ulOrigDISP_LIN_TRANS_GRPH_E = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + ulOrigDISP_LIN_TRANS_GRPH_F = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + + ulOrigCRTC2_H_TOTAL_DISP = INREG(RADEON_CRTC2_H_TOTAL_DISP); + ulOrigCRTC2_V_TOTAL_DISP = INREG(RADEON_CRTC2_V_TOTAL_DISP); + ulOrigCRTC2_H_SYNC_STRT_WID = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + ulOrigCRTC2_V_SYNC_STRT_WID = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + ulData = INREG(RADEON_GPIO_MONID); + ulData &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, ulData); + + OUTREG(RADEON_FP2_GEN_CNTL, 0x0a000c0c); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, 0x00000012); + + OUTREG(RADEON_CRTC2_GEN_CNTL, 0x06000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + ulData = INREG(RADEON_GPIO_MONID); + bConnected = (ulData & RADEON_GPIO_Y_0)?1:0; + if (!bConnected) break; + + usleep(1000); + } + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, ulOrigDISP_LIN_TRANS_GRPH_A); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, ulOrigDISP_LIN_TRANS_GRPH_B); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, ulOrigDISP_LIN_TRANS_GRPH_C); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, ulOrigDISP_LIN_TRANS_GRPH_D); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, ulOrigDISP_LIN_TRANS_GRPH_E); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, ulOrigDISP_LIN_TRANS_GRPH_F); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, ulOrigCRTC2_H_TOTAL_DISP); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, ulOrigCRTC2_V_TOTAL_DISP); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, ulOrigCRTC2_H_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, ulOrigCRTC2_V_SYNC_STRT_WID); + OUTREG(RADEON_CRTC2_GEN_CNTL, ulOrigCRTC2_GEN_CNTL); + OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); + OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); + OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); + } else { + unsigned long ulOrigPIXCLKSDATA; + unsigned long ulOrigTV_MASTER_CNTL; + unsigned long ulOrigTV_DAC_CNTL; + unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; + unsigned long ulOrigDAC_CNTL2; + unsigned long ulData; + unsigned long ulMask; + + ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + + ulData = ulOrigPIXCLKSDATA; + ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); + ulData = ulOrigTV_MASTER_CNTL; + ulData &= ~RADEON_TVCLK_ALWAYS_ONb; + OUTREG(RADEON_TV_MASTER_CNTL, ulData); + + ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); + ulData = ulOrigDAC_CNTL2; + ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, ulData); + + ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); + + ulData = 0x00880213; + OUTREG(RADEON_TV_DAC_CNTL, ulData); + + ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + + ulData = (RADEON_Y_RED_EN + | RADEON_C_GRN_EN + | RADEON_CMP_BLU_EN + | RADEON_RED_MX_FORCE_DAC_DATA + | RADEON_GRN_MX_FORCE_DAC_DATA + | RADEON_BLU_MX_FORCE_DAC_DATA); + 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(10000); + + ulData = INREG(RADEON_TV_DAC_CNTL); + bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; + + ulData = ulOrigPIXCLKSDATA; + ulMask = 0xFFFFFFFFL; + OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); + + OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); + OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); + OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); + } +#endif + return MT_UNKNOWN; + } + + return(bConnected ? MT_CRT : MT_NONE); +} +#endif + +/* Primary Head (DVI or Laptop Int. panel)*/ +/* A ddc capable display connected on DVI port */ +/* Secondary Head (mostly VGA, can be DVI on some OEM boards)*/ +void RADEONConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->MonType == MT_UNKNOWN) { + if (radeon_output->type == OUTPUT_STV || radeon_output->type == OUTPUT_CTV) { + if (info->InternalTVOut) { + if (radeon_output->load_detection) + radeon_output->MonType = radeon_detect_tv(pScrn); + else + radeon_output->MonType = MT_NONE; + } + } else { + radeon_output->MonType = RADEONDisplayDDCConnected(pScrn, output); + if (!radeon_output->MonType) { + if (radeon_output->type == OUTPUT_LVDS || radeon_output->type == OUTPUT_DVI) + radeon_output->MonType = RADEONPortCheckNonDDC(pScrn, output); + if (!radeon_output->MonType) { + if (radeon_output->DACType == DAC_PRIMARY) { + if (radeon_output->load_detection) + radeon_output->MonType = radeon_detect_primary_dac(pScrn, TRUE); + } else if (radeon_output->DACType == DAC_TVDAC) { + if (radeon_output->load_detection) { + if (info->ChipFamily == CHIP_FAMILY_R200) + radeon_output->MonType = radeon_detect_ext_dac(pScrn); + else + radeon_output->MonType = radeon_detect_tv_dac(pScrn, TRUE); + } else + radeon_output->MonType = MT_NONE; + } + } + } + } + } + + /* update panel info for RMX */ + if (radeon_output->MonType == MT_LCD || radeon_output->MonType == MT_DFP) + RADEONUpdatePanelSize(output); + + if (output->MonInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID data from the display on connector: %s ----------------------\n", + info->IsAtomBios ? + ConnectorTypeNameATOM[radeon_output->ConnectorType]: + ConnectorTypeName[radeon_output->ConnectorType] + ); + xf86PrintEDID( output->MonInfo ); + } +} + +static RADEONMonitorType RADEONPortCheckNonDDC(ScrnInfoPtr pScrn, xf86OutputPtr output) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONMonitorType MonType = MT_NONE; + + + if (radeon_output->type == OUTPUT_LVDS) { + MonType = MT_LCD; + } else if (radeon_output->type == OUTPUT_DVI) { + if (radeon_output->TMDSType == TMDS_INT) { + if (INREG(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE) + MonType = MT_DFP; + } else if (radeon_output->TMDSType == TMDS_EXT) { + if (INREG(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE) + MonType = MT_DFP; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Detected Monitor Type: %d\n", MonType); + + return MonType; + +} + +static void +radeon_dpms(xf86OutputPtr output, int mode) +{ + switch(mode) { + case DPMSModeOn: + RADEONEnableDisplay(output, TRUE); + break; + case DPMSModeOff: + case DPMSModeSuspend: + case DPMSModeStandby: + RADEONEnableDisplay(output, FALSE); + break; + } +} + +static void +radeon_save(xf86OutputPtr output) +{ + +} + +static void +radeon_restore(xf86OutputPtr restore) +{ + +} + +static int +radeon_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + /* FIXME: Update when more modes are added */ + if (pMode->HDisplay == 800 && pMode->VDisplay == 600) + return MODE_OK; + else + return MODE_CLOCK_RANGE; + } + + if (radeon_output->type != OUTPUT_LVDS) + return MODE_OK; + + if (pMode->HDisplay > radeon_output->PanelXRes || + pMode->VDisplay > radeon_output->PanelYRes) + return MODE_PANEL; + + return MODE_OK; +} + +static Bool +radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (radeon_output->MonType == MT_LCD || radeon_output->MonType == MT_DFP) { + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + if ((mode->HDisplay < radeon_output->PanelXRes || + mode->VDisplay < radeon_output->PanelYRes) && + radeon_crtc->crtc_id == 0) + adjusted_mode->Flags |= RADEON_USE_RMX; + + if (adjusted_mode->Flags & RADEON_USE_RMX) { + adjusted_mode->CrtcHTotal = mode->CrtcHDisplay + radeon_output->HBlank; + adjusted_mode->CrtcHSyncStart = mode->CrtcHDisplay + radeon_output->HOverPlus; + adjusted_mode->CrtcHSyncEnd = mode->CrtcHSyncStart + radeon_output->HSyncWidth; + adjusted_mode->CrtcVTotal = mode->CrtcVDisplay + radeon_output->VBlank; + adjusted_mode->CrtcVSyncStart = mode->CrtcVDisplay + radeon_output->VOverPlus; + adjusted_mode->CrtcVSyncEnd = mode->CrtcVSyncStart + radeon_output->VSyncWidth; + adjusted_mode->Clock = radeon_output->DotClock; + radeon_output->Flags |= RADEON_USE_RMX; + adjusted_mode->Flags = radeon_output->Flags; + } else + radeon_output->Flags &= ~RADEON_USE_RMX; + + } + + return TRUE; +} + +static void +radeon_mode_prepare(xf86OutputPtr output) +{ +} + +static void RADEONInitFPRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + CARD32 tmp = info->SavedReg.tmds_pll_cntl & 0xfffff; + + for (i=0; i<4; i++) { + if (radeon_output->tmds_pll[i].freq == 0) break; + if ((CARD32)(mode->Clock/10) < radeon_output->tmds_pll[i].freq) { + tmp = radeon_output->tmds_pll[i].value ; + break; + } + } + + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RV280)) { + if (tmp & 0xfff00000) + save->tmds_pll_cntl = tmp; + else { + save->tmds_pll_cntl = info->SavedReg.tmds_pll_cntl & 0xfff00000; + save->tmds_pll_cntl |= tmp; + } + } else save->tmds_pll_cntl = tmp; + + save->tmds_transmitter_cntl = info->SavedReg.tmds_transmitter_cntl & + ~(RADEON_TMDS_TRANSMITTER_PLLRST); + + if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_R200) || !pRADEONEnt->HasCRTC2) + save->tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); + else /* weird, RV chips got this bit reversed? */ + save->tmds_transmitter_cntl |= (RADEON_TMDS_TRANSMITTER_PLLEN); + + save->fp_gen_cntl = info->SavedReg.fp_gen_cntl | + (RADEON_FP_CRTC_DONT_SHADOW_VPAR | + RADEON_FP_CRTC_DONT_SHADOW_HEND ); + + save->fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); + + if (pScrn->rgbBits == 8) + save->fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ + else + save->fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ + + + if (IsPrimary) { + 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; + } else { + if ((IS_R300_VARIANT) || (info->ChipFamily == CHIP_FAMILY_R200)) { + save->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; + save->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; + } else + save->fp_gen_cntl |= RADEON_FP_SEL_CRTC2; + } + +} + +static void RADEONInitFP2Registers(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + + if (pScrn->rgbBits == 8) + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl | + RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ + else + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & + ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ + + save->fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); + + if (IsPrimary) { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_EN | + RADEON_FP2_DVO_RATE_SEL_SDR); + if (mode->Flags & RADEON_USE_RMX) + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_SRC_SEL_CRTC2 | + RADEON_FP2_DVO_RATE_SEL_SDR); + } + } else { + if ((info->ChipFamily == CHIP_FAMILY_R200) || 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; + } else { + save->fp2_gen_cntl &= ~(RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; + } + } + +} + +static void RADEONInitLVDSRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + save->lvds_pll_cntl = info->SavedReg.lvds_pll_cntl; + + save->lvds_gen_cntl = info->SavedReg.lvds_gen_cntl; + save->lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; + save->lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON); + + if (IsPrimary) + save->lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; + else + save->lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; + +} + +static void RADEONInitRMXRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int xres = mode->HDisplay; + int yres = mode->VDisplay; + float Hratio, Vratio; + + save->fp_vert_stretch = info->SavedReg.fp_vert_stretch & + RADEON_VERT_STRETCH_RESERVED; + save->fp_horz_stretch = info->SavedReg.fp_horz_stretch & + (RADEON_HORZ_FP_LOOP_STRETCH | + RADEON_HORZ_AUTO_RATIO_INC); + + if (radeon_output->MonType != MT_LCD && radeon_output->MonType != MT_DFP) + return; + + if (radeon_output->PanelXRes == 0 || radeon_output->PanelYRes == 0) { + Hratio = 1.0; + Vratio = 1.0; + } else { + if (xres > radeon_output->PanelXRes) xres = radeon_output->PanelXRes; + if (yres > radeon_output->PanelYRes) yres = radeon_output->PanelYRes; + + Hratio = (float)xres/(float)radeon_output->PanelXRes; + Vratio = (float)yres/(float)radeon_output->PanelYRes; + } + + if (Hratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_horz_stretch |= ((xres/8-1)<<16); + } else { + save->fp_horz_stretch |= ((((unsigned long) + (Hratio * RADEON_HORZ_STRETCH_RATIO_MAX)) & + RADEON_HORZ_STRETCH_RATIO_MASK) | + RADEON_HORZ_STRETCH_BLEND | + RADEON_HORZ_STRETCH_ENABLE | + ((radeon_output->PanelXRes/8-1)<<16)); + } + + if (Vratio == 1.0 || !(mode->Flags & RADEON_USE_RMX)) { + save->fp_vert_stretch |= ((yres-1)<<12); + } else { + save->fp_vert_stretch |= ((((unsigned long)(Vratio * RADEON_VERT_STRETCH_RATIO_MAX)) & + RADEON_VERT_STRETCH_RATIO_MASK) | + RADEON_VERT_STRETCH_ENABLE | + RADEON_VERT_STRETCH_BLEND | + ((radeon_output->PanelYRes-1)<<12)); + } + +} + +static void RADEONInitDACRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (IsPrimary) { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_DAC_SOURCE_MASK; + } else { + save->dac2_cntl = info->SavedReg.dac2_cntl & ~(RADEON_DAC2_DAC_CLK_SEL); + } + } else { + if ((info->ChipFamily == CHIP_FAMILY_R200) || IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_DAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; + } else { + save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC_CLK_SEL; + } + } + save->dac_cntl = (RADEON_DAC_MASK_ALL + | RADEON_DAC_VGA_ADR_EN + | (info->dac6bits ? 0 : RADEON_DAC_8BIT_EN)); + + save->dac_macro_cntl = info->SavedReg.dac_macro_cntl; +} + +/* XXX: fix me */ +static void +RADEONInitTvDacCntl(ScrnInfoPtr pScrn, RADEONSavePtr save) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (info->ChipFamily == CHIP_FAMILY_R420 || + info->ChipFamily == CHIP_FAMILY_RV410) { + save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & + ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + R420_TV_DAC_DACADJ_MASK | + R420_TV_DAC_RDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_GDACPD | + R420_TV_DAC_TVENABLE); + } else { + save->tv_dac_cntl = info->SavedReg.tv_dac_cntl & + ~(RADEON_TV_DAC_STD_MASK | + RADEON_TV_DAC_BGADJ_MASK | + RADEON_TV_DAC_DACADJ_MASK | + RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD | + RADEON_TV_DAC_GDACPD); + } + /* FIXME: doesn't make sense, this just replaces the previous value... */ + save->tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_DAC_STD_PS2); + +} + +static void RADEONInitDAC2Registers(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + + /*0x0028023;*/ + RADEONInitTvDacCntl(pScrn, save); + + if (IS_R300_VARIANT) + save->gpiopad_a = info->SavedReg.gpiopad_a | 1; + + save->dac2_cntl = info->SavedReg.dac2_cntl | RADEON_DAC2_DAC2_CLK_SEL; + + if (IsPrimary) { + if (IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & + ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + } else { + save->disp_hw_debug = info->SavedReg.disp_hw_debug | RADEON_CRT2_DISP1_SEL; + } + } else { + if (IS_R300_VARIANT) { + save->disp_output_cntl = info->SavedReg.disp_output_cntl & + ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + } else if (info->ChipFamily == CHIP_FAMILY_R200) { + save->fp2_gen_cntl = info->SavedReg.fp2_gen_cntl & + ~(R200_FP2_SOURCE_SEL_MASK | + RADEON_FP2_DVO_RATE_SEL_SDR); + save->fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; + } else { + save->disp_hw_debug = info->SavedReg.disp_hw_debug & + ~RADEON_CRT2_DISP1_SEL; + } + } +} + +static void +RADEONInitOutputRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output, + int crtc_num) +{ + Bool IsPrimary = crtc_num == 0 ? TRUE : FALSE; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + if (crtc_num == 0) + RADEONInitRMXRegisters(output, save, mode); + + if (radeon_output->MonType == MT_CRT) { + if (radeon_output->DACType == DAC_PRIMARY) { + RADEONInitDACRegisters(output, save, mode, IsPrimary); + } else { + RADEONInitDAC2Registers(output, save, mode, IsPrimary); + } + } else if (radeon_output->MonType == MT_LCD) { + RADEONInitLVDSRegisters(output, save, mode, IsPrimary); + } else if (radeon_output->MonType == MT_DFP) { + if (radeon_output->TMDSType == TMDS_INT) { + RADEONInitFPRegisters(output, save, mode, IsPrimary); + } else { + RADEONInitFP2Registers(output, save, mode, IsPrimary); + } + } else if (radeon_output->MonType == MT_STV || + radeon_output->MonType == MT_CTV) { + RADEONInitTVRegisters(output, save, mode, IsPrimary); + } +} + +static void +radeon_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + if (radeon_output->type == OUTPUT_DVI && + radeon_output->TMDSType == TMDS_INT) { + if (radeon_output->tmds_pll_table == TMDS_PLL_BIOS) { + if (!RADEONGetTMDSInfoFromBIOS(output)) + RADEONGetTMDSInfoFromTable(output); + } else + RADEONGetTMDSInfoFromTable(output); + } + + RADEONInitOutputRegisters(pScrn, &info->ModeReg, adjusted_mode, output, radeon_crtc->crtc_id); + + if (radeon_crtc->crtc_id == 0) + RADEONRestoreRMXRegisters(pScrn, &info->ModeReg); + + switch(radeon_output->MonType) { + case MT_LCD: + ErrorF("restore LVDS\n"); + RADEONRestoreLVDSRegisters(pScrn, &info->ModeReg); + break; + case MT_DFP: + if (radeon_output->TMDSType == TMDS_INT) { + ErrorF("restore FP\n"); + RADEONRestoreFPRegisters(pScrn, &info->ModeReg); + } else { + ErrorF("restore FP2\n"); + RADEONRestoreFP2Registers(pScrn, &info->ModeReg); + } + break; + case MT_STV: + case MT_CTV: + ErrorF("restore tv\n"); + RADEONRestoreDACRegisters(pScrn, &info->ModeReg); + RADEONRestoreTVRegisters(pScrn, &info->ModeReg); + break; + default: + ErrorF("restore dac\n"); + RADEONRestoreDACRegisters(pScrn, &info->ModeReg); + } + +} + +static void +radeon_mode_commit(xf86OutputPtr output) +{ + RADEONEnableDisplay(output, TRUE); +} + +/* the following functions are based on the load detection code + * in the beos radeon driver by Thomas Kurschel and the existing + * load detection code in this driver. + */ +static RADEONMonitorType +radeon_detect_primary_dac(ScrnInfoPtr pScrn, Bool color) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 vclk_ecp_cntl, crtc_ext_cntl; + CARD32 dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + vclk_ecp_cntl = INPLL(pScrn, RADEON_VCLK_ECP_CNTL); + crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + dac_cntl = INREG(RADEON_DAC_CNTL); + dac_macro_cntl = INREG(RADEON_DAC_MACRO_CNTL); + + tmp = vclk_ecp_cntl & + ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp); + + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + OUTREG(RADEON_CRTC_EXT_CNTL, tmp); + + tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | + RADEON_DAC_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (IS_R300_VARIANT) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); + tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; + OUTREG(RADEON_DAC_CNTL, tmp); + + tmp &= ~(RADEON_DAC_PDWN_R | + RADEON_DAC_PDWN_G | + RADEON_DAC_PDWN_B); + + OUTREG(RADEON_DAC_MACRO_CNTL, tmp); + + usleep(2000); + + if (INREG(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to primary DAC\n", + color ? "color" : "bw"); + } + + /* restore the regs we used */ + OUTREG(RADEON_DAC_CNTL, dac_cntl); + OUTREG(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); + + return found; +} + +static RADEONMonitorType +radeon_detect_ext_dac(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; + CARD32 disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; + CARD32 disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; + CARD32 tmp, crtc2_h_total_disp, crtc2_v_total_disp; + CARD32 crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; + RADEONMonitorType found = MT_NONE; + int connected = 0; + int i = 0; + + /* save the regs we need */ + gpio_monid = INREG(RADEON_GPIO_MONID); + fp2_gen_cntl = INREG(RADEON_FP2_GEN_CNTL); + disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + disp_lin_trans_grph_a = INREG(RADEON_DISP_LIN_TRANS_GRPH_A); + disp_lin_trans_grph_b = INREG(RADEON_DISP_LIN_TRANS_GRPH_B); + disp_lin_trans_grph_c = INREG(RADEON_DISP_LIN_TRANS_GRPH_C); + disp_lin_trans_grph_d = INREG(RADEON_DISP_LIN_TRANS_GRPH_D); + disp_lin_trans_grph_e = INREG(RADEON_DISP_LIN_TRANS_GRPH_E); + disp_lin_trans_grph_f = INREG(RADEON_DISP_LIN_TRANS_GRPH_F); + crtc2_h_total_disp = INREG(RADEON_CRTC2_H_TOTAL_DISP); + crtc2_v_total_disp = INREG(RADEON_CRTC2_V_TOTAL_DISP); + crtc2_h_sync_strt_wid = INREG(RADEON_CRTC2_H_SYNC_STRT_WID); + crtc2_v_sync_strt_wid = INREG(RADEON_CRTC2_V_SYNC_STRT_WID); + + tmp = INREG(RADEON_GPIO_MONID); + tmp &= ~RADEON_GPIO_A_0; + OUTREG(RADEON_GPIO_MONID, tmp); + + OUTREG(RADEON_FP2_GEN_CNTL, + RADEON_FP2_ON | + RADEON_FP2_PANEL_FORMAT | + R200_FP2_SOURCE_SEL_TRANS_UNIT | + RADEON_FP2_DVO_EN | + R200_FP2_DVO_RATE_SEL_SDR); + + OUTREG(RADEON_DISP_OUTPUT_CNTL, + RADEON_DISP_DAC_SOURCE_RMX | + RADEON_DISP_TRANS_MATRIX_GRAPHICS); + + OUTREG(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_EN | + RADEON_CRTC2_DISP_REQ_EN_B); + + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + tmp = INREG(RADEON_GPIO_MONID); + if (tmp & RADEON_GPIO_Y_0) + connected = 1; + else + connected = 0; + + if (!connected) + break; + + usleep(1000); + } + + if (connected) + found = MT_CRT; + + /* restore the regs we used */ + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); + OUTREG(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); + OUTREG(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + OUTREG(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + OUTREG(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + OUTREG(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREG(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + OUTREG(RADEON_GPIO_MONID, gpio_monid); + + return found; +} + +static RADEONMonitorType +radeon_detect_tv_dac(ScrnInfoPtr pScrn, Bool color) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + CARD32 disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + pixclks_cntl = INPLL(pScrn, RADEON_PIXCLKS_CNTL); + gpiopad_a = IS_R300_VARIANT ? INREG(RADEON_GPIOPAD_A) : 0; + disp_output_cntl = IS_R300_VARIANT ? INREG(RADEON_DISP_OUTPUT_CNTL) : 0; + disp_hw_debug = !IS_R300_VARIANT ? INREG(RADEON_DISP_HW_DEBUG) : 0; + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + + tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb + | RADEON_PIX2CLK_DAC_ALWAYS_ONb); + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp); + + if (IS_R300_VARIANT) { + OUTREGP(RADEON_GPIOPAD_A, 1, ~1 ); + } + + tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; + tmp |= RADEON_CRTC2_CRT2_ON | + (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); + + OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); + + if (IS_R300_VARIANT) { + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); + } else { + tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; + OUTREG(RADEON_DISP_HW_DEBUG, tmp); + } + + tmp = RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_PS2; + + OUTREG(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN; + + if (color) + tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; + else + tmp |= RADEON_DAC_FORCE_DATA_SEL_G; + + if (IS_R300_VARIANT) + tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else + tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); + + OUTREG(RADEON_DAC_EXT_CNTL, tmp); + + tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; + OUTREG(RADEON_DAC_CNTL2, tmp); + + usleep(10000); + + if (IS_R300_VARIANT) { + if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to TV DAC\n", + color ? "color" : "bw"); + } + } else { + if (INREG(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) { + found = MT_CRT; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Found %s CRT connected to TV DAC\n", + color ? "color" : "bw"); + } + } + + /* restore regs we used */ + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + + if (IS_R300_VARIANT) { + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1 ); + } else { + OUTREG(RADEON_DISP_HW_DEBUG, disp_hw_debug); + } + OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, pixclks_cntl); + + return found; +} + +static RADEONMonitorType +r300_detect_tv(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp, dac_cntl2, crtc2_gen_cntl, dac_ext_cntl, tv_dac_cntl; + CARD32 gpiopad_a, disp_output_cntl; + RADEONMonitorType found = MT_NONE; + + /* save the regs we need */ + gpiopad_a = INREG(RADEON_GPIOPAD_A); + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL); + dac_ext_cntl = INREG(RADEON_DAC_EXT_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + disp_output_cntl = INREG(RADEON_DISP_OUTPUT_CNTL); + + OUTREGP(RADEON_GPIOPAD_A, 0, ~1 ); + + OUTREG(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL ); + + OUTREG(RADEON_CRTC2_GEN_CNTL, + RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT ); + + tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; + tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; + OUTREG(RADEON_DISP_OUTPUT_CNTL, tmp); + + OUTREG(RADEON_DAC_EXT_CNTL, + RADEON_DAC2_FORCE_BLANK_OFF_EN | + RADEON_DAC2_FORCE_DATA_EN | + RADEON_DAC_FORCE_DATA_SEL_RGB | + (0xec << RADEON_DAC_FORCE_DATA_SHIFT )); + + OUTREG(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT )); + + INREG(RADEON_TV_DAC_CNTL); + + usleep(4000); + + OUTREG(RADEON_TV_DAC_CNTL, + RADEON_TV_DAC_NBLANK | + RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | + RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT) | + (6 << RADEON_TV_DAC_DACADJ_SHIFT )); + + INREG(RADEON_TV_DAC_CNTL); + + usleep(6000); + + tmp = INREG(RADEON_TV_DAC_CNTL); + if ( (tmp & RADEON_TV_DAC_GDACDET) != 0 ) { + found = MT_STV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "S-Video TV connection detected\n"); + } else if ( (tmp & RADEON_TV_DAC_BDACDET) != 0 ) { + found = MT_CTV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Composite TV connection detected\n" ); + } + + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl ); + OUTREG(RADEON_DAC_EXT_CNTL, dac_ext_cntl); + OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + OUTREG(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + OUTREGP(RADEON_GPIOPAD_A, gpiopad_a, ~1); + + return found; +} + +static RADEONMonitorType +radeon_detect_tv(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + CARD32 tmp, dac_cntl2, tv_master_cntl; + CARD32 tv_dac_cntl, tv_pre_dac_mux_cntl, config_cntl; + RADEONMonitorType found = MT_NONE; + + if (IS_R300_VARIANT) + return r300_detect_tv(pScrn); + + /* save the regs we need */ + dac_cntl2 = INREG(RADEON_DAC_CNTL2); + tv_master_cntl = INREG(RADEON_TV_MASTER_CNTL); + tv_dac_cntl = INREG(RADEON_TV_DAC_CNTL); + config_cntl = INREG(RADEON_CONFIG_CNTL); + tv_pre_dac_mux_cntl = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); + + tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL; + OUTREG(RADEON_DAC_CNTL2, tmp); + + tmp = tv_master_cntl | RADEON_TV_ON; + tmp &= ~(RADEON_TV_ASYNC_RST | + RADEON_RESTART_PHASE_FIX | + RADEON_CRT_FIFO_CE_EN | + RADEON_TV_FIFO_CE_EN | + RADEON_RE_SYNC_NOW_SEL_MASK); + tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST; + + OUTREG(RADEON_TV_MASTER_CNTL, tmp); + + tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | + RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC | + (8 << RADEON_TV_DAC_BGADJ_SHIFT); + + if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK) + tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT); + else + tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT); + + OUTREG(RADEON_TV_DAC_CNTL, tmp); + + tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | + RADEON_RED_MX_FORCE_DAC_DATA | + RADEON_GRN_MX_FORCE_DAC_DATA | + RADEON_BLU_MX_FORCE_DAC_DATA | + (0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT); + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tmp); + + usleep(3000); + + tmp = INREG(RADEON_TV_DAC_CNTL); + if (tmp & RADEON_TV_DAC_GDACDET) { + found = MT_STV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "S-Video TV connection detected\n"); + } else if (tmp & RADEON_TV_DAC_BDACDET) { + found = MT_CTV; + xf86DrvMsg (pScrn->scrnIndex, X_INFO, + "Composite TV connection detected\n" ); + } + + OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl); + OUTREG(RADEON_TV_DAC_CNTL, tv_dac_cntl); + OUTREG(RADEON_TV_MASTER_CNTL, tv_master_cntl); + OUTREG(RADEON_DAC_CNTL2, dac_cntl2); + + return found; +} + +static xf86OutputStatus +radeon_detect(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + Bool connected = TRUE; + + radeon_output->MonType = MT_UNKNOWN; + RADEONConnectorFindMonitor(pScrn, output); + + /* force montype based on output property */ + if (radeon_output->type == OUTPUT_DVI) { + if (radeon_output->MonType == MT_NONE) + connected = FALSE; + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I)) { + if (radeon_output->DVIType == DVI_ANALOG) + radeon_output->MonType = MT_CRT; + else if (radeon_output->DVIType == DVI_DIGITAL) + radeon_output->MonType = MT_DFP; + } + } + + /* set montype so users can force outputs on even if detection fails */ + if (radeon_output->MonType == MT_NONE) { + connected = FALSE; + if (radeon_output->type == OUTPUT_LVDS) + radeon_output->MonType = MT_LCD; + else if (radeon_output->type == OUTPUT_VGA) + radeon_output->MonType = MT_CRT; + else if (radeon_output->type == OUTPUT_STV) + radeon_output->MonType = MT_STV; + else if (radeon_output->type == OUTPUT_CTV) + radeon_output->MonType = MT_CTV; + else if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_D)) + radeon_output->MonType = MT_DFP; + } + + if (radeon_output->MonType == MT_UNKNOWN) { + output->subpixel_order = SubPixelUnknown; + return XF86OutputStatusUnknown; + } else { + + switch(radeon_output->MonType) { + case MT_LCD: + case MT_DFP: + output->subpixel_order = SubPixelHorizontalRGB; + break; + default: + output->subpixel_order = SubPixelNone; + break; + } + + if (connected) + return XF86OutputStatusConnected; + else + return XF86OutputStatusDisconnected; + } + +} + +static DisplayModePtr +radeon_get_modes(xf86OutputPtr output) +{ + DisplayModePtr modes; + modes = RADEONProbeOutputModes(output); + return modes; +} + +static void +radeon_destroy (xf86OutputPtr output) +{ + if(output->driver_private) + xfree(output->driver_private); +} + +static void +radeon_set_backlight_level(xf86OutputPtr output, int level) +{ +#if 0 + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char * RADEONMMIO = info->MMIO; + CARD32 lvds_gen_cntl; + + lvds_gen_cntl = INREG(RADEON_LVDS_GEN_CNTL); + lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN; + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= (level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & RADEON_LVDS_BL_MOD_LEVEL_MASK; + //usleep (radeon_output->PanelPwrDly * 1000); + OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN; + //usleep (radeon_output->PanelPwrDly * 1000); + OUTREG(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); +#endif +} + +static Atom backlight_atom; +static Atom tmds_pll_atom; +static Atom rmx_atom; +static Atom monitor_type_atom; +static Atom load_detection_atom; +static Atom tv_hsize_atom; +static Atom tv_hpos_atom; +static Atom tv_vpos_atom; +static Atom tv_std_atom; +#define RADEON_MAX_BACKLIGHT_LEVEL 255 + +static void +radeon_create_resources(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + INT32 range[2]; + int data, err; + const char *s; + + /* backlight control */ + if (radeon_output->type == OUTPUT_LVDS) { + backlight_atom = MAKE_ATOM("backlight"); + + range[0] = 0; + range[1] = RADEON_MAX_BACKLIGHT_LEVEL; + err = RRConfigureOutputProperty(output->randr_output, backlight_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the backlight property */ + //data = (info->SavedReg.lvds_gen_cntl & RADEON_LVDS_BL_MOD_LEVEL_MASK) >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT; + data = RADEON_MAX_BACKLIGHT_LEVEL; + err = RRChangeOutputProperty(output->randr_output, backlight_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->DACType == DAC_PRIMARY || + radeon_output->DACType == DAC_TVDAC) { + load_detection_atom = MAKE_ATOM("load_detection"); + + range[0] = 0; /* off */ + range[1] = 1; /* on */ + err = RRConfigureOutputProperty(output->randr_output, load_detection_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + + if (radeon_output->DACType == DAC_PRIMARY) + data = 1; /* primary dac, only drives vga */ + else if (radeon_output->DACType == DAC_TVDAC && + info->tvdac_use_count < 2) + data = 1; /* only one output with tvdac */ + else + data = 0; /* shared tvdac between vga/dvi/tv */ + + err = RRChangeOutputProperty(output->randr_output, load_detection_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_DVI && + radeon_output->TMDSType == TMDS_INT) { + tmds_pll_atom = MAKE_ATOM("tmds_pll"); + + err = RRConfigureOutputProperty(output->randr_output, tmds_pll_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the property */ +#if defined(__powerpc__) + s = "driver"; +#else + s = "bios"; +#endif + err = RRChangeOutputProperty(output->randr_output, tmds_pll_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + + } + + /* RMX control - fullscreen, centered, keep ratio */ + /* actually more of a crtc property as only crtc1 has rmx */ + if (radeon_output->type == OUTPUT_LVDS || + radeon_output->type == OUTPUT_DVI) { + rmx_atom = MAKE_ATOM("scaler"); + + err = RRConfigureOutputProperty(output->randr_output, rmx_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the property */ + s = "full"; + err = RRChangeOutputProperty(output->randr_output, rmx_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + /* force auto/analog/digital for DVI-I ports */ + if (radeon_output->type == OUTPUT_DVI) { + if ((info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I_ATOM) || + (!info->IsAtomBios && radeon_output->ConnectorType == CONNECTOR_DVI_I)) { + monitor_type_atom = MAKE_ATOM("dvi_monitor_type"); + + err = RRConfigureOutputProperty(output->randr_output, monitor_type_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the backlight property */ + s = "auto"; + err = RRChangeOutputProperty(output->randr_output, monitor_type_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_hsize_atom = MAKE_ATOM("tv_horizontal_size"); + + range[0] = -MAX_H_SIZE; + range[1] = MAX_H_SIZE; + err = RRConfigureOutputProperty(output->randr_output, tv_hsize_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + data = 0; + err = RRChangeOutputProperty(output->randr_output, tv_hsize_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_hpos_atom = MAKE_ATOM("tv_horizontal_position"); + + range[0] = -MAX_H_POSITION; + range[1] = MAX_H_POSITION; + err = RRConfigureOutputProperty(output->randr_output, tv_hpos_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + data = 0; + err = RRChangeOutputProperty(output->randr_output, tv_hpos_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_vpos_atom = MAKE_ATOM("tv_vertical_position"); + + range[0] = -MAX_V_POSITION; + range[1] = MAX_V_POSITION; + err = RRConfigureOutputProperty(output->randr_output, tv_vpos_atom, + FALSE, TRUE, FALSE, 2, range); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + data = 0; + err = RRChangeOutputProperty(output->randr_output, tv_vpos_atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + tv_std_atom = MAKE_ATOM("tv_standard"); + + err = RRConfigureOutputProperty(output->randr_output, tv_std_atom, + FALSE, FALSE, FALSE, 0, NULL); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + /* Set the current value of the backlight property */ + switch (radeon_output->default_tvStd) { + case TV_STD_PAL: + s = "pal"; + break; + case TV_STD_PAL_M: + s = "pal-m"; + break; + case TV_STD_PAL_60: + s = "pal-60"; + break; + case TV_STD_NTSC_J: + s = "ntsc-j"; + break; + case TV_STD_SCART_PAL: + s = "scart-pal"; + break; + case TV_STD_NTSC: + default: + s = "ntsc"; + break; + } + err = RRChangeOutputProperty(output->randr_output, tv_std_atom, + XA_STRING, 8, PropModeReplace, strlen(s), (pointer)s, + FALSE, FALSE); + if (err != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } +} + +static Bool +radeon_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + INT32 val; + + + if (property == backlight_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < 0 || val > RADEON_MAX_BACKLIGHT_LEVEL) + return FALSE; + +#if defined(__powerpc__) + val = RADEON_MAX_BACKLIGHT_LEVEL - val; +#endif + + radeon_set_backlight_level(output, val); + + } else if (property == load_detection_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < 0 || val > 1) + return FALSE; + + radeon_output->load_detection = val; + + } else if (property == rmx_atom) { + xf86CrtcPtr crtc = output->crtc; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + if (radeon_crtc->crtc_id == 0) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("full") && !strncmp("full", s, strlen("full"))) { + return TRUE; + } else if (value->size == strlen("aspect") && !strncmp("aspect", s, strlen("aspect"))) { + return TRUE; + } else if (value->size == strlen("center") && !strncmp("center", s, strlen("center"))) { + return TRUE; + } + return FALSE; + } else { + return FALSE; + } + } else if (property == tmds_pll_atom) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("bios") && !strncmp("bios", s, strlen("bios"))) { + radeon_output->tmds_pll_table = TMDS_PLL_BIOS; + return TRUE; + } else if (value->size == strlen("driver") && !strncmp("driver", s, strlen("driver"))) { + radeon_output->tmds_pll_table = TMDS_PLL_DRIVER; + return TRUE; + } + return FALSE; + } else if (property == monitor_type_atom) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("auto") && !strncmp("auto", s, strlen("auto"))) { + radeon_output->DVIType = DVI_AUTO; + return TRUE; + } else if (value->size == strlen("analog") && !strncmp("analog", s, strlen("analog"))) { + radeon_output->DVIType = DVI_ANALOG; + return TRUE; + } else if (value->size == strlen("digital") && !strncmp("digital", s, strlen("digital"))) { + radeon_output->DVIType = DVI_DIGITAL; + return TRUE; + } + return FALSE; + } else if (property == tv_hsize_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < -MAX_H_SIZE || val > MAX_H_SIZE) + return FALSE; + + radeon_output->hSize = val; + if (radeon_output->tv_on) + RADEONUpdateHVPosition(output, &output->crtc->mode); + return TRUE; + } else if (property == tv_hpos_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < -MAX_H_POSITION || val > MAX_H_POSITION) + return FALSE; + + radeon_output->hPos = val; + if (radeon_output->tv_on) + RADEONUpdateHVPosition(output, &output->crtc->mode); + return TRUE; + } else if (property == tv_vpos_atom) { + if (value->type != XA_INTEGER || + value->format != 32 || + value->size != 1) { + return FALSE; + } + + val = *(INT32 *)value->data; + if (val < -MAX_H_POSITION || val > MAX_H_POSITION) + return FALSE; + + radeon_output->vPos = val; + if (radeon_output->tv_on) + RADEONUpdateHVPosition(output, &output->crtc->mode); + return TRUE; + } else if (property == tv_std_atom) { + const char *s; + if (value->type != XA_STRING || value->format != 8) + return FALSE; + s = (char*)value->data; + if (value->size == strlen("default") && !strncmp("default", s, strlen("default"))) { + radeon_output->tvStd = radeon_output->default_tvStd; + return TRUE; + } else if (value->size == strlen("ntsc") && !strncmp("ntsc", s, strlen("ntsc"))) { + if (radeon_output->SupportedTVStds & TV_STD_NTSC) { + radeon_output->tvStd = TV_STD_NTSC; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("pal") && !strncmp("pal", s, strlen("pal"))) { + if (radeon_output->SupportedTVStds & TV_STD_PAL) { + radeon_output->tvStd = TV_STD_PAL; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("pal-m") && !strncmp("pal-m", s, strlen("pal-m"))) { + if (radeon_output->SupportedTVStds & TV_STD_PAL_M) { + radeon_output->tvStd = TV_STD_PAL_M; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("pal-60") && !strncmp("pal-60", s, strlen("pal-60"))) { + if (radeon_output->SupportedTVStds & TV_STD_PAL_60) { + radeon_output->tvStd = TV_STD_PAL_60; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("ntsc-j") && !strncmp("ntsc-j", s, strlen("ntsc-j"))) { + if (radeon_output->SupportedTVStds & TV_STD_NTSC_J) { + radeon_output->tvStd = TV_STD_NTSC_J; + return TRUE; + } else { + return FALSE; + } + } else if (value->size == strlen("scart-pal") && !strncmp("scart-pal", s, strlen("scart-pal"))) { + if (radeon_output->SupportedTVStds & TV_STD_SCART_PAL) { + radeon_output->tvStd = TV_STD_SCART_PAL; + return TRUE; + } else { + return FALSE; + } + } + return FALSE; + } + + return TRUE; +} + +static const xf86OutputFuncsRec radeon_output_funcs = { + .create_resources = radeon_create_resources, + .dpms = radeon_dpms, + .save = radeon_save, + .restore = radeon_restore, + .mode_valid = radeon_mode_valid, + .mode_fixup = radeon_mode_fixup, + .prepare = radeon_mode_prepare, + .mode_set = radeon_mode_set, + .commit = radeon_mode_commit, + .detect = radeon_detect, + .get_modes = radeon_get_modes, + .set_property = radeon_set_property, + .destroy = radeon_destroy +}; + +void RADEONSetOutputType(ScrnInfoPtr pScrn, RADEONOutputPrivatePtr radeon_output) +{ + RADEONInfoPtr info = RADEONPTR (pScrn); + RADEONOutputType output; + + if (info->IsAtomBios) { + switch(radeon_output->ConnectorType) { + case CONNECTOR_VGA_ATOM: + output = OUTPUT_VGA; break; + case CONNECTOR_DVI_I_ATOM: + case CONNECTOR_DVI_D_ATOM: + case CONNECTOR_DVI_A_ATOM: + output = OUTPUT_DVI; break; + case CONNECTOR_STV_ATOM: + output = OUTPUT_STV; break; + case CONNECTOR_CTV_ATOM: + output = OUTPUT_CTV; break; + case CONNECTOR_LVDS_ATOM: + case CONNECTOR_DIGITAL_ATOM: + output = OUTPUT_LVDS; break; + case CONNECTOR_NONE_ATOM: + case CONNECTOR_UNSUPPORTED_ATOM: + default: + output = OUTPUT_NONE; break; + } + } + else { + switch(radeon_output->ConnectorType) { + case CONNECTOR_PROPRIETARY: + output = OUTPUT_LVDS; break; + case CONNECTOR_CRT: + output = OUTPUT_VGA; break; + case CONNECTOR_DVI_I: + case CONNECTOR_DVI_D: + output = OUTPUT_DVI; break; + case CONNECTOR_CTV: + output = OUTPUT_CTV; break; + case CONNECTOR_STV: + output = OUTPUT_STV; break; + case CONNECTOR_NONE: + case CONNECTOR_UNSUPPORTED: + default: + output = OUTPUT_NONE; break; + } + } + radeon_output->type = output; +} + +static void RADEONI2CGetBits(I2CBusPtr b, int *Clock, int *data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + /* Get the result */ + + if (b->DriverPrivate.uval == RADEON_LCD_GPIO_MASK) { + val = INREG(b->DriverPrivate.uval+4); + *Clock = (val & (1<<13)) != 0; + *data = (val & (1<<12)) != 0; + } else { + val = INREG(b->DriverPrivate.uval); + *Clock = (val & RADEON_GPIO_Y_1) != 0; + *data = (val & RADEON_GPIO_Y_0) != 0; + } +} + +static void RADEONI2CPutBits(I2CBusPtr b, int Clock, int data) +{ + ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned long val; + unsigned char *RADEONMMIO = info->MMIO; + + if (b->DriverPrivate.uval == RADEON_LCD_GPIO_MASK) { + val = INREG(b->DriverPrivate.uval) & (CARD32)~((1<<12) | (1<<13)); + val |= (Clock ? 0:(1<<13)); + val |= (data ? 0:(1<<12)); + OUTREG(b->DriverPrivate.uval, val); + } else { + val = INREG(b->DriverPrivate.uval) & (CARD32)~(RADEON_GPIO_EN_0 | RADEON_GPIO_EN_1); + val |= (Clock ? 0:RADEON_GPIO_EN_1); + val |= (data ? 0:RADEON_GPIO_EN_0); + OUTREG(b->DriverPrivate.uval, val); + } + /* read back to improve reliability on some cards. */ + val = INREG(b->DriverPrivate.uval); +} + +static Bool +RADEONI2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name) +{ + I2CBusPtr pI2CBus; + + pI2CBus = xf86CreateI2CBusRec(); + if (!pI2CBus) return FALSE; + + pI2CBus->BusName = name; + pI2CBus->scrnIndex = pScrn->scrnIndex; + pI2CBus->I2CPutBits = RADEONI2CPutBits; + pI2CBus->I2CGetBits = RADEONI2CGetBits; + pI2CBus->AcknTimeout = 5; + pI2CBus->DriverPrivate.uval = i2c_reg; + + if (!xf86I2CBusInit(pI2CBus)) return FALSE; + + *bus_ptr = pI2CBus; + return TRUE; +} + +static void +RADEONGetPanelInfoFromReg (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + unsigned char *RADEONMMIO = info->MMIO; + CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); + CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); + + radeon_output->PanelPwrDly = 200; + if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { + radeon_output->PanelYRes = ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >> + RADEON_VERT_PANEL_SHIFT) + 1; + } else { + radeon_output->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; + } + if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { + radeon_output->PanelXRes = (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >> + RADEON_HORZ_PANEL_SHIFT) + 1) * 8; + } else { + radeon_output->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; + } + + if ((radeon_output->PanelXRes < 640) || (radeon_output->PanelYRes < 480)) { + radeon_output->PanelXRes = 640; + radeon_output->PanelYRes = 480; + } + + // move this to crtc function + if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { + CARD32 ppll_div_sel, ppll_val; + + ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; + RADEONPllErrataAfterIndex(info); + ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); + if ((ppll_val & 0x000707ff) == 0x1bb) + goto noprobe; + info->FeedbackDivider = ppll_val & 0x7ff; + info->PostDivider = (ppll_val >> 16) & 0x7; + info->RefDivider = info->pll.reference_div; + info->UseBiosDividers = TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Existing panel PLL dividers will be used.\n"); + } + noprobe: + + 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", + radeon_output->PanelXRes, radeon_output->PanelYRes); +} + +/* BIOS may not have right panel size, we search through all supported + * DDC modes looking for the maximum panel size. + */ +static void +RADEONUpdatePanelSize(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int j; + /* XXX: fixme */ + //xf86MonPtr ddc = pScrn->monitor->DDC; + xf86MonPtr ddc = output->MonInfo; + DisplayModePtr p; + + // crtc should handle? + if ((info->UseBiosDividers && radeon_output->DotClock != 0) || (ddc == NULL)) + return; + + /* Go thru detailed timing table first */ + for (j = 0; j < 4; j++) { + if (ddc->det_mon[j].type == 0) { + struct detailed_timings *d_timings = + &ddc->det_mon[j].section.d_timings; + int match = 0; + + /* If we didn't get a panel clock or guessed one, try to match the + * mode with the panel size. We do that because we _need_ a panel + * clock, or ValidateFPModes will fail, even when UseBiosDividers + * is set. + */ + if (radeon_output->DotClock == 0 && + radeon_output->PanelXRes == d_timings->h_active && + radeon_output->PanelYRes == d_timings->v_active) + match = 1; + + /* If we don't have a BIOS provided panel data with fixed dividers, + * check for a larger panel size + */ + if (radeon_output->PanelXRes < d_timings->h_active && + radeon_output->PanelYRes < d_timings->v_active && + !info->UseBiosDividers) + match = 1; + + if (match) { + radeon_output->PanelXRes = d_timings->h_active; + radeon_output->PanelYRes = d_timings->v_active; + radeon_output->DotClock = d_timings->clock / 1000; + radeon_output->HOverPlus = d_timings->h_sync_off; + radeon_output->HSyncWidth = d_timings->h_sync_width; + radeon_output->HBlank = d_timings->h_blanking; + radeon_output->VOverPlus = d_timings->v_sync_off; + radeon_output->VSyncWidth = d_timings->v_sync_width; + radeon_output->VBlank = d_timings->v_blanking; + radeon_output->Flags = (d_timings->interlaced ? V_INTERLACE : 0); + switch (d_timings->misc) { + case 0: radeon_output->Flags |= V_NHSYNC | V_NVSYNC; break; + case 1: radeon_output->Flags |= V_PHSYNC | V_NVSYNC; break; + case 2: radeon_output->Flags |= V_NHSYNC | V_PVSYNC; break; + case 3: radeon_output->Flags |= V_PHSYNC | V_PVSYNC; break; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC detailed: %dx%d\n", + radeon_output->PanelXRes, radeon_output->PanelYRes); + } + } + } + + if (info->UseBiosDividers && radeon_output->DotClock != 0) + return; + + /* Search thru standard VESA modes from EDID */ + for (j = 0; j < 8; j++) { + if ((radeon_output->PanelXRes < ddc->timings2[j].hsize) && + (radeon_output->PanelYRes < ddc->timings2[j].vsize)) { + for (p = pScrn->monitor->Modes; p; p = p->next) { + if ((ddc->timings2[j].hsize == p->HDisplay) && + (ddc->timings2[j].vsize == p->VDisplay)) { + float refresh = + (float)p->Clock * 1000.0 / p->HTotal / p->VTotal; + + if (abs((float)ddc->timings2[j].refresh - refresh) < 1.0) { + /* Is this good enough? */ + radeon_output->PanelXRes = ddc->timings2[j].hsize; + radeon_output->PanelYRes = ddc->timings2[j].vsize; + radeon_output->HBlank = p->HTotal - p->HDisplay; + radeon_output->HOverPlus = p->HSyncStart - p->HDisplay; + radeon_output->HSyncWidth = p->HSyncEnd - p->HSyncStart; + radeon_output->VBlank = p->VTotal - p->VDisplay; + radeon_output->VOverPlus = p->VSyncStart - p->VDisplay; + radeon_output->VSyncWidth = p->VSyncEnd - p->VSyncStart; + radeon_output->DotClock = p->Clock; + radeon_output->Flags = p->Flags; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Panel infos found from DDC VESA/EDID: %dx%d\n", + radeon_output->PanelXRes, radeon_output->PanelYRes); + } + } + } + } + } +} + +static Bool +RADEONGetLVDSInfo (xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + char* s; + + if (!RADEONGetLVDSInfoFromBIOS(output)) + RADEONGetPanelInfoFromReg(output); + + if ((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { + radeon_output->PanelPwrDly = 200; + if (sscanf (s, "%dx%d", &radeon_output->PanelXRes, &radeon_output->PanelYRes) != 2) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); + RADEONGetPanelInfoFromReg(output); + } + } + + /* 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 + * found from EDID data. + */ + RADEONUpdatePanelSize(output); + + if (radeon_output->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 == radeon_output->PanelXRes) && + (tmp_mode->VDisplay == radeon_output->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)) { + radeon_output->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; + radeon_output->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; + radeon_output->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; + radeon_output->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; + radeon_output->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; + radeon_output->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; + radeon_output->DotClock = tmp_mode->Clock; + radeon_output->Flags = 0; + break; + } + } + + tmp_mode = tmp_mode->next; + + if (tmp_mode == pScrn->monitor->Modes) + break; + } + if ((radeon_output->DotClock == 0) && !output->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 +RADEONGetTMDSInfoFromTable(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + + for (i=0; i<4; i++) { + radeon_output->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; + radeon_output->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; + } +} + +static void +RADEONGetTMDSInfo(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int i; + + for (i=0; i<4; i++) { + radeon_output->tmds_pll[i].value = 0; + radeon_output->tmds_pll[i].freq = 0; + } + + if (RADEONGetTMDSInfoFromBIOS(output)) return; + + RADEONGetTMDSInfoFromTable(output); + +} + +static void +RADEONGetTVInfo(xf86OutputPtr output) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + radeon_output->hPos = 0; + radeon_output->vPos = 0; + radeon_output->hSize = 0; + + if (RADEONGetTVInfoFromBIOS(output)) return; + + /* set some reasonable defaults */ + radeon_output->default_tvStd = TV_STD_NTSC; + radeon_output->tvStd = TV_STD_NTSC; + radeon_output->TVRefClk = 27.000000000; + radeon_output->SupportedTVStds = TV_STD_NTSC | TV_STD_PAL; + +} + +void RADEONInitConnector(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int DDCReg = 0; + char* name = (char*) DDCTypeName[radeon_output->DDCType]; + + switch(radeon_output->DDCType) { + case DDC_MONID: DDCReg = RADEON_GPIO_MONID; break; + case DDC_DVI : DDCReg = RADEON_GPIO_DVI_DDC; break; + case DDC_VGA : DDCReg = RADEON_GPIO_VGA_DDC; break; + case DDC_CRT2 : DDCReg = RADEON_GPIO_CRT2_DDC; break; + case DDC_LCD : DDCReg = RADEON_LCD_GPIO_MASK; break; + default: break; + } + + if (radeon_output->DACType == DAC_PRIMARY) + radeon_output->load_detection = 1; /* primary dac, only drives vga */ + else if (radeon_output->DACType == DAC_TVDAC && + info->tvdac_use_count < 2) + radeon_output->load_detection = 1; /* only one output with tvdac */ + else + radeon_output->load_detection = 0; /* shared tvdac between vga/dvi/tv */ + + if (DDCReg) { + radeon_output->DDCReg = DDCReg; + RADEONI2CInit(pScrn, &radeon_output->pI2CBus, DDCReg, name); + } + + if (radeon_output->type == OUTPUT_LVDS) { + RADEONGetLVDSInfo(output); + } + + if (radeon_output->type == OUTPUT_DVI) { + RADEONGetTMDSInfo(output); + } + + if (radeon_output->type == OUTPUT_STV || + radeon_output->type == OUTPUT_CTV) { + RADEONGetTVInfo(output); + } + + if (radeon_output->DACType == DAC_TVDAC) { + radeon_output->tv_on = FALSE; + RADEONGetTVDacAdjInfo(output); + } + +} + +static void RADEONSetupGenericConnectors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (info->IsMobility) { + /* Below is the most common setting, but may not be true */ + if (info->IsIGP) { + info->BiosConnector[0].DDCType = DDC_LCD; + info->BiosConnector[0].DACType = DAC_UNKNOWN; + info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[0].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[0].valid = TRUE; + + /* IGP only has TVDAC */ + if (info->ChipFamily == CHIP_FAMILY_RS400) + info->BiosConnector[1].DDCType = DDC_CRT2; + else + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_TVDAC; + info->BiosConnector[1].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[1].valid = TRUE; + } else { +#if defined(__powerpc__) + info->BiosConnector[0].DDCType = DDC_DVI; +#else + info->BiosConnector[0].DDCType = DDC_LCD; +#endif + info->BiosConnector[0].DACType = DAC_UNKNOWN; + info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[0].ConnectorType = CONNECTOR_PROPRIETARY; + info->BiosConnector[0].valid = TRUE; + + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_PRIMARY; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[1].valid = TRUE; + } + } else { + /* Below is the most common setting, but may not be true */ + if (info->IsIGP) { + if (info->ChipFamily == CHIP_FAMILY_RS400) + info->BiosConnector[0].DDCType = DDC_CRT2; + else + info->BiosConnector[0].DDCType = DDC_VGA; + info->BiosConnector[0].DACType = DAC_TVDAC; + info->BiosConnector[0].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[0].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[0].valid = TRUE; + + /* not sure what a good default DDCType for DVI on + * IGP desktop chips is + */ + info->BiosConnector[1].DDCType = DDC_MONID; /* DDC_DVI? */ + info->BiosConnector[1].DACType = DAC_UNKNOWN; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_DVI_D; + info->BiosConnector[1].valid = TRUE; + } else { + info->BiosConnector[0].DDCType = DDC_DVI; + info->BiosConnector[0].DACType = DAC_TVDAC; + info->BiosConnector[0].TMDSType = TMDS_INT; + info->BiosConnector[0].ConnectorType = CONNECTOR_DVI_I; + info->BiosConnector[0].valid = TRUE; + + info->BiosConnector[1].DDCType = DDC_VGA; + info->BiosConnector[1].DACType = DAC_PRIMARY; + info->BiosConnector[1].TMDSType = TMDS_EXT; + info->BiosConnector[1].ConnectorType = CONNECTOR_CRT; + info->BiosConnector[1].valid = TRUE; + } + } + + if (info->InternalTVOut) { + info->BiosConnector[2].ConnectorType = CONNECTOR_STV; + info->BiosConnector[2].DACType = DAC_TVDAC; + info->BiosConnector[2].TMDSType = TMDS_NONE; + info->BiosConnector[2].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[2].valid = TRUE; + } + + /* Some cards have the DDC lines swapped and we have no way to + * detect it yet (Mac cards) + */ + if (xf86ReturnOptValBool(info->Options, OPTION_REVERSE_DDC, FALSE)) { + info->BiosConnector[0].DDCType = DDC_VGA; + info->BiosConnector[1].DDCType = DDC_DVI; + } + +} + +/* + * initialise the static data sos we don't have to re-do at randr change */ +Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + xf86OutputPtr output; + char *optstr; + int i = 0; + int num_vga = 0; + int num_dvi = 0; + + /* 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. + */ + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + info->BiosConnector[i].valid = FALSE; + info->BiosConnector[i].DDCType = DDC_NONE_DETECTED; + info->BiosConnector[i].DACType = DAC_UNKNOWN; + info->BiosConnector[i].TMDSType = TMDS_UNKNOWN; + info->BiosConnector[i].ConnectorType = CONNECTOR_NONE; + } + + if (xf86ReturnOptValBool(info->Options, OPTION_DEFAULT_CONNECTOR_TABLE, FALSE)) { + RADEONSetupGenericConnectors(pScrn); + } else { + if (!RADEONGetConnectorInfoFromBIOS(pScrn)) + RADEONSetupGenericConnectors(pScrn); + } + + if (info->HasSingleDAC) { + /* For RS300/RS350/RS400 chips, there is no primary DAC. Force VGA port to use TVDAC*/ + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) + info->BiosConnector[i].DACType = DAC_TVDAC; + } + } else if (!pRADEONEnt->HasCRTC2) { + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) + info->BiosConnector[i].DACType = DAC_PRIMARY; + } + } + + /* parse connector table option */ + optstr = (char *)xf86GetOptValString(info->Options, OPTION_CONNECTORTABLE); + + if (optstr) { + for (i = 2; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + info->BiosConnector[i].valid = FALSE; + } + info->BiosConnector[0].valid = TRUE; + info->BiosConnector[1].valid = TRUE; + if (sscanf(optstr, "%u,%d,%d,%u,%u,%d,%d,%u", + &info->BiosConnector[0].DDCType, + &info->BiosConnector[0].DACType, + &info->BiosConnector[0].TMDSType, + &info->BiosConnector[0].ConnectorType, + &info->BiosConnector[1].DDCType, + &info->BiosConnector[1].DACType, + &info->BiosConnector[1].TMDSType, + &info->BiosConnector[1].ConnectorType) != 8) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid ConnectorTable option: %s\n", optstr); + return FALSE; + } + } + + info->tvdac_use_count = 0; + for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + if (info->BiosConnector[i].DACType == DAC_TVDAC) + info->tvdac_use_count++; + + if (info->IsAtomBios) { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A_ATOM)) { + num_dvi++; + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_VGA_ATOM) { + num_vga++; + } + } else { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I)) { + num_dvi++; + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) { + num_vga++; + } + } + } + } + + for (i = 0 ; i < RADEON_MAX_BIOS_CONNECTOR; i++) { + if (info->BiosConnector[i].valid) { + RADEONOutputPrivatePtr radeon_output = xnfcalloc(sizeof(RADEONOutputPrivateRec), 1); + if (!radeon_output) { + return FALSE; + } + radeon_output->MonType = MT_UNKNOWN; + radeon_output->ConnectorType = info->BiosConnector[i].ConnectorType; + radeon_output->DDCType = info->BiosConnector[i].DDCType; + if (info->IsAtomBios) { + if (radeon_output->ConnectorType == CONNECTOR_DVI_D_ATOM) + radeon_output->DACType = DAC_NONE; + else + radeon_output->DACType = info->BiosConnector[i].DACType; + + if (radeon_output->ConnectorType == CONNECTOR_VGA_ATOM) + radeon_output->TMDSType = TMDS_NONE; + else + radeon_output->TMDSType = info->BiosConnector[i].TMDSType; + } else { + if (radeon_output->ConnectorType == CONNECTOR_DVI_D) + radeon_output->DACType = DAC_NONE; + else + radeon_output->DACType = info->BiosConnector[i].DACType; + + if (radeon_output->ConnectorType == CONNECTOR_CRT) + radeon_output->TMDSType = TMDS_NONE; + else + radeon_output->TMDSType = info->BiosConnector[i].TMDSType; + } + RADEONSetOutputType(pScrn, radeon_output); + if (info->IsAtomBios) { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I_ATOM) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_A_ATOM)) { + if (num_dvi > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-1"); + num_dvi--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-0"); + } + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_VGA_ATOM) { + if (num_vga > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-1"); + num_vga--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-0"); + } + } else + output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); + } else { + if ((info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_D) || + (info->BiosConnector[i].ConnectorType == CONNECTOR_DVI_I)) { + if (num_dvi > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-1"); + num_dvi--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "DVI-0"); + } + } else if (info->BiosConnector[i].ConnectorType == CONNECTOR_CRT) { + if (num_vga > 1) { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-1"); + num_vga--; + } else { + output = xf86OutputCreate(pScrn, &radeon_output_funcs, "VGA-0"); + } + } else + output = xf86OutputCreate(pScrn, &radeon_output_funcs, OutputType[radeon_output->type]); + } + + if (!output) { + return FALSE; + } + output->driver_private = radeon_output; + output->possible_crtcs = 1; + /* crtc2 can drive LVDS, it just doesn't have RMX */ + if (radeon_output->type != OUTPUT_LVDS) + output->possible_crtcs |= 2; + + /* we can clone the DACs, and probably TV-out, + but I'm not sure it's worth the trouble */ + output->possible_clones = 0; + + RADEONInitConnector(output); + } + } + + return TRUE; +} + diff --git a/src/radeon_probe.c b/src/radeon_probe.c index 98b35aa6..c697f65c 100644 --- a/src/radeon_probe.c +++ b/src/radeon_probe.c @@ -40,7 +40,6 @@ * Modified by Marc Aurele La France <tsi@xfree86.org> for ATI driver merge. */ -#include "atimodule.h" #include "ativersion.h" #include "radeon_probe.h" @@ -200,7 +199,7 @@ PciChipsets RADEONPciChipsets[] = { int gRADEONEntityIndex = -1; /* Return the options for supported chipset 'n'; NULL otherwise */ -const OptionInfoRec * +_X_EXPORT const OptionInfoRec * RADEONAvailableOptions(int chipid, int busid) { int i; @@ -219,7 +218,7 @@ RADEONAvailableOptions(int chipid, int busid) } /* Return the string name for supported chipset 'n'; NULL otherwise. */ -void +_X_EXPORT void RADEONIdentify(int flags) { xf86PrintChipsets(RADEON_NAME, @@ -228,7 +227,7 @@ RADEONIdentify(int flags) } /* Return TRUE if chipset is present; FALSE otherwise. */ -Bool +_X_EXPORT Bool RADEONProbe(DriverPtr drv, int flags) { int numUsed; @@ -285,22 +284,26 @@ RADEONProbe(DriverPtr drv, int flags) if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], RADEONPciChipsets, 0, 0, 0, 0, 0))) { -#ifdef XFree86LOADER - if (!xf86LoadSubModule(pScrn, "radeon")) { - xf86Msg(X_ERROR, RADEON_NAME - ": Failed to load \"radeon\" module.\n"); - xf86DeleteScreen(pScrn->scrnIndex, 0); - continue; - } - - xf86LoaderReqSymLists(RADEONSymbols, NULL); + 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; - pScrn->Probe = RADEONProbe; - RADEONFillInScreenInfo(pScrn); foundScreen = TRUE; } + xfree(pEnt); pEnt = xf86GetEntityInfo(usedChips[i]); /* create a RADEONEntity for all chips, even with diff --git a/src/radeon_probe.h b/src/radeon_probe.h index b651e7d0..b6ef59dd 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -38,17 +38,28 @@ #include "xf86str.h" #include "xf86DDC.h" +#include "randrstr.h" #define _XF86MISC_SERVER_ #include <X11/extensions/xf86misc.h> +#include "xf86Crtc.h" + +#ifdef USE_EXA +#include "exa.h" +#endif +#ifdef USE_XAA +#include "xaa.h" +#endif + typedef enum { DDC_NONE_DETECTED, DDC_MONID, DDC_DVI, DDC_VGA, - DDC_CRT2 + DDC_CRT2, + DDC_LCD, } RADEONDDCType; typedef enum @@ -92,41 +103,120 @@ typedef enum { DAC_UNKNOWN = -1, DAC_PRIMARY = 0, - DAC_TVDAC = 1 + DAC_TVDAC = 1, + DAC_NONE = 2 } RADEONDacType; typedef enum { TMDS_UNKNOWN = -1, TMDS_INT = 0, - TMDS_EXT = 1 + TMDS_EXT = 1, + TMDS_NONE = 2 } RADEONTmdsType; -typedef struct +typedef enum { - Bool IsUsed; - Bool IsActive; - int binding; // which instance of the driver "owns" this controller - DisplayModePtr pCurMode; -} RADEONController; + DVI_AUTO, + DVI_DIGITAL, + DVI_ANALOG +} RADEONDviType; -typedef struct +typedef enum +{ + TMDS_PLL_BIOS, + TMDS_PLL_DRIVER +} RADEONTMDSPllType; + +typedef struct { + CARD32 freq; + CARD32 value; +}RADEONTMDSPll; + +typedef enum +{ + OUTPUT_NONE, + OUTPUT_VGA, + OUTPUT_DVI, + OUTPUT_LVDS, + OUTPUT_STV, + OUTPUT_CTV, +} RADEONOutputType; + +/* standards */ +typedef enum { + TV_STD_NTSC = 1, + TV_STD_PAL = 2, + TV_STD_PAL_M = 4, + TV_STD_PAL_60 = 8, + TV_STD_NTSC_J = 16, + TV_STD_SCART_PAL = 32, +} TVStd; + +typedef struct _RADEONCrtcPrivateRec { +#ifdef USE_XAA + FBLinearPtr rotate_mem_xaa; +#endif +#ifdef USE_EXA + ExaOffscreenArea *rotate_mem_exa; +#endif + int crtc_id; + int binding; + /* Lookup table values to be set when the CRTC is enabled */ + CARD8 lut_r[256], lut_g[256], lut_b[256]; +} RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr; + +typedef struct { RADEONDDCType DDCType; RADEONDacType DACType; RADEONTmdsType TMDSType; RADEONConnectorType ConnectorType; - RADEONMonitorType MonType; - xf86MonPtr MonInfo; + Bool valid; +} RADEONBIOSConnector; - /* one connector can be bound to one CRTC */ +typedef struct _RADEONOutputPrivateRec { + int num; + RADEONOutputType type; + void *dev_priv; + RADEONDDCType DDCType; + RADEONDacType DACType; + RADEONDviType DVIType; + RADEONTmdsType TMDSType; + RADEONConnectorType ConnectorType; + RADEONMonitorType MonType; int crtc_num; -} RADEONConnector; - - + int DDCReg; + I2CBusPtr pI2CBus; + CARD32 tv_dac_adj; + /* panel stuff */ + int PanelXRes; + int PanelYRes; + int HOverPlus; + int HSyncWidth; + int HBlank; + int VOverPlus; + int VSyncWidth; + int VBlank; + int Flags; /* Saved copy of mode flags */ + int PanelPwrDly; + int DotClock; + RADEONTMDSPll tmds_pll[4]; + RADEONTMDSPllType tmds_pll_table; + /* TV out */ + TVStd default_tvStd; + TVStd tvStd; + int hPos; + int vPos; + int hSize; + float TVRefClk; + int SupportedTVStds; + Bool tv_on; + int load_detection; +} RADEONOutputPrivateRec, *RADEONOutputPrivatePtr; -#define RADEON_MAX_CONNECTOR 2 #define RADEON_MAX_CRTC 2 +#define RADEON_MAX_BIOS_CONNECTOR 8 typedef struct { @@ -139,13 +229,11 @@ typedef struct Bool IsSecondaryRestored; Bool RestorePrimary; - ScrnInfoPtr pSecondaryScrn; - ScrnInfoPtr pPrimaryScrn; - Bool ReversedDAC; /* TVDAC used as primary dac */ Bool ReversedTMDS; /* DDC_DVI is used for external TMDS */ - RADEONConnector *PortInfo[RADEON_MAX_CONNECTOR]; - RADEONController *Controller[RADEON_MAX_CRTC]; /* pointer to a controller */ + xf86CrtcPtr pCrtc[RADEON_MAX_CRTC]; + RADEONCrtcPrivatePtr Controller[RADEON_MAX_CRTC]; + } RADEONEntRec, *RADEONEntPtr; /* radeon_probe.c */ @@ -172,6 +260,4 @@ extern ModeStatus RADEONValidMode(int, DisplayModePtr, Bool, int); extern const OptionInfoRec *RADEONOptionsWeak(void); -extern void RADEONFillInScreenInfo(ScrnInfoPtr); - #endif /* _RADEON_PROBE_H_ */ diff --git a/src/radeon_reg.h b/src/radeon_reg.h index b50fcf0a..af62a692 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -231,7 +231,13 @@ # 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_MC_BUSY (1 << 16) +# define RADEON_DLL_READY (1 << 19) +# define RADEON_CG_NO1_DEBUG_0 (1 << 24) +# define RADEON_CG_NO1_DEBUG_MASK (0x1f << 24) # define RADEON_DYN_STOP_MODE_MASK (7 << 21) +# define RADEON_TVPLL_PWRMGT_OFF (1 << 30) +# define RADEON_TVCLK_TURNOFF (1 << 31) #define RADEON_PLL_PWRMGT_CNTL 0x0015 # define RADEON_TCL_BYPASS_DISABLE (1 << 20) #define RADEON_CLR_CMP_CLR_3D 0x1a24 @@ -308,7 +314,7 @@ # define RADEON_CRTC_CSYNC_EN (1 << 4) # define RADEON_CRTC_ICON_EN (1 << 15) # define RADEON_CRTC_CUR_EN (1 << 16) -# define RADEON_CRTC_CUR_MODE_MASK (7 << 17) +# define RADEON_CRTC_CUR_MODE_MASK (7 << 20) # define RADEON_CRTC_EXT_DISP_EN (1 << 24) # define RADEON_CRTC_EN (1 << 25) # define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) @@ -319,6 +325,8 @@ # define RADEON_CRTC2_HSYNC_TRISTAT (1 << 5) # define RADEON_CRTC2_VSYNC_TRISTAT (1 << 6) # define RADEON_CRTC2_CRT2_ON (1 << 7) +# define RADEON_CRTC2_PIX_WIDTH_SHIFT 8 +# define RADEON_CRTC2_PIX_WIDTH_MASK (0xf << 8) # define RADEON_CRTC2_ICON_EN (1 << 15) # define RADEON_CRTC2_CUR_EN (1 << 16) # define RADEON_CRTC2_CUR_MODE_MASK (7 << 20) @@ -329,8 +337,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) @@ -451,6 +459,7 @@ #define RADEON_DAC_CNTL 0x0058 # define RADEON_DAC_RANGE_CNTL (3 << 0) +# define RADEON_DAC_RANGE_CNTL_PS2 (2 << 0) # define RADEON_DAC_RANGE_CNTL_MASK 0x03 # define RADEON_DAC_BLANKING (1 << 2) # define RADEON_DAC_CMP_EN (1 << 3) @@ -461,13 +470,25 @@ # define RADEON_DAC_PDWN (1 << 15) # define RADEON_DAC_MASK_ALL (0xff << 24) #define RADEON_DAC_CNTL2 0x007c +# define RADEON_DAC2_TV_CLK_SEL (0 << 1) # define RADEON_DAC2_DAC_CLK_SEL (1 << 0) # define RADEON_DAC2_DAC2_CLK_SEL (1 << 1) # define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5) +# define RADEON_DAC2_CMP_EN (1 << 7) +# define RADEON_DAC2_CMP_OUT_R (1 << 8) +# define RADEON_DAC2_CMP_OUT_G (1 << 9) +# define RADEON_DAC2_CMP_OUT_B (1 << 10) +# define RADEON_DAC2_CMP_OUTPUT (1 << 11) #define RADEON_DAC_EXT_CNTL 0x0280 -# define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) -# define RADEON_DAC_FORCE_DATA_EN (1 << 5) +# define RADEON_DAC2_FORCE_BLANK_OFF_EN (1 << 0) +# define RADEON_DAC2_FORCE_DATA_EN (1 << 1) +# define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) +# define RADEON_DAC_FORCE_DATA_EN (1 << 5) # define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_R (0 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_G (1 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_B (2 << 6) +# define RADEON_DAC_FORCE_DATA_SEL_RGB (3 << 6) # define RADEON_DAC_FORCE_DATA_MASK 0x0003ff00 # define RADEON_DAC_FORCE_DATA_SHIFT 8 #define RADEON_DAC_MACRO_CNTL 0x0d04 @@ -480,15 +501,22 @@ # define RADEON_TV_DAC_PEDESTAL (1 << 2) # define RADEON_TV_MONITOR_DETECT_EN (1 << 4) # define RADEON_TV_DAC_CMPOUT (1 << 5) +# define RADEON_TV_DAC_STD_MASK (3 << 8) +# define RADEON_TV_DAC_STD_PAL (0 << 8) # define RADEON_TV_DAC_STD_NTSC (1 << 8) -# define RADEON_TV_DAC_STD_MASK 0x0300 -# define RADEON_TV_DAC_STD_PS2 0x0200 +# define RADEON_TV_DAC_STD_PS2 (2 << 8) +# define RADEON_TV_DAC_STD_RS343 (3 << 8) # define RADEON_TV_DAC_BGSLEEP (1 << 6) # define RADEON_TV_DAC_BGADJ_MASK (0xf << 16) +# define RADEON_TV_DAC_BGADJ_SHIFT 16 # define RADEON_TV_DAC_DACADJ_MASK (0xf << 20) +# define RADEON_TV_DAC_DACADJ_SHIFT 20 # 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_RDACDET (1 << 29) +# define RADEON_TV_DAC_GDACDET (1 << 30) +# define RADEON_TV_DAC_BDACDET (1 << 31) # define R420_TV_DAC_DACADJ_MASK (0x1f << 20) # define R420_TV_DAC_RDACPD (1 << 25) # define R420_TV_DAC_GDACPD (1 << 26) @@ -500,10 +528,18 @@ # define RADEON_DISP_DAC_SOURCE_MASK 0x03 # define RADEON_DISP_DAC2_SOURCE_MASK 0x0c # define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 +# define RADEON_DISP_DAC_SOURCE_RMX 0x02 +# define RADEON_DISP_DAC_SOURCE_LTU 0x03 # define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 -# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03<<2) +# define RADEON_DISP_TVDAC_SOURCE_MASK (0x03 << 2) # define RADEON_DISP_TVDAC_SOURCE_CRTC 0x0 -# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01<<2) +# define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01 << 2) +# define RADEON_DISP_TVDAC_SOURCE_RMX (0x02 << 2) +# define RADEON_DISP_TVDAC_SOURCE_LTU (0x03 << 2) +# define RADEON_DISP_TRANS_MATRIX_MASK (0x03 << 4) +# define RADEON_DISP_TRANS_MATRIX_ALPHA_MSB (0x00 << 4) +# define RADEON_DISP_TRANS_MATRIX_GRAPHICS (0x01 << 4) +# define RADEON_DISP_TRANS_MATRIX_VIDEO (0x02 << 4) # define RADEON_DISP_TV_SOURCE_CRTC (1 << 16) /* crtc1 or crtc2 */ # define RADEON_DISP_TV_SOURCE_LTU (0 << 16) /* linear transform unit */ #define RADEON_DISP_TV_OUT_CNTL 0x0d6c @@ -531,12 +567,12 @@ # define RADEON_DISP_ALPHA_MODE_KEY 0 # define RADEON_DISP_ALPHA_MODE_PER_PIXEL 1 # define RADEON_DISP_ALPHA_MODE_GLOBAL 2 -# define RADEON_DISP_RGB_OFFSET_EN (1<<8) +# define RADEON_DISP_RGB_OFFSET_EN (1 << 8) # define RADEON_DISP_GRPH_ALPHA_MASK (0xff << 16) # define RADEON_DISP_OV0_ALPHA_MASK (0xff << 24) # define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) #define RADEON_DISP2_MERGE_CNTL 0x0d68 -# define RADEON_DISP2_RGB_OFFSET_EN (1<<8) +# define RADEON_DISP2_RGB_OFFSET_EN (1 << 8) #define RADEON_DISP_LIN_TRANS_GRPH_A 0x0d80 #define RADEON_DISP_LIN_TRANS_GRPH_B 0x0d84 #define RADEON_DISP_LIN_TRANS_GRPH_C 0x0d88 @@ -742,10 +778,12 @@ # define RADEON_FP2_BLANK_EN (1 << 1) # define RADEON_FP2_ON (1 << 2) # define RADEON_FP2_PANEL_FORMAT (1 << 3) +# define RADEON_FP2_DETECT_SENSE (1 << 8) # 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 R200_FP2_SOURCE_SEL_TRANS_UNIT (3 << 10) # define RADEON_FP2_SRC_SEL_MASK (3 << 13) # define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) # define RADEON_FP2_FP_POL (1 << 16) @@ -757,6 +795,7 @@ # define RADEON_FP2_CRC_READ_EN (1 << 24) # define RADEON_FP2_DVO_EN (1 << 25) # define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26) +# define R200_FP2_DVO_RATE_SEL_SDR (1 << 27) #define RADEON_FP_H_SYNC_STRT_WID 0x02c4 #define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 #define RADEON_FP_HORZ_STRETCH 0x028c @@ -837,6 +876,7 @@ # define RADEON_HDP_SOFT_RESET (1 << 26) # define RADEON_HDP_APER_CNTL (1 << 23) #define RADEON_HTOTAL_CNTL 0x0009 /* PLL */ +# define RADEON_HTOT_CNTL_VGA_EN (1 << 28) #define RADEON_HTOTAL2_CNTL 0x002e /* PLL */ /* Multimedia I2C bus */ @@ -875,6 +915,9 @@ # define RADEON_LVDS_PANEL_TYPE (1 << 2) # define RADEON_LVDS_PANEL_FORMAT (1 << 3) # define RADEON_LVDS_EN (1 << 7) +# define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 +# define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) +# define RADEON_LVDS_BL_MOD_EN (1 << 16) # define RADEON_LVDS_DIGON (1 << 18) # define RADEON_LVDS_BLON (1 << 19) # define RADEON_LVDS_SEL_CRTC2 (1 << 23) @@ -885,9 +928,6 @@ #define RADEON_MAX_LATENCY 0x0f3f /* PCI */ #define RADEON_MC_AGP_LOCATION 0x014c #define RADEON_MC_FB_LOCATION 0x0148 -#define RADEON_MC_STATUS 0x0150 -# define RADEON_MC_IDLE (1 << 2) -# define R300_MC_IDLE (1 << 4) #define RADEON_DISPLAY_BASE_ADDR 0x23c #define RADEON_DISPLAY2_BASE_ADDR 0x33c #define RADEON_OV0_BASE_ADDR 0x43c @@ -903,27 +943,41 @@ # 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_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 << 15) +#define RADEON_LCD_GPIO_MASK 0x01a0 +#define RADEON_LCD_GPIO_Y_REG 0x01a4 #define RADEON_MDGPIO_A_REG 0x01ac #define RADEON_MDGPIO_EN_REG 0x01b0 #define RADEON_MDGPIO_MASK 0x0198 +#define RADEON_GPIOPAD_A 0x019c #define RADEON_MDGPIO_Y_REG 0x01b4 #define RADEON_MEM_ADDR_CONFIG 0x0148 #define RADEON_MEM_BASE 0x0f10 /* PCI */ #define RADEON_MEM_CNTL 0x0140 # define RADEON_MEM_NUM_CHANNELS_MASK 0x01 -# define RADEON_MEM_USE_B_CH_ONLY (1<<1) -# define RV100_HALF_MODE (1<<3) +# define RADEON_MEM_USE_B_CH_ONLY (1 << 1) +# define RV100_HALF_MODE (1 << 3) # define R300_MEM_NUM_CHANNELS_MASK 0x03 -# define R300_MEM_USE_CD_CH_ONLY (1<<2) +# define R300_MEM_USE_CD_CH_ONLY (1 << 2) #define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */ #define RADEON_MEM_INIT_LAT_TIMER 0x0154 #define RADEON_MEM_INTF_CNTL 0x014c #define RADEON_MEM_SDRAM_MODE_REG 0x0158 +# define RADEON_SDRAM_MODE_MASK 0xffff0000 +# define RADEON_B3MEM_RESET_MASK 0x6fffffff #define RADEON_MEM_STR_CNTL 0x0150 +# define RADEON_MEM_PWRUP_COMPL_A (1 << 0) +# define RADEON_MEM_PWRUP_COMPL_B (1 << 1) +# define R300_MEM_PWRUP_COMPL_C (1 << 2) +# define R300_MEM_PWRUP_COMPL_D (1 << 3) +# define RADEON_MEM_PWRUP_COMPLETE 0x03 +# define R300_MEM_PWRUP_COMPLETE 0x0f +#define RADEON_MC_STATUS 0x0150 +# define RADEON_MC_IDLE (1 << 2) +# define R300_MC_IDLE (1 << 4) #define RADEON_MEM_VGA_RP_SEL 0x003c #define RADEON_MEM_VGA_WP_SEL 0x0038 #define RADEON_MIN_GRANT 0x0f3e /* PCI */ @@ -1040,6 +1094,7 @@ # define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L # define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L # define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L +# define RADEON_REG_LD_CTL_FLIP_READBACK 0x00000010L #define RADEON_OV0_SCALE_CNTL 0x0420 # define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L # define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L @@ -1205,6 +1260,8 @@ #define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ # define RADEON_P2PLL_RESET (1 << 0) # define RADEON_P2PLL_SLEEP (1 << 1) +# define RADEON_P2PLL_PVG_MASK (7 << 11) +# define RADEON_P2PLL_PVG_SHIFT 11 # define RADEON_P2PLL_ATOMIC_UPDATE_EN (1 << 16) # define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17) # define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18) @@ -1245,6 +1302,7 @@ # 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_PLL_MASK_READ_B (1 << 9) #define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ #define RADEON_PMI_DATA 0x0f63 /* PCI */ #define RADEON_PMI_NXT_CAP_PTR 0x0f5d /* PCI */ @@ -1254,6 +1312,8 @@ #define RADEON_PPLL_CNTL 0x0002 /* PLL */ # define RADEON_PPLL_RESET (1 << 0) # define RADEON_PPLL_SLEEP (1 << 1) +# define RADEON_PPLL_PVG_MASK (7 << 11) +# define RADEON_PPLL_PVG_SHIFT 11 # define RADEON_PPLL_ATOMIC_UPDATE_EN (1 << 16) # define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17) # define RADEON_PPLL_ATOMIC_UPDATE_VSYNC (1 << 18) @@ -3056,9 +3116,15 @@ # define RADEON_TV_ASYNC_RST (1 << 0) # define RADEON_CRT_ASYNC_RST (1 << 1) # define RADEON_RESTART_PHASE_FIX (1 << 3) +# define RADEON_TV_FIFO_ASYNC_RST (1 << 4) +# define RADEON_VIN_ASYNC_RST (1 << 5) +# define RADEON_AUD_ASYNC_RST (1 << 6) +# define RADEON_DVS_ASYNC_RST (1 << 7) # define RADEON_CRT_FIFO_CE_EN (1 << 9) # define RADEON_TV_FIFO_CE_EN (1 << 10) +# define RADEON_RE_SYNC_NOW_SEL_MASK (3 << 14) # define RADEON_TVCLK_ALWAYS_ONb (1 << 30) +# define RADEON_TV_ON (1 << 31) #define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 # define RADEON_Y_RED_EN (1 << 0) # define RADEON_C_GRN_EN (1 << 1) @@ -3076,7 +3142,16 @@ # define RADEON_RGB_SRC_SEL_RMX (1 << 8) # define RADEON_RGB_SRC_SEL_CRTC2 (2 << 8) # define RADEON_RGB_CONVERT_BY_PASS (1 << 10) +# define RADEON_UVRAM_READ_MARGIN_SHIFT 16 +# define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20 +# define RADEON_TVOUT_SCALE_EN (1 << 26) #define RADEON_TV_SYNC_CNTL 0x0808 +# define RADEON_SYNC_OE (1 << 0) +# define RADEON_SYNC_OUT (1 << 1) +# define RADEON_SYNC_IN (1 << 2) +# define RADEON_SYNC_PUB (1 << 3) +# define RADEON_SYNC_PD (1 << 4) +# define RADEON_TV_SYNC_IO_DRIVE (1 << 5) #define RADEON_TV_HTOTAL 0x080c #define RADEON_TV_HDISP 0x0810 #define RADEON_TV_HSTART 0x0818 @@ -3092,10 +3167,23 @@ #define RADEON_TV_HOST_READ_DATA 0x0840 #define RADEON_TV_HOST_WRITE_DATA 0x0844 #define RADEON_TV_HOST_RD_WT_CNTL 0x0848 +# define RADEON_HOST_FIFO_RD (1 << 12) +# define RADEON_HOST_FIFO_RD_ACK (1 << 13) +# define RADEON_HOST_FIFO_WT (1 << 14) +# define RADEON_HOST_FIFO_WT_ACK (1 << 15) #define RADEON_TV_VSCALER_CNTL1 0x084c +# define RADEON_UV_INC_MASK 0xffff +# define RADEON_UV_INC_SHIFT 0 +# define RADEON_Y_W_EN (1 << 24) # define RADEON_RESTART_FIELD (1 << 29) /* restart on field 0 */ # define RADEON_Y_DEL_W_SIG_SHIFT 26 #define RADEON_TV_TIMING_CNTL 0x0850 +# define RADEON_H_INC_MASK 0xfff +# define RADEON_H_INC_SHIFT 0 +# define RADEON_REQ_Y_FIRST (1 << 19) +# define RADEON_FORCE_BURST_ALWAYS (1 << 21) +# define RADEON_UV_POST_SCALE_BYPASS (1 << 23) +# define RADEON_UV_OUTPUT_POST_SCALE_SHIFT 24 #define RADEON_TV_VSCALER_CNTL2 0x0854 # define RADEON_DITHER_MODE (1 << 0) # define RADEON_Y_OUTPUT_DITHER_EN (1 << 1) @@ -3103,25 +3191,75 @@ # define RADEON_UV_TO_BUF_DITHER_EN (1 << 3) #define RADEON_TV_Y_FALL_CNTL 0x0858 # define RADEON_Y_FALL_PING_PONG (1 << 16) +# define RADEON_Y_COEF_EN (1 << 17) #define RADEON_TV_Y_RISE_CNTL 0x085c # define RADEON_Y_RISE_PING_PONG (1 << 16) #define RADEON_TV_Y_SAW_TOOTH_CNTL 0x0860 #define RADEON_TV_UPSAMP_AND_GAIN_CNTL 0x0864 +# define RADEON_YUPSAMP_EN (1 << 0) +# define RADEON_UVUPSAMP_EN (1 << 2) #define RADEON_TV_GAIN_LIMIT_SETTINGS 0x0868 +# define RADEON_Y_GAIN_LIMIT_SHIFT 0 +# define RADEON_UV_GAIN_LIMIT_SHIFT 16 #define RADEON_TV_LINEAR_GAIN_SETTINGS 0x086c +# define RADEON_Y_GAIN_SHIFT 0 +# define RADEON_UV_GAIN_SHIFT 16 #define RADEON_TV_MODULATOR_CNTL1 0x0870 +# define RADEON_YFLT_EN (1 << 2) +# define RADEON_UVFLT_EN (1 << 3) # define RADEON_ALT_PHASE_EN (1 << 6) # define RADEON_SYNC_TIP_LEVEL (1 << 7) +# define RADEON_BLANK_LEVEL_SHIFT 8 +# define RADEON_SET_UP_LEVEL_SHIFT 16 +# define RADEON_SLEW_RATE_LIMIT (1 << 23) +# define RADEON_CY_FILT_BLEND_SHIFT 28 #define RADEON_TV_MODULATOR_CNTL2 0x0874 +# define RADEON_TV_U_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_MASK 0x1ff +# define RADEON_TV_V_BURST_LEVEL_SHIFT 16 #define RADEON_TV_CRC_CNTL 0x0890 #define RADEON_TV_UV_ADR 0x08ac +# define RADEON_MAX_UV_ADR_MASK 0x000000ff +# define RADEON_MAX_UV_ADR_SHIFT 0 +# define RADEON_TABLE1_BOT_ADR_MASK 0x0000ff00 +# define RADEON_TABLE1_BOT_ADR_SHIFT 8 +# define RADEON_TABLE3_TOP_ADR_MASK 0x00ff0000 +# define RADEON_TABLE3_TOP_ADR_SHIFT 16 +# define RADEON_HCODE_TABLE_SEL_MASK 0x06000000 +# define RADEON_HCODE_TABLE_SEL_SHIFT 25 +# define RADEON_VCODE_TABLE_SEL_MASK 0x18000000 +# define RADEON_VCODE_TABLE_SEL_SHIFT 27 +# define RADEON_TV_MAX_FIFO_ADDR 0x1a7 +# define RADEON_TV_MAX_FIFO_ADDR_INTERNAL 0x1ff #define RADEON_TV_PLL_FINE_CNTL 0x0020 /* PLL */ #define RADEON_TV_PLL_CNTL 0x0021 /* PLL */ +# define RADEON_TV_M0LO_MASK 0xff +# define RADEON_TV_M0HI_MASK 0x3 +# define RADEON_TV_M0HI_SHIFT 18 +# define RADEON_TV_N0LO_MASK 0xff +# define RADEON_TV_N0LO_SHIFT 8 +# define RADEON_TV_N0HI_MASK 0x3 +# define RADEON_TV_N0HI_SHIFT 21 +# define RADEON_TV_P_MASK 0xf +# define RADEON_TV_P_SHIFT 24 # define RADEON_TV_SLIP_EN (1 << 23) # define RADEON_TV_DTO_EN (1 << 28) #define RADEON_TV_PLL_CNTL1 0x0022 /* PLL */ -# define RADEON_TVPLL_TEST_DIS (1 << 31) -# define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) +# define RADEON_TVPLL_RESET (1 << 1) # define RADEON_TVPLL_SLEEP (1 << 3) # define RADEON_TVPLL_REFCLK_SEL (1 << 4) +# define RADEON_TVPCP_SHIFT 8 +# define RADEON_TVPCP_MASK (7 << 8) +# define RADEON_TVPVG_SHIFT 11 +# define RADEON_TVPVG_MASK (7 << 11) +# define RADEON_TVPDC_SHIFT 14 +# define RADEON_TVPDC_MASK (3 << 14) +# define RADEON_TVPLL_TEST_DIS (1 << 31) +# define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) + +#define RADEON_RS480_UNK_e30 0xe30 +#define RADEON_RS480_UNK_e34 0xe34 +#define RADEON_RS480_UNK_e38 0xe38 +#define RADEON_RS480_UNK_e3c 0xe3c + #endif diff --git a/src/radeon_tv.c b/src/radeon_tv.c new file mode 100644 index 00000000..3a26a0a7 --- /dev/null +++ b/src/radeon_tv.c @@ -0,0 +1,759 @@ +/* + * Integrated TV out support based on the GATOS code by + * Federico Ulivi <fulivi@lycos.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "vgaHW.h" +#include "xf86Modes.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_tv.h" + +/********************************************************************** + * + * ModeConstants + * + * Storage of constants related to a single video mode + * + **********************************************************************/ + +typedef struct +{ + CARD16 horResolution; + CARD16 verResolution; + TVStd standard; + CARD16 horTotal; + CARD16 verTotal; + CARD16 horStart; + CARD16 horSyncStart; + CARD16 verSyncStart; + unsigned defRestart; + CARD16 crtcPLL_N; + CARD8 crtcPLL_M; + CARD8 crtcPLL_postDiv; + unsigned pixToTV; +} TVModeConstants; + +static const CARD16 hor_timing_NTSC[] = +{ + 0x0007, + 0x003f, + 0x0263, + 0x0a24, + 0x2a6b, + 0x0a36, + 0x126d, /* H_TABLE_POS1 */ + 0x1bfe, + 0x1a8f, /* H_TABLE_POS2 */ + 0x1ec7, + 0x3863, + 0x1bfe, + 0x1bfe, + 0x1a2a, + 0x1e95, + 0x0e31, + 0x201b, + 0 +}; + +static const CARD16 vert_timing_NTSC[] = +{ + 0x2001, + 0x200d, + 0x1006, + 0x0c06, + 0x1006, + 0x1818, + 0x21e3, + 0x1006, + 0x0c06, + 0x1006, + 0x1817, + 0x21d4, + 0x0002, + 0 +}; + +static const CARD16 hor_timing_PAL[] = +{ + 0x0007, + 0x0058, + 0x027c, + 0x0a31, + 0x2a77, + 0x0a95, + 0x124f, /* H_TABLE_POS1 */ + 0x1bfe, + 0x1b22, /* H_TABLE_POS2 */ + 0x1ef9, + 0x387c, + 0x1bfe, + 0x1bfe, + 0x1b31, + 0x1eb5, + 0x0e43, + 0x201b, + 0 +}; + +static const CARD16 vert_timing_PAL[] = +{ + 0x2001, + 0x200c, + 0x1005, + 0x0c05, + 0x1005, + 0x1401, + 0x1821, + 0x2240, + 0x1005, + 0x0c05, + 0x1005, + 0x1401, + 0x1822, + 0x2230, + 0x0002, + 0 +}; + +/********************************************************************** + * + * availableModes + * + * Table of all allowed modes for tv output + * + **********************************************************************/ +static const TVModeConstants availableTVModes[] = +{ + { + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_NTSC, /* standard */ + 990, /* horTotal */ + 740, /* verTotal */ + 813, /* horStart */ + 824, /* horSyncStart */ + 632, /* verSyncStart */ + 625592, /* defRestart */ + 592, /* crtcPLL_N */ + 91, /* crtcPLL_M */ + 4, /* crtcPLL_postDiv */ + 1022, /* pixToTV */ + }, + { + 800, /* horResolution */ + 600, /* verResolution */ + TV_STD_PAL, /* standard */ + 1144, /* horTotal */ + 706, /* verTotal */ + 812, /* horStart */ + 824, /* horSyncStart */ + 669, /* verSyncStart */ + 696700, /* defRestart */ + 1382, /* crtcPLL_N */ + 231, /* crtcPLL_M */ + 4, /* crtcPLL_postDiv */ + 759, /* pixToTV */ + } +}; + +#define N_AVAILABLE_MODES (sizeof(availableModes) / sizeof(availableModes[ 0 ])) + +static long YCOEF_value[5] = { 2, 2, 0, 4, 0 }; +static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 }; +static long SLOPE_value[5] = { 1, 2, 2, 4, 8 }; +static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 }; + + +/* Compute F,V,H restarts from default restart position and hPos & vPos + * Return TRUE when code timing table was changed + */ +static Bool RADEONInitTVRestarts(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode) +{ + RADEONOutputPrivatePtr radeon_output = output->driver_private; + int restart; + unsigned hTotal; + unsigned vTotal; + unsigned fTotal; + int vOffset; + int hOffset; + CARD16 p1; + CARD16 p2; + Bool hChanged; + CARD16 hInc; + const TVModeConstants *constPtr; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + hTotal = constPtr->horTotal; + vTotal = constPtr->verTotal; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + fTotal = NTSC_TV_VFTOTAL + 1; + else + fTotal = PAL_TV_VFTOTAL + 1; + + /* Adjust positions 1&2 in hor. code timing table */ + hOffset = radeon_output->hPos * H_POS_UNIT; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) { + p1 = hor_timing_NTSC[ H_TABLE_POS1 ]; + p2 = hor_timing_NTSC[ H_TABLE_POS2 ]; + } else { + p1 = hor_timing_PAL[ H_TABLE_POS1 ]; + p2 = hor_timing_PAL[ H_TABLE_POS2 ]; + } + + + p1 = (CARD16)((int)p1 + hOffset); + p2 = (CARD16)((int)p2 - hOffset); + + hChanged = (p1 != save->h_code_timing[ H_TABLE_POS1 ] || + p2 != save->h_code_timing[ H_TABLE_POS2 ]); + + save->h_code_timing[ H_TABLE_POS1 ] = p1; + save->h_code_timing[ H_TABLE_POS2 ] = p2; + + /* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */ + hOffset = (hOffset * (int)(constPtr->pixToTV)) / 1000; + + /* Adjust restart */ + restart = constPtr->defRestart; + + /* + * Convert vPos TV lines to n. of CRTC pixels + * Be verrrrry careful when mixing signed & unsigned values in C.. + */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + vOffset = ((int)(vTotal * hTotal) * 2 * radeon_output->vPos) / (int)(NTSC_TV_LINES_PER_FRAME); + else + vOffset = ((int)(vTotal * hTotal) * 2 * radeon_output->vPos) / (int)(PAL_TV_LINES_PER_FRAME); + + restart -= vOffset + hOffset; + + ErrorF("computeRestarts: def = %u, h = %d, v = %d, p1=%04x, p2=%04x, restart = %d\n", + constPtr->defRestart , radeon_output->hPos , radeon_output->vPos , p1 , p2 , restart); + + save->tv_hrestart = restart % hTotal; + restart /= hTotal; + save->tv_vrestart = restart % vTotal; + restart /= vTotal; + save->tv_frestart = restart % fTotal; + + ErrorF("computeRestarts: F/H/V=%u,%u,%u\n", + (unsigned)save->tv_frestart, (unsigned)save->tv_vrestart, + (unsigned)save->tv_hrestart); + + /* Compute H_INC from hSize */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + hInc = (CARD16)((int)(constPtr->horResolution * 4096 * NTSC_TV_CLOCK_T) / + (radeon_output->hSize * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE))); + else + hInc = (CARD16)((int)(constPtr->horResolution * 4096 * PAL_TV_CLOCK_T) / + (radeon_output->hSize * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE))); + + save->tv_timing_cntl = (save->tv_timing_cntl & ~RADEON_H_INC_MASK) | + ((CARD32)hInc << RADEON_H_INC_SHIFT); + + ErrorF("computeRestarts: hSize=%d,hInc=%u\n" , radeon_output->hSize , hInc); + + return hChanged; +} + +/* intit TV-out regs */ +void RADEONInitTVRegisters(xf86OutputPtr output, RADEONSavePtr save, + DisplayModePtr mode, BOOL IsPrimary) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned i; + unsigned long vert_space, flicker_removal; + CARD32 tmp; + const TVModeConstants *constPtr; + const CARD16 *hor_timing; + const CARD16 *vert_timing; + + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->tv_crc_cntl = 0; + + save->tv_gain_limit_settings = (0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) | + (0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT); + + save->tv_hdisp = constPtr->horResolution - 1; + save->tv_hstart = constPtr->horStart; + save->tv_htotal = constPtr->horTotal - 1; + + save->tv_linear_gain_settings = (0x100 << RADEON_UV_GAIN_SHIFT) | + (0x100 << RADEON_Y_GAIN_SHIFT); + + save->tv_master_cntl = (RADEON_VIN_ASYNC_RST + | RADEON_CRT_FIFO_CE_EN + | RADEON_TV_FIFO_CE_EN + | RADEON_TV_ON); + + if (!IS_R300_VARIANT) + save->tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) + save->tv_master_cntl |= RADEON_RESTART_PHASE_FIX; + + save->tv_modulator_cntl1 = RADEON_SLEW_RATE_LIMIT + | RADEON_SYNC_TIP_LEVEL + | RADEON_YFLT_EN + | RADEON_UVFLT_EN + | (6 << RADEON_CY_FILT_BLEND_SHIFT); + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) { + save->tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) + | (0x3b << RADEON_BLANK_LEVEL_SHIFT); + save->tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } else if (radeon_output->tvStd == TV_STD_SCART_PAL) { + save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN; + save->tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } else { + save->tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN + | (0x3b << RADEON_SET_UP_LEVEL_SHIFT) + | (0x3b << RADEON_BLANK_LEVEL_SHIFT); + save->tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) | + ((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT); + } + + save->pll_test_cntl = 0; + + save->tv_pre_dac_mux_cntl = (RADEON_Y_RED_EN + | RADEON_C_GRN_EN + | RADEON_CMP_BLU_EN + | RADEON_DAC_DITHER_EN); + + save->tv_rgb_cntl = (RADEON_RGB_DITHER_EN + | RADEON_TVOUT_SCALE_EN + | (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT) + | (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)); + + if (IsPrimary) { + if (radeon_output->Flags & RADEON_USE_RMX) + save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX; + else + save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1; + } else { + save->tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2; + } + + save->tv_sync_cntl = RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE; + + save->tv_sync_size = constPtr->horResolution + 8; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + vert_space = constPtr->verTotal * 2 * 10000 / NTSC_TV_LINES_PER_FRAME; + else + vert_space = constPtr->verTotal * 2 * 10000 / PAL_TV_LINES_PER_FRAME; + + save->tv_vscaler_cntl1 = RADEON_Y_W_EN; + save->tv_vscaler_cntl1 = + (save->tv_vscaler_cntl1 & 0xe3ff0000) | (vert_space * (1 << FRAC_BITS) / 10000); + save->tv_vscaler_cntl1 |= RADEON_RESTART_FIELD; + if (constPtr->horResolution == 1024) + save->tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT); + else + save->tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT); + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + flicker_removal = + (float) constPtr->verTotal * 2.0 / NTSC_TV_LINES_PER_FRAME + 0.5; + else + flicker_removal = + (float) constPtr->verTotal * 2.0 / PAL_TV_LINES_PER_FRAME + 0.5; + + if (flicker_removal < 3) + flicker_removal = 3; + for (i = 0; i < 6; ++i) { + if (flicker_removal == SLOPE_limit[i]) + break; + } + save->tv_y_saw_tooth_cntl = + (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) + 5001) / 10000 / 8 + | ((SLOPE_value[i] * (1 << (FRAC_BITS - 1)) / 8) << 16); + save->tv_y_fall_cntl = + (YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) | + RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) / + 1024; + save->tv_y_rise_cntl = + RADEON_Y_RISE_PING_PONG + | (flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024; + + save->tv_vscaler_cntl2 = ((save->tv_vscaler_cntl2 & 0x00fffff0) + | (0x10 << 24) + | RADEON_DITHER_MODE + | RADEON_Y_OUTPUT_DITHER_EN + | RADEON_UV_OUTPUT_DITHER_EN + | RADEON_UV_TO_BUF_DITHER_EN); + + tmp = (save->tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK; + tmp = ((16384 * 256 * 10) / tmp + 5) / 10; + tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000; + save->tv_timing_cntl = tmp; + + save->tv_dac_cntl = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | (8 << 16) | (6 << 20); + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) + save->tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC; + else + save->tv_dac_cntl |= RADEON_TV_DAC_STD_PAL; + +#if 0 + /* needs fixes for r4xx */ + save->tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | RADEON_TV_DAC_GDACPD + | RADEON_TV_DAC_BDACPD); + + if (radeon_output->MonType == MT_CTV) { + save->tv_dac_cntl &= ~RADEON_TV_DAC_BDACPD; + } + + if (radeon_output->MonType == MT_STV) { + save->tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | + RADEON_TV_DAC_GDACPD); + } +#endif + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J) + save->tv_pll_cntl = (NTSC_TV_PLL_M & RADEON_TV_M0LO_MASK) | + (((NTSC_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | + ((NTSC_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | + (((NTSC_TV_PLL_N >> 8) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | + ((NTSC_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); + else + save->tv_pll_cntl = (PAL_TV_PLL_M & RADEON_TV_M0LO_MASK) | + (((PAL_TV_PLL_M >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) | + ((PAL_TV_PLL_N & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) | + (((PAL_TV_PLL_N >> 8) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) | + ((PAL_TV_PLL_P & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT); + + save->tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK)<< RADEON_TVPCP_SHIFT) | + ((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) | + ((1 & RADEON_TVPDC_MASK)<< RADEON_TVPDC_SHIFT) | + RADEON_TVCLK_SRC_SEL_TVPLL | + RADEON_TVPLL_TEST_DIS); + + save->tv_upsamp_and_gain_cntl = RADEON_YUPSAMP_EN | RADEON_UVUPSAMP_EN; + + save->tv_uv_adr = 0xc8; + + save->tv_vdisp = constPtr->verResolution - 1; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) + save->tv_ftotal = NTSC_TV_VFTOTAL; + else + save->tv_ftotal = PAL_TV_VFTOTAL; + + save->tv_vtotal = constPtr->verTotal - 1; + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) { + hor_timing = hor_timing_NTSC; + } else { + hor_timing = hor_timing_PAL; + } + + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M || + radeon_output->tvStd == TV_STD_PAL_60) { + vert_timing = vert_timing_NTSC; + } else { + vert_timing = vert_timing_PAL; + } + + for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) { + if ((save->h_code_timing[ i ] = hor_timing[ i ]) == 0) + break; + } + + for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) { + if ((save->v_code_timing[ i ] = vert_timing[ i ]) == 0) + break; + } + + /* + * This must be called AFTER loading timing tables as they are modified by this function + */ + RADEONInitTVRestarts(output, save, mode); + + save->dac_cntl &= ~RADEON_DAC_TVO_EN; + + if (IS_R300_VARIANT) + save->gpiopad_a = info->SavedReg.gpiopad_a & ~1; + + if (IsPrimary) { + save->disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; + save->disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC + | RADEON_DISP_TV_SOURCE_CRTC); + if (info->ChipFamily >= CHIP_FAMILY_R200) { + save->disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2; + } else { + save->disp_hw_debug |= RADEON_CRT2_DISP1_SEL; + } + } else { + save->disp_output_cntl &= ~RADEON_DISP_DAC_SOURCE_MASK; + save->disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC; + + if (info->ChipFamily >= CHIP_FAMILY_R200) { + save->disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2; + } else { + save->disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; + } + } +} + + +/* Set hw registers for a new h/v position & h size */ +void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode) +{ + ScrnInfoPtr pScrn = output->scrn; + RADEONInfoPtr info = RADEONPTR(pScrn); + unsigned char *RADEONMMIO = info->MMIO; + Bool reloadTable; + RADEONSavePtr restore = &info->ModeReg; + + reloadTable = RADEONInitTVRestarts(output, restore, mode); + + RADEONRestoreTVRestarts(pScrn, restore); + + OUTREG(RADEON_TV_TIMING_CNTL, restore->tv_timing_cntl); + + if (reloadTable) { + OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl + | RADEON_TV_ASYNC_RST + | RADEON_CRT_ASYNC_RST + | RADEON_RESTART_PHASE_FIX); + + RADEONRestoreTVTimingTables(pScrn, restore); + + OUTREG(RADEON_TV_MASTER_CNTL, restore->tv_master_cntl); + } +} + +void RADEONAdjustCrtcRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->crtc_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | + (((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); + + save->crtc_h_sync_strt_wid = (save->crtc_h_sync_strt_wid + & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) | + (((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | + (constPtr->horSyncStart & 7); + + save->crtc_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | + ((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT); + + save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) | + ((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); + +} + +void RADEONAdjustPLLRegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + unsigned postDiv; + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->htotal_cntl = (constPtr->horTotal & 0x7 /*0xf*/) | RADEON_HTOT_CNTL_VGA_EN; + + save->ppll_ref_div = constPtr->crtcPLL_M; + + switch (constPtr->crtcPLL_postDiv) { + case 1: + postDiv = 0; + break; + case 2: + postDiv = 1; + break; + case 3: + postDiv = 4; + break; + case 4: + postDiv = 2; + break; + case 6: + postDiv = 6; + break; + case 8: + postDiv = 3; + break; + case 12: + postDiv = 7; + break; + case 16: + default: + postDiv = 5; + break; + } + + save->ppll_div_3 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16); + + save->pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL); + save->pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK; + +} + +void RADEONAdjustCrtc2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->crtc2_h_total_disp = (((constPtr->horResolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) | + (((constPtr->horTotal / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT); + + save->crtc2_h_sync_strt_wid = (save->crtc2_h_sync_strt_wid + & ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR)) | + (((constPtr->horSyncStart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) | + (constPtr->horSyncStart & 7); + + save->crtc2_v_total_disp = ((constPtr->verResolution - 1) << RADEON_CRTC_V_DISP_SHIFT) | + ((constPtr->verTotal - 1) << RADEON_CRTC_V_TOTAL_SHIFT); + + save->crtc_v_sync_strt_wid = (save->crtc_v_sync_strt_wid & ~RADEON_CRTC_V_SYNC_STRT) | + ((constPtr->verSyncStart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT); + +} + +void RADEONAdjustPLL2RegistersForTV(ScrnInfoPtr pScrn, RADEONSavePtr save, + DisplayModePtr mode, xf86OutputPtr output) +{ + unsigned postDiv; + const TVModeConstants *constPtr; + RADEONOutputPrivatePtr radeon_output = output->driver_private; + + /* FIXME: need to revisit this when we add more modes */ + if (radeon_output->tvStd == TV_STD_NTSC || + radeon_output->tvStd == TV_STD_NTSC_J || + radeon_output->tvStd == TV_STD_PAL_M) + constPtr = &availableTVModes[0]; + else + constPtr = &availableTVModes[1]; + + save->htotal_cntl2 = (constPtr->horTotal & 0x7); /* 0xf */ + + save->p2pll_ref_div = constPtr->crtcPLL_M; + + switch (constPtr->crtcPLL_postDiv) { + case 1: + postDiv = 0; + break; + case 2: + postDiv = 1; + break; + case 3: + postDiv = 4; + break; + case 4: + postDiv = 2; + break; + case 6: + postDiv = 6; + break; + case 8: + postDiv = 3; + break; + case 12: + postDiv = 7; + break; + case 16: + default: + postDiv = 5; + break; + } + + save->p2pll_div_0 = (constPtr->crtcPLL_N & 0x7ff) | (postDiv << 16); + + save->pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK; + save->pixclks_cntl |= (RADEON_PIX2CLK_SRC_SEL_P2PLLCLK + | RADEON_PIXCLK_TV_SRC_SEL); + +} diff --git a/src/radeon_tv.h b/src/radeon_tv.h new file mode 100644 index 00000000..5c8c8c97 --- /dev/null +++ b/src/radeon_tv.h @@ -0,0 +1,56 @@ +/* + * Integrated TV out support based on the GATOS code by + * Federico Ulivi <fulivi@lycos.com> + */ + +/* + * Maximum length of horizontal/vertical code timing tables for state storage + */ +#define MAX_H_CODE_TIMING_LEN 32 +#define MAX_V_CODE_TIMING_LEN 32 + +/* + * Limits of h/v positions (hPos & vPos) + */ +#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */ +#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */ + +/* + * Unit for hPos (in TV clock periods) + */ +#define H_POS_UNIT 10 + +/* + * Indexes in h. code timing table for horizontal line position adjustment + */ +#define H_TABLE_POS1 6 +#define H_TABLE_POS2 8 + +/* + * Limits of hor. size (hSize) + */ +#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */ + +/* tv standard constants */ +#define NTSC_TV_PLL_M 22 +#define NTSC_TV_PLL_N 175 +#define NTSC_TV_PLL_P 5 +#define NTSC_TV_CLOCK_T 233 +#define NTSC_TV_VFTOTAL 1 +#define NTSC_TV_LINES_PER_FRAME 525 +#define NTSC_TV_ZERO_H_SIZE 479166 +#define NTSC_TV_H_SIZE_UNIT 9478 + +#define PAL_TV_PLL_M 113 +#define PAL_TV_PLL_N 668 +#define PAL_TV_PLL_P 3 +#define PAL_TV_CLOCK_T 188 +#define PAL_TV_VFTOTAL 3 +#define PAL_TV_LINES_PER_FRAME 625 +#define PAL_TV_ZERO_H_SIZE 473200 +#define PAL_TV_H_SIZE_UNIT 9360 + + +#define VERT_LEAD_IN_LINES 2 +#define FRAC_BITS 0xe +#define FRAC_MASK 0x3fff diff --git a/src/radeon_version.h b/src/radeon_version.h index a1b24590..ccc1367a 100644 --- a/src/radeon_version.h +++ b/src/radeon_version.h @@ -41,7 +41,7 @@ #define RADEON_VERSION_MAJOR 4 #define RADEON_VERSION_MAJOR_TILED 5 -#define RADEON_VERSION_MINOR 2 +#define RADEON_VERSION_MINOR 3 #define RADEON_VERSION_PATCH 0 #ifndef RADEON_VERSION_EXTRA diff --git a/src/radeon_video.c b/src/radeon_video.c index 390df892..271f7fe8 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -12,7 +12,6 @@ #include "radeon_reg.h" #include "radeon_macros.h" #include "radeon_probe.h" -#include "radeon_mergedfb.h" #include "radeon_video.h" #include "xf86.h" @@ -100,14 +99,14 @@ static void RADEON_TDA9885_SetEncoding(RADEONPortPrivPtr pPriv); static void RADEON_FI1236_SetEncoding(RADEONPortPrivPtr pPriv); -#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; +static Atom xvCRTC; static Atom xvEncoding, xvFrequency, xvVolume, xvMute, xvDecBrightness, xvDecContrast, xvDecHue, xvDecColor, xvDecSaturation, xvTunerStatus, xvSAP, xvOverlayDeinterlacingMethod, @@ -120,6 +119,114 @@ static Atom xvOvAlpha, xvGrAlpha, xvAlphaMode; #define GET_PORT_PRIVATE(pScrn) \ (RADEONPortPrivPtr)((RADEONPTR(pScrn))->adaptor->pPortPrivates[0].ptr) +static void +radeon_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) +{ + dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; + dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; + dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; + + if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; +} + +static void +radeon_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->enabled) { + crtc_box->x1 = crtc->x; + crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); + crtc_box->y1 = crtc->y; + crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static int +radeon_box_area(BoxPtr box) +{ + return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1); +} + +static xf86CrtcPtr +radeon_covering_crtc(ScrnInfoPtr pScrn, + BoxPtr box, + xf86CrtcPtr desired, + BoxPtr crtc_box_ret) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + crtc_box_ret->x1 = 0; + crtc_box_ret->x2 = 0; + crtc_box_ret->y1 = 0; + crtc_box_ret->y2 = 0; + for (c = 0; c < xf86_config->num_crtc; c++) { + crtc = xf86_config->crtc[c]; + radeon_crtc_box(crtc, &crtc_box); + radeon_box_intersect(&cover_box, &crtc_box, box); + coverage = radeon_box_area(&cover_box); + if (coverage && crtc == desired) { + *crtc_box_ret = crtc_box; + return crtc; + } else if (coverage > best_coverage) { + *crtc_box_ret = crtc_box; + best_crtc = crtc; + best_coverage = coverage; + } + } + return best_crtc; +} + +static Bool +radeon_clip_video_helper(ScrnInfoPtr pScrn, + xf86CrtcPtr *crtc_ret, + xf86CrtcPtr desired_crtc, + BoxPtr dst, + INT32 *xa, + INT32 *xb, + INT32 *ya, + INT32 *yb, + RegionPtr reg, + INT32 width, + INT32 height) +{ + Bool ret; + RegionRec crtc_region_local; + RegionPtr crtc_region = reg; + + /* + * For overlay video, compute the relevant CRTC and + * clip video to that + */ + if (crtc_ret) { + BoxRec crtc_box; + xf86CrtcPtr crtc = radeon_covering_crtc(pScrn, dst, + desired_crtc, + &crtc_box); + + if (crtc) { + REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); + crtc_region = &crtc_region_local; + REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); + } + *crtc_ret = crtc; + } + + ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, + crtc_region, width, height); + + if (crtc_region != reg) + REGION_UNINIT (pScreen, &crtc_region_local); + + return ret; +} #ifdef USE_EXA static void @@ -227,7 +334,7 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = {XvSettable | XvGettable, -1000, 1000, "XV_RED_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_GREEN_INTENSITY"}, {XvSettable | XvGettable, -1000, 1000, "XV_BLUE_INTENSITY"}, - {XvSettable | XvGettable, 0, 1, "XV_SWITCHCRT"}, + {XvSettable | XvGettable, -1, 1, "XV_CRTC"}, {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, }; @@ -258,7 +365,7 @@ static XF86AttributeRec Attributes[NUM_DEC_ATTRIBUTES+1] = {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, -1, 1, "XV_CRTC"}, {XvSettable | XvGettable, 100, 10000, "XV_GAMMA"}, {XvSettable | XvGettable, 0, 1, "XV_COLORSPACE"}, @@ -1083,7 +1190,7 @@ RADEONResetVideo(ScrnInfoPtr pScrn) xvAutopaintColorkey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY"); xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS"); - xvSwitchCRT = MAKE_ATOM("XV_SWITCHCRT"); + xvCRTC = MAKE_ATOM("XV_CRTC"); xvOvAlpha = MAKE_ATOM("XV_OVERLAY_ALPHA"); xvGrAlpha = MAKE_ATOM("XV_GRAPHICS_ALPHA"); @@ -1189,17 +1296,10 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) /* Go and find Rage Theatre, if it exists */ - switch(info->Chipset){ - case PCI_CHIP_RADEON_LY: - case PCI_CHIP_RADEON_LZ: - xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M6, not scanning for Rage Theatre\n"); - break; - case PCI_CHIP_RADEON_LW: - xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M7, not scanning for Rage Theatre\n"); - break; - default: - pPriv->theatre=xf86_DetectTheatre(pPriv->VIP); - } + if (info->IsMobility) + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility, not scanning for Rage Theatre\n"); + else + pPriv->theatre=xf86_DetectTheatre(pPriv->VIP); if(pPriv->theatre==NULL)return; @@ -1225,21 +1325,21 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) } else { t->wComp0Connector=RT_COMP1; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %ld\n", t->wComp0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Composite connector is port %u\n", (unsigned)t->wComp0Connector); break; case 3: if(a & 0x4){ t->wSVideo0Connector=RT_YCR_COMP4; } else { t->wSVideo0Connector=RT_YCF_COMP4; } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %ld\n", t->wSVideo0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SVideo connector is port %u\n", (unsigned)t->wSVideo0Connector); break; default: break; } } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%ld, composite=%ld, svideo=%ld\n", - t->wTunerConnector, t->wComp0Connector, t->wSVideo0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Rage Theatre: Connectors (detected): tuner=%u, composite=%u, svideo=%u\n", + (unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector); } @@ -1247,8 +1347,8 @@ static void RADEONSetupTheatre(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) if(info->RageTheatreCompositePort>=0)t->wComp0Connector=info->RageTheatreCompositePort; if(info->RageTheatreSVideoPort>=0)t->wSVideo0Connector=info->RageTheatreSVideoPort; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%ld, composite=%ld, svideo=%ld\n", - t->wTunerConnector, t->wComp0Connector, t->wSVideo0Connector); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RageTheatre: Connectors (using): tuner=%u, composite=%u, svideo=%u\n", + (unsigned)t->wTunerConnector, (unsigned)t->wComp0Connector, (unsigned)t->wSVideo0Connector); switch((info->RageTheatreCrystal>=0)?info->RageTheatreCrystal:pll->reference_freq){ case 2700: @@ -1303,11 +1403,8 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) pPriv->currentBuffer = 0; pPriv->autopaint_colorkey = TRUE; pPriv->gamma = 1000; - if (info->OverlayOnCRTC2) - pPriv->crt2 = TRUE; - else - pPriv->crt2 = FALSE; - + pPriv->desired_crtc = NULL; + pPriv->ov_alpha = 255; pPriv->gr_alpha = 255; pPriv->alpha_mode = 0; @@ -1332,27 +1429,15 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) * 0 for PIXCLK < 175Mhz, and 1 (divide by 2) * for higher clocks, sure makes life nicer */ + dot_clock = info->ModeReg.dot_clock_freq; - /* Figure out which head we are on */ - 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) + if (dot_clock < 17500) info->ecp_div = 0; else info->ecp_div = 1; ecp = (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (info->ecp_div << 8); -#if 0 - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, info->ecp_div); -#endif - - - if ((info->ChipFamily == CHIP_FAMILY_RS100) || - (info->ChipFamily == CHIP_FAMILY_RS200) || - (info->ChipFamily == CHIP_FAMILY_RS300)) { + if (info->IsIGP) { /* Force the overlay clock on for integrated chips */ ecp |= (1<<18); @@ -1361,7 +1446,6 @@ RADEONAllocAdaptor(ScrnInfoPtr pScrn) OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, ecp); - /* Decide on tuner type */ if((info->tunerType<0) && (info->MM_TABLE_valid)) { pPriv->tuner_type = info->MM_TABLE.tuner_type; @@ -1478,7 +1562,7 @@ RADEONSetupImageVideo(ScreenPtr pScreen) return NULL; adapt->type = XvWindowMask | XvInputMask | XvImageMask; - adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->flags = VIDEO_OVERLAID_IMAGES /*| VIDEO_CLIP_TO_VIEWPORT*/; adapt->name = "ATI Radeon Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = &DummyEncoding; @@ -1665,14 +1749,15 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, RADEONSetColorKey (pScrn, pPriv->colorKey); REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } - else if(attribute == xvSwitchCRT) + else if(attribute == xvCRTC) { - pPriv->crt2 = ClipValue (value, 0, 1); - pPriv->crt2 = value; - if (pPriv->crt2) - info->OverlayOnCRTC2 = TRUE; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + if ((value < -1) || (value > xf86_config->num_crtc)) + return BadValue; + if (value < 0) + pPriv->desired_crtc = NULL; else - info->OverlayOnCRTC2 = FALSE; + pPriv->desired_crtc = xf86_config->crtc[value]; } else if(attribute == xvOvAlpha) { @@ -1796,7 +1881,8 @@ RADEONSetPortAttribute(ScrnInfoPtr pScrn, else if(attribute == xvAdjustment) { pPriv->adjustment=value; - xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %ld\n", pPriv->adjustment); + xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Setting pPriv->adjustment to %u\n", + (unsigned)pPriv->adjustment); if(pPriv->tda9885!=0){ pPriv->tda9885->top_adjustment=value; RADEON_TDA9885_SetEncoding(pPriv); @@ -1862,8 +1948,16 @@ RADEONGetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->doubleBuffer ? 1 : 0; else if(attribute == xvColorKey) *value = pPriv->colorKey; - else if(attribute == xvSwitchCRT) - *value = pPriv->crt2 ? 1 : 0; + else if(attribute == xvCRTC) { + int c; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + for (c = 0; c < xf86_config->num_crtc; c++) + if (xf86_config->crtc[c] == pPriv->desired_crtc) + break; + if (c == xf86_config->num_crtc) + c = -1; + *value = c; + } else if(attribute == xvOvAlpha) *value = pPriv->ov_alpha; else if(attribute == xvGrAlpha) @@ -2396,7 +2490,8 @@ RADEONFreeMemory( static void RADEONDisplayVideo( ScrnInfoPtr pScrn, - RADEONPortPrivPtr pPriv, + xf86CrtcPtr crtc, + RADEONPortPrivPtr pPriv, int id, int offset1, int offset2, int offset3, int offset4, @@ -2410,6 +2505,7 @@ RADEONDisplayVideo( int deinterlacing_method ){ RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 v_inc, h_inc, h_inc_uv, step_by_y, step_by_uv, tmp; double h_inc_d; @@ -2423,7 +2519,6 @@ RADEONDisplayVideo( int y_off; CARD32 scaler_src; CARD32 dot_clock; - DisplayModePtr overlay_mode; int is_rgb; int is_planar; int i; @@ -2433,6 +2528,10 @@ RADEONDisplayVideo( int predownscale=0; int src_w_d; int leftuv = 0; + DisplayModePtr mode; + RADEONOutputPrivatePtr radeon_output; + xf86OutputPtr output; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; is_rgb=0; is_planar=0; switch(id){ @@ -2455,7 +2554,7 @@ RADEONDisplayVideo( workarounds for chip erratas */ /* Figure out which head we are on for dot clock */ - if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) + if (radeon_crtc->crtc_id == 1) dot_clock = info->ModeReg.dot_clock_freq_2; else dot_clock = info->ModeReg.dot_clock_freq; @@ -2480,34 +2579,26 @@ RADEONDisplayVideo( v_inc_shift = 20; 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 { - if (pScrn->currentMode->Flags & V_INTERLACE) - v_inc_shift++; - if (pScrn->currentMode->Flags & V_DBLSCAN) { - v_inc_shift--; - y_mult = 2; + mode = &crtc->mode; + + if (mode->Flags & V_INTERLACE) + v_inc_shift++; + if (mode->Flags & V_DBLSCAN) { + v_inc_shift--; + y_mult = 2; + } + + v_inc = (src_h << v_inc_shift) / drw_h; + + for (i = 0; i < xf86_config->num_output; i++) { + output = xf86_config->output[i]; + if (output->crtc == crtc) { + radeon_output = output->driver_private; + if (radeon_output->Flags & RADEON_USE_RMX) + v_inc = ((src_h * mode->CrtcVDisplay / + radeon_output->PanelYRes) << v_inc_shift) / drw_h; + break; } - 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 = (1 << (12 + ecp_div)); @@ -2593,14 +2684,6 @@ RADEONDisplayVideo( offset5 += ((left >> 16) & ~7) << 1; offset6 += ((left >> 16) & ~7) << 1; } - if (info->IsSecondary) { - offset1 += info->FbMapSize; - offset2 += info->FbMapSize; - offset3 += info->FbMapSize; - offset4 += info->FbMapSize; - offset5 += info->FbMapSize; - offset6 += info->FbMapSize; - } tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); p1_h_accum_init = ((tmp << 4) & 0x000f8000) | @@ -2651,19 +2734,15 @@ RADEONDisplayVideo( 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; */ - } + /* XXX: may need to adjust x_off/y_off for dualhead like mergedfb -- need to test */ + /* + if (srel == radeonLeftOf) { + x_off -= mode->CrtcHDisplay; + } + if (srel == radeonAbove) { + y_off -= mode->CrtcVDisplay; } + */ /* Put the hardware overlay on CRTC2: * @@ -2672,7 +2751,7 @@ RADEONDisplayVideo( * rendering for the second head. */ - if ((info->MergedFB && info->OverlayOnCRTC2) || info->IsSecondary) { + if (radeon_crtc->crtc_id == 1) { x_off = 0; OUTREG(RADEON_OV1_Y_X_START, ((dstBox->x1 + x_off) | ((dstBox->y1*y_mult) << 16))); @@ -2750,6 +2829,7 @@ RADEONDisplayVideo( | ((info->ChipFamily >= CHIP_FAMILY_R200) ? RADEON_SCALER_TEMPORAL_DEINT : 0); break; } + OUTREG(RADEON_OV0_SCALE_CNTL, scale_cntl); OUTREG(RADEON_OV0_REG_LOAD_CNTL, 0); } @@ -2789,6 +2869,7 @@ RADEONPutImage( int top, left, npixels, nlines, bpp; BoxRec dstBox; CARD32 tmp; + xf86CrtcPtr crtc; /* * s2offset, s3offset - byte offsets into U and V plane of the @@ -2821,24 +2902,15 @@ 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; - - 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 (!radeon_clip_video_helper(pScrn, &crtc, pPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) + return Success; + + dstBox.x1 -= crtc->x; + dstBox.x2 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.y2 -= crtc->y; bpp = pScrn->bitsPerPixel >> 3; @@ -2891,8 +2963,14 @@ RADEONPutImage( offset = (pPriv->video_offset) + (top * dstPitch); - if(pPriv->doubleBuffer) + if(pPriv->doubleBuffer) { + unsigned char *RADEONMMIO = info->MMIO; + + /* Wait for last flip to take effect */ + while(!(INREG(RADEON_OV0_REG_LOAD_CNTL) & RADEON_REG_LD_CTL_FLIP_READBACK)); + offset += pPriv->currentBuffer * new_size; + } dst_start = info->FB + offset; @@ -2962,7 +3040,7 @@ RADEONPutImage( /* FIXME: someone should look at these offsets, I don't think it makes sense how they are handled throughout the source. */ - RADEONDisplayVideo(pScrn, pPriv, id, offset, offset + d2line, offset + d3line, + RADEONDisplayVideo(pScrn, crtc, pPriv, id, offset, offset + d2line, offset + d3line, offset, offset + d2line, offset + d3line, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h, METHOD_BOB); @@ -3180,12 +3258,12 @@ RADEONDisplaySurface( ){ OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; ScrnInfoPtr pScrn = surface->pScrn; - RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPortPrivPtr portPriv = info->adaptor->pPortPrivates[0].ptr; INT32 xa, ya, xb, yb; BoxRec dstBox; + xf86CrtcPtr crtc; if (src_w > (drw_w << 4)) drw_w = src_w >> 4; @@ -3202,30 +3280,21 @@ RADEONDisplaySurface( dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; - if (info->MergedFB) - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if (!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, - surface->width, surface->height)) - return Success; + if (!radeon_clip_video_helper(pScrn, &crtc, portPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, clipBoxes, + surface->width, surface->height)) + return Success; - 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; - } + dstBox.x1 -= crtc->x; + dstBox.x2 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.y2 -= crtc->y; #if 0 /* this isn't needed */ RADEONResetVideo(pScrn); #endif - RADEONDisplayVideo(pScrn, portPriv, surface->id, + RADEONDisplayVideo(pScrn, crtc, portPriv, surface->id, surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], surface->offsets[0], @@ -3261,8 +3330,8 @@ RADEONInitOffscreenImages(ScreenPtr pScreen) return; offscreenImages[0].image = &Images[0]; - offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | - VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES /*| + VIDEO_CLIP_TO_VIEWPORT*/; offscreenImages[0].alloc_surface = RADEONAllocateSurface; offscreenImages[0].free_surface = RADEONFreeSurface; offscreenImages[0].display = RADEONDisplaySurface; @@ -3303,6 +3372,7 @@ RADEONPutVideo( int width, height; int mult; int vbi_line_width, vbi_start, vbi_end; + xf86CrtcPtr crtc; RADEON_SYNC(info, pScrn); /* @@ -3340,27 +3410,19 @@ RADEONPutVideo( vbi_line_width = 798*2; if(width<=640) - vbi_line_width = 0x640; /* 1600 actually */ - else - vbi_line_width = 2000; /* might need adjustment */ + vbi_line_width = 0x640; /* 1600 actually */ + else + vbi_line_width = 2000; /* might need adjustment */ - if (info->MergedFB) - RADEONChooseOverlayCRTC(pScrn, &dstBox); - - if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) - return Success; + if (!radeon_clip_video_helper(pScrn, &crtc, pPriv->desired_crtc, + &dstBox, &xa, &xb, &ya, &yb, + clipBoxes, width, height)) + return Success; - 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; - } + dstBox.x1 -= crtc->x; + dstBox.x2 -= crtc->x; + dstBox.y1 -= crtc->y; + dstBox.y2 -= crtc->y; bpp = pScrn->bitsPerPixel >> 3; pitch = bpp * pScrn->displayWidth; @@ -3382,7 +3444,8 @@ RADEONPutVideo( id = FOURCC_YUY2; top = ya>>16; - +#if 0 + /* setting the ID above makes this useful - needs revisiting */ switch(id) { case FOURCC_YV12: case FOURCC_I420: @@ -3400,6 +3463,10 @@ RADEONPutVideo( srcPitch = (width<<1); break; } +#else + dstPitch = ((width<<1) + 15) & ~15; + srcPitch = (width<<1); +#endif new_size = dstPitch * height; new_size = new_size + 0x1f; /* for aligning */ @@ -3510,7 +3577,7 @@ RADEONPutVideo( RADEONFillKeyHelper(pDraw, pPriv->colorKey, clipBoxes); } - RADEONDisplayVideo(pScrn, pPriv, id, offset1+top*srcPitch, offset2+top*srcPitch, + RADEONDisplayVideo(pScrn, crtc, pPriv, id, offset1+top*srcPitch, offset2+top*srcPitch, offset3+top*srcPitch, offset4+top*srcPitch, offset1+top*srcPitch, offset2+top*srcPitch, width, height, dstPitch*mult/2, xa, xb, ya, &dstBox, src_w, src_h*mult/2, drw_w, drw_h, pPriv->overlay_deinterlacing_method); diff --git a/src/radeon_video.h b/src/radeon_video.h index b6d5d2d9..072f40e1 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -11,6 +11,8 @@ #include "generic_bus.h" #include "theatre.h" +#include "xf86Crtc.h" + /* Xvideo port struct */ typedef struct { CARD32 transform_index; @@ -40,7 +42,7 @@ typedef struct { CARD8 tuner_type; MSP3430Ptr msp3430; TDA9885Ptr tda9885; - UDA1380Ptr uda1380; + UDA1380Ptr uda1380; /* VIP bus and devices */ GENERIC_BUS_Ptr VIP; @@ -77,7 +79,7 @@ typedef struct { Time offTime; Time freeTime; Bool autopaint_colorkey; - Bool crt2; /* 0=CRT1, 1=CRT2 */ + xf86CrtcPtr desired_crtc; #ifdef USE_EXA int size; diff --git a/src/theatre.c b/src/theatre.c index 0a635fa7..a5aadfb3 100644 --- a/src/theatre.c +++ b/src/theatre.c @@ -1796,7 +1796,9 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) counter++; } dwTempContrast = ReadRT_fld (fld_LP_CONTRAST); - if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "Rage Theatre: timeout waiting for line count (%ld)\n", ReadRT_fld (fld_VS_LINE_COUNT)); + if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "Rage Theatre: timeout waiting for line count (%u)\n", + (unsigned)ReadRT_fld (fld_VS_LINE_COUNT)); WriteRT_fld (fld_LP_CONTRAST, 0x0); @@ -1851,7 +1853,9 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) counter++; } WriteRT_fld (fld_LP_CONTRAST, dwTempContrast); - if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "Rage Theatre: timeout waiting for line count (%ld)\n", ReadRT_fld (fld_VS_LINE_COUNT)); + if(counter>=10000)xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "Rage Theatre: timeout waiting for line count (%u)\n", + (unsigned)ReadRT_fld (fld_VS_LINE_COUNT)); @@ -1942,7 +1946,8 @@ void DumpRageTheatreRegs(TheatrePtr t) for(i=0;i<0x900;i+=4) { RT_regr(i, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register 0x%04x is equal to 0x%08lx\n", i, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register 0x%04x is equal to 0x%08x\n", i, (unsigned)data); } } @@ -2147,7 +2152,9 @@ void DumpRageTheatreRegsByName(TheatrePtr t) for(i=0; rt_reg_list[i].name!=NULL;i++){ RT_regr(rt_reg_list[i].addr, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register (0x%04lx) %s is equal to 0x%08lx\n", rt_reg_list[i].addr, rt_reg_list[i].name, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register (0x%04lx) %s is equal to 0x%08x\n", + rt_reg_list[i].addr, rt_reg_list[i].name, (unsigned)data); } } diff --git a/src/theatre200.c b/src/theatre200.c index ff863959..672f01e8 100644 --- a/src/theatre200.c +++ b/src/theatre200.c @@ -1799,10 +1799,12 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) t->wConnector = wConnector; theatre_read(t, VIP_GPIO_CNTL, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %x\n", + (unsigned)data); theatre_read(t, VIP_GPIO_INOUT, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %x\n", + (unsigned)data); switch (wConnector) { @@ -1851,10 +1853,12 @@ void RT_SetConnector (TheatrePtr t, CARD16 wConnector, int tunerFlag) } theatre_read(t, VIP_GPIO_CNTL, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_CNTL: %x\n", + (unsigned)data); theatre_read(t, VIP_GPIO_INOUT, &data); - xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %lx\n", data); + xf86DrvMsg(t->VIP->scrnIndex,X_INFO,"VIP_GPIO_INOUT: %x\n", + (unsigned)data); dsp_configure_i2s_port(t, 0, 0, 0); @@ -2007,7 +2011,8 @@ void DumpRageTheatreRegs(TheatrePtr t) for(i=0;i<0x900;i+=4) { RT_regr(i, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register 0x%04x is equal to 0x%08lx\n", i, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register 0x%04x is equal to 0x%08x\n", i, (unsigned)data); } } @@ -2212,7 +2217,9 @@ void DumpRageTheatreRegsByName(TheatrePtr t) for(i=0; rt_reg_list[i].name!=NULL;i++){ RT_regr(rt_reg_list[i].addr, &data); - xf86DrvMsg(t->VIP->scrnIndex, X_INFO, "register (0x%04lx) %s is equal to 0x%08lx\n", rt_reg_list[i].addr, rt_reg_list[i].name, data); + xf86DrvMsg(t->VIP->scrnIndex, X_INFO, + "register (0x%04lx) %s is equal to 0x%08x\n", + rt_reg_list[i].addr, rt_reg_list[i].name, (unsigned)data); } } diff --git a/src/theatre_detect.c b/src/theatre_detect.c index e7548327..87709119 100644 --- a/src/theatre_detect.c +++ b/src/theatre_detect.c @@ -67,7 +67,7 @@ static Bool theatre_write(TheatrePtr t,CARD32 reg, CARD32 data) TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) { TheatrePtr t; - CARD32 i; + int i; CARD32 val; char s[20]; @@ -88,7 +88,9 @@ TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) { if(b->read(b, ((i & 0x03)<<14) | VIP_VIP_VENDOR_DEVICE_ID, 4, (CARD8 *)&val)) { - if(val)xf86DrvMsg(b->scrnIndex, X_INFO, "Device %ld on VIP bus ids as 0x%08lx\n",i,val); + if(val)xf86DrvMsg(b->scrnIndex, X_INFO, + "Device %d on VIP bus ids as 0x%08x\n", i, + (unsigned)val); if(t->theatre_num>=0)continue; /* already found one instance */ switch(val){ case RT100_ATI_ID: @@ -101,10 +103,12 @@ TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) break; } } else { - xf86DrvMsg(b->scrnIndex, X_INFO, "No response from device %ld on VIP bus\n",i); + xf86DrvMsg(b->scrnIndex, X_INFO, "No response from device %d on VIP bus\n",i); } } - if(t->theatre_num>=0)xf86DrvMsg(b->scrnIndex, X_INFO, "Detected Rage Theatre as device %d on VIP bus with id 0x%08lx\n",t->theatre_num,t->theatre_id); + if(t->theatre_num>=0)xf86DrvMsg(b->scrnIndex, X_INFO, + "Detected Rage Theatre as device %d on VIP bus with id 0x%08x\n", + t->theatre_num, (unsigned)t->theatre_id); if(t->theatre_num < 0) { @@ -113,7 +117,8 @@ TheatrePtr DetectTheatre(GENERIC_BUS_Ptr b) } RT_regr(VIP_VIP_REVISION_ID, &val); - xf86DrvMsg(b->scrnIndex, X_INFO, "Detected Rage Theatre revision %8.8lX\n", val); + xf86DrvMsg(b->scrnIndex, X_INFO, "Detected Rage Theatre revision %8.8X\n", + (unsigned)val); #if 0 DumpRageTheatreRegsByName(t); |