diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | compat/.gitignore | 2 | ||||
-rw-r--r-- | compat/Makefile.am | 15 | ||||
-rw-r--r-- | compat/README | 7 | ||||
-rw-r--r-- | configure.ac | 70 | ||||
-rw-r--r-- | man/Makefile.am | 9 | ||||
-rw-r--r-- | man/nv.man | 13 | ||||
-rw-r--r-- | src/Makefile.am | 29 | ||||
-rw-r--r-- | src/g80_cursor.c | 150 | ||||
-rw-r--r-- | src/g80_cursor.h | 8 | ||||
-rw-r--r-- | src/g80_dac.c | 199 | ||||
-rw-r--r-- | src/g80_ddc.h | 1 | ||||
-rw-r--r-- | src/g80_display.c | 410 | ||||
-rw-r--r-- | src/g80_display.h | 21 | ||||
-rw-r--r-- | src/g80_driver.c | 164 | ||||
-rw-r--r-- | src/g80_output.c (renamed from src/g80_ddc.c) | 219 | ||||
-rw-r--r-- | src/g80_output.h | 29 | ||||
-rw-r--r-- | src/g80_sor.c | 151 | ||||
-rw-r--r-- | src/g80_type.h | 19 | ||||
-rw-r--r-- | src/local_xf86Rename.h | 23 | ||||
-rw-r--r-- | src/nv_driver.c | 19 | ||||
-rw-r--r-- | src/nv_include.h | 5 | ||||
-rw-r--r-- | src/nv_local.h | 3 | ||||
-rw-r--r-- | src/nv_video.c | 13 | ||||
-rw-r--r-- | src/riva_include.h | 5 | ||||
-rw-r--r-- | src/riva_local.h | 3 |
26 files changed, 1010 insertions, 579 deletions
diff --git a/Makefile.am b/Makefile.am index fd65d86..aa4996b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AUTOMAKE_OPTIONS = foreign -SUBDIRS = src man +SUBDIRS = src man compat EXTRA_DIST = README.NV1 README.G80 ChangeLog diff --git a/compat/.gitignore b/compat/.gitignore new file mode 100644 index 0000000..8d30df6 --- /dev/null +++ b/compat/.gitignore @@ -0,0 +1,2 @@ +modes +parser diff --git a/compat/Makefile.am b/compat/Makefile.am new file mode 100644 index 0000000..f5f8d93 --- /dev/null +++ b/compat/Makefile.am @@ -0,0 +1,15 @@ +EXTRA_DIST = \ + parser/xf86Parser.h \ + parser/xf86Optrec.h \ + modes/xf86Crtc.c \ + modes/xf86Crtc.h \ + modes/xf86Cursors.c \ + modes/xf86cvt.c \ + modes/xf86DiDGA.c \ + modes/xf86EdidModes.c \ + modes/xf86Modes.c \ + modes/xf86Modes.h \ + modes/xf86RandR12.c \ + modes/xf86RandR12.h \ + modes/xf86Rename.h \ + modes/xf86Rotate.c diff --git a/compat/README b/compat/README new file mode 100644 index 0000000..3e2b089 --- /dev/null +++ b/compat/README @@ -0,0 +1,7 @@ +This directory contains a copy of the mode and parser code from RandR 1.2. + +If you are building from git and you don't have xorg-server-1.3 or higher or you +want to be able to make dist, you should create symlinks to the modes and parser +directories from a RandR 1.2-enabled server here: + + $ ln -s /path/to/xorg/xserver/hw/xfree86/{modes,parser} . diff --git a/configure.ac b/configure.ac index e2f3999..75e954a 100644 --- a/configure.ac +++ b/configure.ac @@ -41,47 +41,74 @@ AC_PROG_CC AH_TOP([#include "xorg-server.h"]) +# Options AC_ARG_WITH(xorg-module-dir, AC_HELP_STRING([--with-xorg-module-dir=DIR], [Default xorg module directory [[default=$libdir/xorg/modules]]]), [moduledir="$withval"], [moduledir="$libdir/xorg/modules"]) +AC_ARG_WITH(xserver-source,AC_HELP_STRING([--with-xserver-source=XSERVER_SOURCE], + [Path to X server source tree]), + [ XSERVER_SOURCE="$withval" ], + [ XSERVER_SOURCE="" ]) + # Checks for extensions XORG_DRIVER_CHECK_EXT(RANDR, randrproto) XORG_DRIVER_CHECK_EXT(RENDER, renderproto) XORG_DRIVER_CHECK_EXT(XV, videoproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) -# Determine whether XV PutImage takes a DrawablePtr and whether or not to use -# the libcwrapper. -PKG_CHECK_EXISTS([xorg-server >= 1.0.99.901], - [AC_DEFINE(HAVE_XV_DRAWABLE,1,[XV hooks take a DrawablePtr])], - [AC_DEFINE(USE_LIBC_WRAPPER,1,[Use the libc wrapper])]) - -PKG_CHECK_EXISTS([xorg-server >= 1.1.99.901], - [AC_DEFINE(USE_CVTMODE_FUNC,1,[Use xf86CVTMode func])]) - # Checks for pkg-config packages -PKG_CHECK_MODULES(XORG, [xorg-server xproto fontsproto $REQUIRED_MODULES]) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.2 xproto fontsproto $REQUIRED_MODULES]) sdkdir=$(pkg-config --variable=sdkdir xorg-server) -# Check for optional compile-time support -AC_ARG_ENABLE(g80, AC_HELP_STRING([--disable-g80], - [Disable G80 support [[default=no]]]), - [SUPPORT_G80="$enableval"], - [SUPPORT_G80=yes]) -AM_CONDITIONAL(SUPPORT_G80, test x$SUPPORT_G80 = xyes) -if test "$SUPPORT_G80" = yes; then - AC_DEFINE(SUPPORT_G80,1,[Enable G80 support]) - echo "Enabling G80 support" -fi - # Checks for libraries. # Checks for header files. AC_HEADER_STDC +save_CFLAGS="$CFLAGS" +CFLAGS="$XORG_CFLAGS" +AC_CHECK_HEADER(xf86Modes.h,[BUILD_XMODES=no],[BUILD_XMODES=yes],[#include "xorg-server.h"]) +CFLAGS="$save_CFLAGS" +AM_CONDITIONAL(BUILD_XMODES, test "x$BUILD_XMODES" = xyes) +if test "x$XSERVER_SOURCE" != x; then + if test -d "$XSERVER_SOURCE"; then + XSERVER_SOURCE=`cd "$XSERVER_SOURCE" && pwd` + if test -f "$XSERVER_SOURCE/hw/xfree86/modes/xf86Modes.h" -a -f "$XSERVER_SOURCE/hw/xfree86/parser/xf86Parser.h"; then + : + else + AC_ERROR([Server source at $XSERVER_SOURCE doesn't have the new mode code]) + fi + else + AC_ERROR([Can't find xserver-source path $XSERVER_SOURCE]) + fi +fi +if test "x$BUILD_XMODES" = xno; then + AC_MSG_NOTICE([X server has new mode code]) + XMODES_CFLAGS= + parser_dir= + modes_dir= +else + if test "x$XSERVER_SOURCE" = x; then + AC_MSG_NOTICE([X server is missing new mode code and --with-xserver-source not specified, using local copy]) + AC_MSG_NOTICE([If you're building from git, please read compat/README]) + parser_dir='$(top_srcdir)/compat/parser' + modes_dir='$(top_srcdir)/compat/modes' + else + AC_MSG_NOTICE([Using mode code from $XSERVER_SOURCE]) + parser_dir="$XSERVER_SOURCE/hw/xfree86/parser" + modes_dir="$XSERVER_SOURCE/hw/xfree86/modes" + fi + XMODES_CFLAGS="-DXF86_MODES_RENAME -I\"$modes_dir\" -I\"$parser_dir\"" + AC_DEFINE(BUILD_XMODES, 1,[X server doesn't have built-in mode code, so we need to build it]) +fi +AC_SUBST([XMODES_CFLAGS]) +AC_SUBST([parser_dir]) +AC_SUBST([modes_dir]) + +# Substitutions AC_SUBST([XORG_CFLAGS]) AC_SUBST([moduledir]) @@ -95,4 +122,5 @@ AC_OUTPUT([ Makefile src/Makefile man/Makefile + compat/Makefile ]) diff --git a/man/Makefile.am b/man/Makefile.am index 442d27d..bf7ec17 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -41,12 +41,6 @@ SED = sed XORGRELSTRING = @PACKAGE_STRING@ XORGMANNAME = X Version 11 -if SUPPORT_G80 -MAN_SUPPORT_G80 = 1 -else -MAN_SUPPORT_G80 = 0 -endif - MAN_SUBSTS = \ -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ @@ -57,8 +51,7 @@ MAN_SUBSTS = \ -e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \ -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \ -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \ - -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' \ - -e 's|__support_g80__|$(MAN_SUPPORT_G80)|g' + -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man @@ -58,12 +58,9 @@ NV40, NV41, NV43, NV44, NV45, C51 .TP 22 .B GeForce 7XXX G70, G71, G72, G73 -.de G8 .TP 22 .B GeForce 8XXX G80, G84, G86 -.. -.if __support_g80__ .G8 .SH CONFIGURATION DETAILS Please refer to __xconfigfile__(__filemansuffix__) for general configuration @@ -136,7 +133,6 @@ Default: no rotation support. Enable or disable use of the shadow framebuffer layer. Default: off. . .\" ******************** begin G80 section ******************** -.de G8 .PP The following driver .B Options @@ -147,15 +143,6 @@ Enable or disable the hardware cursor. Default: on. .TP .BI "Option \*qNoAccel\*q \*q" boolean \*q Disable or enable acceleration. Default: acceleration is enabled. -.TP -.BI "Option \*qBackendMode\*q \*q" mode \*q -Designate a mode to be used as the physical mode driving the display. -The screen will be scaled to fit the requested mode. -For example, if -.B Option \*qBackendMode\*q \*q1280x1024\*q -is specified, the monitor will always display the 1280x1024 mode and the screen will be scaled to match. -.. -.if __support_g80__ .G8 .\" ******************** end G80 section ******************** . .SH "SEE ALSO" diff --git a/src/Makefile.am b/src/Makefile.am index b7c1128..52b6b47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,7 +23,7 @@ # -avoid-version prevents gratuitous .0.0.0 version numbers on the end # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -AM_CFLAGS = @XORG_CFLAGS@ +AM_CFLAGS = @XMODES_CFLAGS@ @XORG_CFLAGS@ nv_drv_la_LTLIBRARIES = nv_drv.la nv_drv_la_LDFLAGS = -module -avoid-version nv_drv_ladir = @moduledir@/drivers @@ -66,18 +66,39 @@ riva_sources = \ riva_type.h \ riva_xaa.c -if SUPPORT_G80 g80_sources = \ g80_cursor.c \ g80_cursor.h \ - g80_ddc.c \ - g80_ddc.h \ + g80_dac.c \ g80_display.c \ g80_display.h \ g80_dma.c \ g80_dma.h \ g80_driver.c \ + g80_output.c \ + g80_output.h \ + g80_sor.c \ g80_type.h \ g80_xaa.c \ g80_xaa.h + +xmode_sources = \ + @parser_dir@/xf86Parser.h \ + @parser_dir@/xf86Optrec.h \ + @modes_dir@/xf86Modes.h \ + @modes_dir@/xf86Modes.c \ + @modes_dir@/xf86cvt.c \ + @modes_dir@/xf86Crtc.h \ + @modes_dir@/xf86Crtc.c \ + @modes_dir@/xf86Cursors.c \ + @modes_dir@/xf86EdidModes.c \ + @modes_dir@/xf86RandR12.c \ + @modes_dir@/xf86RandR12.h \ + @modes_dir@/xf86Rename.h \ + @modes_dir@/xf86Rotate.c \ + @modes_dir@/xf86DiDGA.c + +if BUILD_XMODES +EXTRA_nv_drv_la_SOURCES = local_xf86Rename.h +nodist_nv_drv_la_SOURCES = $(xmode_sources) endif diff --git a/src/g80_cursor.c b/src/g80_cursor.c index 07422e5..98a2736 100644 --- a/src/g80_cursor.c +++ b/src/g80_cursor.c @@ -21,7 +21,6 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -36,36 +35,10 @@ #define CURSOR_PTR ((CARD32*)pNv->mem + pNv->videoRam * 256 - 0x1000) -static void G80SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) -{ - G80Ptr pNv = G80PTR(pScrn); - CARD32 *dst = CURSOR_PTR; - CARD32 *src = pNv->tmpCursor; - int i, j; - - fg |= 0xff000000; - bg |= 0xff000000; - - for(i = 0; i < 128; i++) { - CARD32 b = *src++; - CARD32 m = *src++; - - for(j = 0; j < 32; j++) { - if(m & 1) - *dst = (b & 1) ? fg : bg; - else - *dst = 0; - b >>= 1; - m >>= 1; - dst++; - } - } -} - -static void G80SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +void G80SetCursorPosition(xf86CrtcPtr crtc, int x, int y) { - G80Ptr pNv = G80PTR(pScrn); - const int headOff = 0x1000*pNv->head; + G80Ptr pNv = G80PTR(crtc->scrn); + const int headOff = 0x1000*G80CrtcGetHead(crtc); x &= 0xffff; y &= 0xffff; @@ -73,113 +46,58 @@ static void G80SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) pNv->reg[(0x00647080 + headOff)/4] = 0; } -static void G80LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits) -{ - G80Ptr pNv = G80PTR(pScrn); - memcpy(pNv->tmpCursor, bits, sizeof(pNv->tmpCursor)); -} - -static void G80HideCursor(ScrnInfoPtr pScrn) +void G80LoadCursorARGB(xf86CrtcPtr crtc, CARD32 *src) { - G80Ptr pNv = G80PTR(pScrn); + G80Ptr pNv = G80PTR(crtc->scrn); + CARD32 *dst = CURSOR_PTR; - pNv->cursorVisible = FALSE; - G80DispHideCursor(G80PTR(pScrn), TRUE); + /* Assume cursor is 64x64 */ + memcpy(dst, src, 64 * 64 * 4); } -static void G80ShowCursor(ScrnInfoPtr pScrn) +Bool G80CursorAcquire(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; - pNv->cursorVisible = TRUE; - G80DispShowCursor(G80PTR(pScrn), TRUE); -} + if(!pNv->HWCursor) return TRUE; -static Bool G80UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) -{ - return TRUE; -} + /* Initialize the cursor on each head */ + for(i = 0; i < xf86_config->num_crtc; i++) { + const int headOff = 0x10 * G80CrtcGetHead(xf86_config->crtc[i]); -#ifdef ARGB_CURSOR -static Bool G80UseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs) -{ - if((pCurs->bits->width <= 64) && (pCurs->bits->height <= 64)) - return TRUE; + pNv->reg[(0x00610270+headOff)/4] = 0x2000; + while(pNv->reg[(0x00610270+headOff)/4] & 0x30000); - return FALSE; -} - -static void G80LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) -{ - G80Ptr pNv = G80PTR(pScrn); - CARD32 *dst = CURSOR_PTR, *src = pCurs->bits->argb; - int y; - - for(y = 0; y < pCurs->bits->height; y++) { - memcpy(dst, src, pCurs->bits->width * 4); - memset(dst + pCurs->bits->width, 0, (64 - pCurs->bits->width) * 4); - src += pCurs->bits->width; - dst += 64; + pNv->reg[(0x00610270+headOff)/4] = 1; + while((pNv->reg[(0x00610270+headOff)/4] & 0x30000) != 0x10000); } - memset(dst, 0, (64 - y) * 64 * 4); -} -#endif - -Bool G80CursorAcquire(G80Ptr pNv) -{ - const int headOff = 0x10 * pNv->head; - - if(!pNv->HWCursor) return TRUE; - - pNv->reg[(0x00610270+headOff)/4] = 0x2000; - while(pNv->reg[(0x00610270+headOff)/4] & 0x30000); - - pNv->reg[(0x00610270+headOff)/4] = 1; - while((pNv->reg[(0x00610270+headOff)/4] & 0x30000) != 0x10000); - return TRUE; } -void G80CursorRelease(G80Ptr pNv) +void G80CursorRelease(ScrnInfoPtr pScrn) { - const int headOff = 0x10 * pNv->head; + G80Ptr pNv = G80PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; if(!pNv->HWCursor) return; - pNv->reg[(0x00610270+headOff)/4] = 0; - while(pNv->reg[(0x00610270+headOff)/4] & 0x30000); + /* Release the cursor on each head */ + for(i = 0; i < xf86_config->num_crtc; i++) { + const int headOff = 0x10 * G80CrtcGetHead(xf86_config->crtc[i]); + + pNv->reg[(0x00610270+headOff)/4] = 0; + while(pNv->reg[(0x00610270+headOff)/4] & 0x30000); + } } Bool G80CursorInit(ScreenPtr pScreen) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - G80Ptr pNv = G80PTR(pScrn); - xf86CursorInfoPtr infoPtr; - - if(!pNv->HWCursor) - return TRUE; - - infoPtr = xf86CreateCursorInfoRec(); - if(!infoPtr) return FALSE; - - pNv->CursorInfo = infoPtr; - pNv->cursorVisible = FALSE; - - infoPtr->MaxWidth = infoPtr->MaxHeight = 64; - infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32; - infoPtr->SetCursorColors = G80SetCursorColors; - infoPtr->SetCursorPosition = G80SetCursorPosition; - infoPtr->LoadCursorImage = G80LoadCursorImage; - infoPtr->HideCursor = G80HideCursor; - infoPtr->ShowCursor = G80ShowCursor; - infoPtr->UseHWCursor = G80UseHWCursor; - -#ifdef ARGB_CURSOR - infoPtr->UseHWCursorARGB = G80UseHWCursorARGB; - infoPtr->LoadCursorARGB = G80LoadCursorARGB; -#endif - - return xf86InitCursor(pScreen, infoPtr); + return xf86_cursors_init(pScreen, 64, 64, + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | + HARDWARE_CURSOR_ARGB); } diff --git a/src/g80_cursor.h b/src/g80_cursor.h index 9cd56ee..4d81d80 100644 --- a/src/g80_cursor.h +++ b/src/g80_cursor.h @@ -1,3 +1,7 @@ Bool G80CursorInit(ScreenPtr); -Bool G80CursorAcquire(G80Ptr); -void G80CursorRelease(G80Ptr); +Bool G80CursorAcquire(ScrnInfoPtr); +void G80CursorRelease(ScrnInfoPtr); + +/* CRTC cursor functions */ +void G80SetCursorPosition(xf86CrtcPtr crtc, int x, int y); +void G80LoadCursorARGB(xf86CrtcPtr crtc, CARD32 *src); diff --git a/src/g80_dac.c b/src/g80_dac.c new file mode 100644 index 0000000..7848de2 --- /dev/null +++ b/src/g80_dac.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2007 NVIDIA, Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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 <unistd.h> + +#define DPMS_SERVER +#include <X11/extensions/dpms.h> + +#include "g80_type.h" +#include "g80_display.h" +#include "g80_output.h" + +static void +G80DacSetPClk(xf86OutputPtr output, int pclk) +{ + G80Ptr pNv = G80PTR(output->scrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int orOff = 0x800 * pPriv->or; + + pNv->reg[(0x00614280+orOff)/4] = 0; +} + +static void +G80DacDPMSSet(xf86OutputPtr output, int mode) +{ + G80Ptr pNv = G80PTR(output->scrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int off = 0x800 * pPriv->or; + CARD32 tmp; + + /* + * DPMSModeOn everything on + * DPMSModeStandby hsync disabled, vsync enabled + * DPMSModeSuspend hsync enabled, vsync disabled + * DPMSModeOff sync disabled + */ + while(pNv->reg[(0x0061A004+off)/4] & 0x80000000); + + tmp = pNv->reg[(0x0061A004+off)/4]; + tmp &= ~0x7f; + tmp |= 0x80000000; + + if(mode == DPMSModeStandby || mode == DPMSModeOff) + tmp |= 1; + if(mode == DPMSModeSuspend || mode == DPMSModeOff) + tmp |= 4; + if(mode != DPMSModeOn) + tmp |= 0x10; + if(mode == DPMSModeOff) + tmp |= 0x40; + + pNv->reg[(0x0061A004+off)/4] = tmp; +} + +static void +G80DacModeSet(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + G80OutputPrivPtr pPriv = output->driver_private; + const int dacOff = 0x80 * pPriv->or; + + if(!adjusted_mode) { + C(0x00000400 + dacOff, 0); + return; + } + + // This wouldn't be necessary, but the server is stupid and calls + // G80DacDPMSSet after the output is disconnected, even though the hardware + // turns it off automatically. + G80DacDPMSSet(output, DPMSModeOn); + + C(0x00000400 + dacOff, + (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) | 0x40); + C(0x00000404 + dacOff, + (adjusted_mode->Flags & V_NHSYNC) ? 1 : 0 | + (adjusted_mode->Flags & V_NVSYNC) ? 2 : 0); +} + +/* + * Perform DAC load detection to determine if there is a connected display. + */ +static xf86OutputStatus +G80DacDetect(xf86OutputPtr output) +{ + G80OutputPrivPtr pPriv = output->driver_private; + + /* Assume physical status isn't going to change before the BlockHandler */ + if(pPriv->cached_status != XF86OutputStatusUnknown) + return pPriv->cached_status; + + G80OutputPartnersDetect(output, pPriv->partner, pPriv->i2c); + return pPriv->cached_status; +} + +Bool +G80DacLoadDetect(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + G80Ptr pNv = G80PTR(pScrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int scrnIndex = pScrn->scrnIndex; + const int dacOff = 2048 * pPriv->or; + CARD32 load, tmp, tmp2; + + xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on VGA%i ... ", + pPriv->or); + + pNv->reg[(0x0061A010+dacOff)/4] = 0x00000001; + tmp2 = pNv->reg[(0x0061A004+dacOff)/4]; + pNv->reg[(0x0061A004+dacOff)/4] = 0x80150000; + while(pNv->reg[(0x0061A004+dacOff)/4] & 0x80000000); + tmp = pNv->architecture == 0x50 ? 420 : 340; + pNv->reg[(0x0061A00C+dacOff)/4] = tmp | 0x100000; + usleep(4500); + load = pNv->reg[(0x0061A00C+dacOff)/4]; + pNv->reg[(0x0061A00C+dacOff)/4] = 0; + pNv->reg[(0x0061A004+dacOff)/4] = 0x80000000 | tmp2; + + // Use this DAC if all three channels show load. + if((load & 0x38000000) == 0x38000000) { + xf86ErrorF("found one!\n"); + return TRUE; + } + + xf86ErrorF("nothing.\n"); + return FALSE; +} + +static void +G80DacDestroy(xf86OutputPtr output) +{ + G80OutputDestroy(output); + + xfree(output->driver_private); + output->driver_private = NULL; +} + +static const xf86OutputFuncsRec G80DacOutputFuncs = { + .dpms = G80DacDPMSSet, + .save = NULL, + .restore = NULL, + .mode_valid = G80OutputModeValid, + .mode_fixup = G80OutputModeFixup, + .prepare = G80OutputPrepare, + .commit = G80OutputCommit, + .mode_set = G80DacModeSet, + .detect = G80DacDetect, + .get_modes = G80OutputGetDDCModes, + .destroy = G80DacDestroy, +}; + +xf86OutputPtr +G80CreateDac(ScrnInfoPtr pScrn, ORNum or) +{ + G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1); + xf86OutputPtr output; + char orName[5]; + + if(!pPriv) + return FALSE; + + snprintf(orName, 5, "VGA%i", or); + output = xf86OutputCreate(pScrn, &G80DacOutputFuncs, orName); + + pPriv->type = DAC; + pPriv->or = or; + pPriv->cached_status = XF86OutputStatusUnknown; + pPriv->set_pclk = G80DacSetPClk; + output->driver_private = pPriv; + output->interlaceAllowed = TRUE; + output->doubleScanAllowed = TRUE; + + return output; +} diff --git a/src/g80_ddc.h b/src/g80_ddc.h deleted file mode 100644 index d209d62..0000000 --- a/src/g80_ddc.h +++ /dev/null @@ -1 +0,0 @@ -Bool G80ProbeDDC(ScrnInfoPtr pScrn); diff --git a/src/g80_display.c b/src/g80_display.c index 068e902..652a5a9 100644 --- a/src/g80_display.c +++ b/src/g80_display.c @@ -32,10 +32,17 @@ #include <unistd.h> #include "g80_type.h" +#include "g80_cursor.h" #include "g80_display.h" +#include "g80_output.h" -#define DPMS_SERVER -#include <X11/extensions/dpms.h> +typedef struct G80CrtcPrivRec { + Head head; + int pclk; /* Target pixel clock in kHz */ + Bool cursorVisible; +} G80CrtcPrivRec, *G80CrtcPrivPtr; + +static void G80CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update); /* * PLL calculation. pclk is in kHz. @@ -137,8 +144,42 @@ G80CalcPLL(float pclk, int *pNA, int *pMA, int *pNB, int *pMB, int *pP) } static void -G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data) +G80CrtcSetPClk(xf86CrtcPtr crtc) { + G80Ptr pNv = G80PTR(crtc->scrn); + G80CrtcPrivPtr pPriv = crtc->driver_private; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + const int headOff = 0x800 * pPriv->head; + int lo_n, lo_m, hi_n, hi_m, p, i; + CARD32 lo = pNv->reg[(0x00614104+headOff)/4]; + CARD32 hi = pNv->reg[(0x00614108+headOff)/4]; + + pNv->reg[(0x00614100+headOff)/4] = 0x10000610; + lo &= 0xff00ff00; + hi &= 0x8000ff00; + + G80CalcPLL(pPriv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p); + + lo |= (lo_m << 16) | lo_n; + hi |= (p << 28) | (hi_m << 16) | hi_n; + pNv->reg[(0x00614104+headOff)/4] = lo; + pNv->reg[(0x00614108+headOff)/4] = hi; + pNv->reg[(0x00614200+headOff)/4] = 0; + + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if(output->crtc != crtc) + continue; + G80OutputSetPClk(output, pPriv->pclk); + } +} + +void +G80DispCommand(ScrnInfoPtr pScrn, CARD32 addr, CARD32 data) +{ + G80Ptr pNv = G80PTR(pScrn); + pNv->reg[0x00610304/4] = data; pNv->reg[0x00610300/4] = addr | 0x80010001; @@ -147,35 +188,17 @@ G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data) if(super) { if(super == 2) { - const int headOff = 0x800 * pNv->head; - const int orOff = 0x800 * pNv->or; - - if(pNv->reg[0x00610030/4] & 0x600) { - int lo_n, lo_m, hi_n, hi_m, p; - CARD32 lo = pNv->reg[(0x00614104+headOff)/4]; - CARD32 hi = pNv->reg[(0x00614108+headOff)/4]; - - pNv->reg[(0x00614100+headOff)/4] = 0x10000610; - lo &= 0xff00ff00; - hi &= 0x8000ff00; - - G80CalcPLL(pNv->pclk, &lo_n, &lo_m, &hi_n, &hi_m, &p); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + const CARD32 r = pNv->reg[0x00610030/4]; + int i; - lo |= (lo_m << 16) | lo_n; - hi |= (p << 28) | (hi_m << 16) | hi_n; - pNv->reg[(0x00614104+headOff)/4] = lo; - pNv->reg[(0x00614108+headOff)/4] = hi; - } + for(i = 0; i < xf86_config->num_crtc; i++) + { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + G80CrtcPrivPtr pPriv = crtc->driver_private; - pNv->reg[(0x00614200+headOff)/4] = 0; - switch(pNv->orType) { - case DAC: - pNv->reg[(0x00614280+orOff)/4] = 0; - break; - case SOR: - pNv->reg[(0x00614300+orOff)/4] = - (pNv->pclk > 165000) ? 0x101 : 0; - break; + if(r & (0x200 << pPriv->head)) + G80CrtcSetPClk(crtc); } } @@ -184,59 +207,16 @@ G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data) } } } -#define C(mthd, data) G80DispCommand(pNv, (mthd), (data)) -/* - * Performs load detection on a single DAC. - */ -Bool G80DispDetectLoad(ScrnInfoPtr pScrn, ORNum or) +Head +G80CrtcGetHead(xf86CrtcPtr crtc) { - G80Ptr pNv = G80PTR(pScrn); - const int dacOff = 2048 * or; - CARD32 load, tmp; - - pNv->reg[(0x0061A010+dacOff)/4] = 0x00000001; - pNv->reg[(0x0061A004+dacOff)/4] = 0x80150000; - while(pNv->reg[(0x0061A004+dacOff)/4] & 0x80000000); - tmp = pNv->architecture == 0x50 ? 420 : 340; - pNv->reg[(0x0061A00C+dacOff)/4] = tmp | 0x100000; - usleep(4500); - load = pNv->reg[(0x0061A00C+dacOff)/4]; - pNv->reg[(0x0061A00C+dacOff)/4] = 0; - pNv->reg[(0x0061A004+dacOff)/4] = 0x80550000; - - return (load & 0x38000000) == 0x38000000; -} - -/* - * Performs load detection on the DACs. Sets pNv->orType and pNv->or - * accordingly. - */ -Bool G80LoadDetect(ScrnInfoPtr pScrn) -{ - G80Ptr pNv = G80PTR(pScrn); - const int scrnIndex = pScrn->scrnIndex; - ORNum or; - - pNv->orType = DAC; - - for(or = DAC0; or <= DAC2; or++) { - xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on DAC%i ... ", or); - - if(G80DispDetectLoad(pScrn, or)) { - xf86ErrorF("found one!\n"); - pNv->or = or; - return TRUE; - } - - xf86ErrorF("nothing.\n"); - } - - return FALSE; + G80CrtcPrivPtr pPriv = crtc->driver_private; + return pPriv->head; } Bool -G80DispInit(ScrnInfoPtr pScrn) +G80DispPreInit(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); @@ -269,6 +249,14 @@ G80DispInit(ScrnInfoPtr pScrn) pNv->reg[0x0061B004/4] = 0x80550000; pNv->reg[0x0061B010/4] = 0x00000001; + return TRUE; +} + +Bool +G80DispInit(ScrnInfoPtr pScrn) +{ + G80Ptr pNv = G80PTR(pScrn); + if(pNv->reg[0x00610024/4] & 0x100) { pNv->reg[0x00610024/4] = 0x100; pNv->reg[0x006194E8/4] &= ~1; @@ -295,68 +283,59 @@ void G80DispShutdown(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); - CARD32 mask; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for(i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; - G80DispBlankScreen(pScrn, TRUE); + G80CrtcBlankScreen(crtc, TRUE); + } + + C(0x00000080, 0); + + for(i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + if(crtc->enabled) { + const CARD32 mask = 4 << G80CrtcGetHead(crtc); + + pNv->reg[0x00610024/4] = mask; + while(!(pNv->reg[0x00610024/4] & mask)); + } + } - mask = 4 << pNv->head; - pNv->reg[0x00610024/4] = mask; - while(!(pNv->reg[0x00610024/4] & mask)); pNv->reg[0x00610200/4] = 0; pNv->reg[0x00610300/4] = 0; while((pNv->reg[0x00610200/4] & 0x1e0000) != 0); } -static void -setupDAC(G80Ptr pNv, Head head, ORNum or, DisplayModePtr mode) +static Bool +G80CrtcModeFixup(xf86CrtcPtr crtc, + DisplayModePtr mode, DisplayModePtr adjusted_mode) { - const int dacOff = 0x80 * pNv->or; - - C(0x00000400 + dacOff, (head == HEAD0 ? 1 : 2) | 0x40); - C(0x00000404 + dacOff, - (mode->Flags & V_NHSYNC) ? 1 : 0 | - (mode->Flags & V_NVSYNC) ? 2 : 0); + // TODO: Fix up the mode here + return TRUE; } static void -setupSOR(G80Ptr pNv, Head head, ORNum or, DisplayModePtr mode) -{ - const int sorOff = 0x40 * pNv->or; - - C(0x00000600 + sorOff, - (head == HEAD0 ? 1 : 2) | - (mode->SynthClock > 165000 ? 0x500 : 0x100) | - ((mode->Flags & V_NHSYNC) ? 0x1000 : 0) | - ((mode->Flags & V_NVSYNC) ? 0x2000 : 0)); -} - -Bool -G80DispSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) +G80CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, + DisplayModePtr adjusted_mode, int x, int y) { - G80Ptr pNv = G80PTR(pScrn); + ScrnInfoPtr pScrn = crtc->scrn; + G80CrtcPrivPtr pPriv = crtc->driver_private; const int HDisplay = mode->HDisplay, VDisplay = mode->VDisplay; - const int headOff = 0x400 * pNv->head; + const int headOff = 0x400 * G80CrtcGetHead(crtc); int interlaceDiv, fudge; - if(pNv->BackendMode) - mode = pNv->BackendMode; - - pNv->pclk = mode->SynthClock; + // TODO: Use adjusted_mode and fix it up in G80CrtcModeFixup + pPriv->pclk = mode->Clock; /* Magic mode timing fudge factor */ fudge = ((mode->Flags & V_INTERLACE) && (mode->Flags & V_DBLSCAN)) ? 2 : 1; interlaceDiv = (mode->Flags & V_INTERLACE) ? 2 : 1; - switch(pNv->orType) { - case DAC: - setupDAC(pNv, pNv->head, pNv->or, mode); - break; - case SOR: - setupSOR(pNv, pNv->head, pNv->or, mode); - break; - } - - C(0x00000804 + headOff, mode->SynthClock | 0x800000); + C(0x00000804 + headOff, mode->Clock | 0x800000); C(0x00000808 + headOff, (mode->Flags & V_INTERLACE) ? 2 : 0); C(0x00000810 + headOff, 0); C(0x0000082C + headOff, 0); @@ -391,41 +370,25 @@ G80DispSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) C(0x000008A4 + headOff, 0); } C(0x000008A8 + headOff, 0x40000); - /* Use the screen's panning, but not if it's bogus */ - if(pScrn->frameX0 >= 0 && pScrn->frameY0 >= 0 && - pScrn->frameX0 + HDisplay <= pScrn->virtualX && - pScrn->frameY0 + VDisplay <= pScrn->virtualY) { - C(0x000008C0 + headOff, pScrn->frameY0 << 16 | pScrn->frameX0); - } else { - C(0x000008C0 + headOff, 0); - } + C(0x000008C0 + headOff, y << 16 | x); C(0x000008C8 + headOff, VDisplay << 16 | HDisplay); C(0x000008D4 + headOff, 0); C(0x000008D8 + headOff, mode->CrtcVDisplay << 16 | mode->CrtcHDisplay); C(0x000008DC + headOff, mode->CrtcVDisplay << 16 | mode->CrtcHDisplay); - G80DispBlankScreen(pScrn, FALSE); - - return TRUE; + G80CrtcBlankScreen(crtc, FALSE); } void -G80DispAdjustFrame(G80Ptr pNv, int x, int y) -{ - const int headOff = 0x400 * pNv->head; - - C(0x000008C0 + headOff, y << 16 | x); - C(0x00000080, 0); -} - -void -G80DispBlankScreen(ScrnInfoPtr pScrn, Bool blank) +G80CrtcBlankScreen(xf86CrtcPtr crtc, Bool blank) { + ScrnInfoPtr pScrn = crtc->scrn; G80Ptr pNv = G80PTR(pScrn); - const int headOff = 0x400 * pNv->head; + G80CrtcPrivPtr pPriv = crtc->driver_private; + const int headOff = 0x400 * pPriv->head; if(blank) { - G80DispHideCursor(pNv, FALSE); + G80CrtcShowHideCursor(crtc, FALSE, FALSE); C(0x00000840 + headOff, 0); C(0x00000844 + headOff, 0); @@ -444,82 +407,125 @@ G80DispBlankScreen(ScrnInfoPtr pScrn, Bool blank) C(0x00000884 + headOff, (pNv->videoRam << 2) - 0x40); if(pNv->architecture != 0x50) C(0x0000089C + headOff, 1); - if(pNv->cursorVisible) - G80DispShowCursor(pNv, FALSE); + if(pPriv->cursorVisible) + G80CrtcShowHideCursor(crtc, TRUE, FALSE); C(0x00000840 + headOff, pScrn->depth == 8 ? 0x80000000 : 0xc0000000); C(0x00000844 + headOff, (pNv->videoRam * 1024 - 0x5000) >> 8); if(pNv->architecture != 0x50) C(0x0000085C + headOff, 1); C(0x00000874 + headOff, 1); } - - C(0x00000080, 0); } void -G80DispDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +G80CrtcDPMSSet(xf86CrtcPtr crtc, int mode) { - G80Ptr pNv = G80PTR(pScrn); - const int off = 0x800 * pNv->or; - CARD32 tmp; - - /* - * DPMSModeOn everything on - * DPMSModeStandby hsync disabled, vsync enabled - * DPMSModeSuspend hsync enabled, vsync disabled - * DPMSModeOff sync disabled - */ - switch(pNv->orType) { - case DAC: - while(pNv->reg[(0x0061A004+off)/4] & 0x80000000); - - tmp = pNv->reg[(0x0061A004+off)/4]; - tmp &= ~0x7f; - tmp |= 0x80000000; - - if(mode == DPMSModeStandby || mode == DPMSModeOff) - tmp |= 1; - if(mode == DPMSModeSuspend || mode == DPMSModeOff) - tmp |= 4; - if(mode != DPMSModeOn) - tmp |= 0x10; - if(mode == DPMSModeOff) - tmp |= 0x40; - - pNv->reg[(0x0061A004+off)/4] = tmp; - - break; - - case SOR: - while(pNv->reg[(0x0061C004+off)/4] & 0x80000000); - - tmp = pNv->reg[(0x0061C004+off)/4]; - tmp |= 0x80000000; - - if(mode == DPMSModeOn) - tmp |= 1; - else - tmp &= ~1; - - pNv->reg[(0x0061C004+off)/4] = tmp; - - break; - } } /******************************** Cursor stuff ********************************/ -void G80DispShowCursor(G80Ptr pNv, Bool update) +static void G80CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update) { - const int headOff = 0x400 * pNv->head; + ScrnInfoPtr pScrn = crtc->scrn; + G80CrtcPrivPtr pPriv = crtc->driver_private; + const int headOff = 0x400 * G80CrtcGetHead(crtc); + + C(0x00000880 + headOff, show ? 0x85000000 : 0x5000000); + if(update) { + pPriv->cursorVisible = show; + C(0x00000080, 0); + } +} - C(0x00000880 + headOff, 0x85000000); - if(update) C(0x00000080, 0); +void G80CrtcShowCursor(xf86CrtcPtr crtc) +{ + G80CrtcShowHideCursor(crtc, TRUE, TRUE); } -void G80DispHideCursor(G80Ptr pNv, Bool update) +void G80CrtcHideCursor(xf86CrtcPtr crtc) { - const int headOff = 0x400 * pNv->head; + G80CrtcShowHideCursor(crtc, FALSE, TRUE); +} - C(0x00000880 + headOff, 0x5000000); - if(update) C(0x00000080, 0); +/******************************** CRTC stuff ********************************/ + +static Bool +G80CrtcLock(xf86CrtcPtr crtc) +{ + return FALSE; +} + +static void +G80CrtcPrepare(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if(!output->crtc) + output->funcs->mode_set(output, NULL, NULL); + } +} + +static void +G80CrtcCommit(xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + int i, crtc_mask = 0; + + /* If any heads are unused, blank them */ + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if(output->crtc) + /* XXXagp: This assumes that xf86_config->crtc[i] is HEADi */ + crtc_mask |= 1 << G80CrtcGetHead(output->crtc); + } + + for(i = 0; i < xf86_config->num_crtc; i++) + if(!((1 << i) & crtc_mask)) + G80CrtcBlankScreen(xf86_config->crtc[i], TRUE); + + C(0x00000080, 0); +} + +static const xf86CrtcFuncsRec g80_crtc_funcs = { + .dpms = G80CrtcDPMSSet, + .save = NULL, + .restore = NULL, + .lock = G80CrtcLock, + .unlock = NULL, + .mode_fixup = G80CrtcModeFixup, + .prepare = G80CrtcPrepare, + .mode_set = G80CrtcModeSet, + // .gamma_set = G80DispGammaSet, + .commit = G80CrtcCommit, + .shadow_create = NULL, + .shadow_destroy = NULL, + .set_cursor_position = G80SetCursorPosition, + .show_cursor = G80CrtcShowCursor, + .hide_cursor = G80CrtcHideCursor, + .load_cursor_argb = G80LoadCursorARGB, + .destroy = NULL, +}; + +void +G80DispCreateCrtcs(ScrnInfoPtr pScrn) +{ + Head head; + xf86CrtcPtr crtc; + G80CrtcPrivPtr g80_crtc; + + /* Create a "crtc" object for each head */ + for(head = HEAD0; head <= HEAD1; head++) { + crtc = xf86CrtcCreate(pScrn, &g80_crtc_funcs); + if(!crtc) return; + + g80_crtc = xnfcalloc(sizeof(*g80_crtc), 1); + g80_crtc->head = head; + crtc->driver_private = g80_crtc; + } } diff --git a/src/g80_display.h b/src/g80_display.h index 5213576..fac7877 100644 --- a/src/g80_display.h +++ b/src/g80_display.h @@ -1,10 +1,15 @@ -Bool G80LoadDetect(ScrnInfoPtr); -Bool G80DispDetectLoad(ScrnInfoPtr, ORNum or); +Bool G80DispPreInit(ScrnInfoPtr); Bool G80DispInit(ScrnInfoPtr); -Bool G80DispSetMode(ScrnInfoPtr, DisplayModePtr); void G80DispShutdown(ScrnInfoPtr); -void G80DispAdjustFrame(G80Ptr pNv, int x, int y); -void G80DispBlankScreen(ScrnInfoPtr, Bool blank); -void G80DispDPMSSet(ScrnInfoPtr, int mode, int flags); -void G80DispShowCursor(G80Ptr, Bool update); -void G80DispHideCursor(G80Ptr, Bool update); + +void G80DispCommand(ScrnInfoPtr, CARD32 addr, CARD32 data); +#define C(mthd, data) G80DispCommand(pScrn, (mthd), (data)) + +Head G80CrtcGetHead(xf86CrtcPtr); + +void G80CrtcBlankScreen(xf86CrtcPtr, Bool blank); +void G80CrtcEnableCursor(xf86CrtcPtr, Bool update); +void G80CrtcDisableCursor(xf86CrtcPtr, Bool update); +void G80CrtcSetCursorPosition(xf86CrtcPtr, int x, int y); + +void G80DispCreateCrtcs(ScrnInfoPtr pScrn); diff --git a/src/g80_driver.c b/src/g80_driver.c index 2a3120f..a4e7bad 100644 --- a/src/g80_driver.c +++ b/src/g80_driver.c @@ -30,6 +30,7 @@ #include <xf86_OSproc.h> #include <xf86Resources.h> +#include <xf86RandR12.h> #include <mipointer.h> #include <mibstore.h> #include <micmap.h> @@ -42,8 +43,8 @@ #include "g80_type.h" #include "g80_cursor.h" #include "g80_display.h" -#include "g80_ddc.h" #include "g80_dma.h" +#include "g80_output.h" #include "g80_xaa.h" #define G80_REG_SIZE (1024 * 1024 * 16) @@ -95,13 +96,11 @@ static const char *int10Symbols[] = { typedef enum { OPTION_HW_CURSOR, OPTION_NOACCEL, - OPTION_BACKEND_MODE, } G80Opts; static const OptionInfoRec G80Options[] = { { OPTION_HW_CURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_BACKEND_MODE, "BackendMode", OPTV_ANYSTR, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -122,17 +121,47 @@ G80FreeRec(ScrnInfoPtr pScrn) } static Bool +G80ResizeScreen(ScrnInfoPtr pScrn, int width, int height) +{ + G80Ptr pNv = G80PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int pitch = width * (pScrn->bitsPerPixel / 8); + int i; + + pitch = (pitch + 255) & ~255; + + pScrn->virtualX = width; + pScrn->virtualY = height; + + /* Can resize if XAA is disabled */ + if(!pNv->xaa) { + (*pScrn->pScreen->GetScreenPixmap)(pScrn->pScreen)->devKind = pitch; + pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); + + /* Re-set the modes so the new pitch is taken into account */ + for(i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + if(crtc->enabled) + xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); + } + } + + return TRUE; +} + +static const xf86CrtcConfigFuncsRec randr12_screen_funcs = { + .resize = G80ResizeScreen, +}; + +static Bool G80PreInit(ScrnInfoPtr pScrn, int flags) { G80Ptr pNv; EntityInfoPtr pEnt; pciVideoPtr pPci; PCITAG pcitag; - ClockRangePtr clockRanges; MessageType from; Bool primary; - int i; - char *s; const rgb zeros = {0, 0, 0}; const Gamma gzeros = {0.0, 0.0, 0.0}; CARD32 tmp; @@ -250,18 +279,6 @@ G80PreInit(ScrnInfoPtr pScrn, int flags) if(!xf86SetGamma(pScrn, gzeros)) goto fail; - /* - * Setup the ClockRanges, which describe what clock ranges are available, - * and what sort of modes they can be used for. - */ - clockRanges = xnfcalloc(sizeof(ClockRange), 1); - clockRanges->next = NULL; - clockRanges->minClock = 0; - clockRanges->maxClock = 400000; - clockRanges->clockIndex = -1; /* programmable */ - clockRanges->doubleScanAllowed = TRUE; - clockRanges->interlaceAllowed = TRUE; - /* Map memory */ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO registers at 0x%lx\n", pPci->memBase[0]); @@ -310,63 +327,40 @@ G80PreInit(ScrnInfoPtr pScrn, int flags) else pNv->table1 -= 0x10000; - /* Probe DDC */ - /* If no DDC info found, try DAC load detection */ + xf86CrtcConfigInit(pScrn, &randr12_screen_funcs); + xf86CrtcSetSizeRange(pScrn, 320, 200, 8192, 8192); + if(!xf86LoadSubModule(pScrn, "i2c")) goto fail; if(!xf86LoadSubModule(pScrn, "ddc")) goto fail; xf86LoaderReqSymLists(i2cSymbols, ddcSymbols, NULL); - if(!G80ProbeDDC(pScrn) && !G80LoadDetect(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No display devices found\n"); + + if(!G80DispPreInit(pScrn)) goto fail; + /* Read the DDC routing table and create outputs */ + if(!G80CreateOutputs(pScrn)) goto fail; + /* Create the crtcs */ + G80DispCreateCrtcs(pScrn); + + /* We can grow the desktop if XAA is disabled */ + if(!xf86InitialConfiguration(pScrn, pNv->NoAccel)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid initial configuration found\n"); + goto fail; + } + pScrn->displayWidth = (pScrn->virtualX + 255) & ~255; + + if(!xf86RandR12PreInit(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); goto fail; } - /* Hardcode HEAD0 for now. RandR 1.2 will move this into a Crtc struct. */ - pNv->head = 0; - - i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, - pScrn->display->modes, clockRanges, - NULL, 256, 8192, - 512, 128, 8192, - pScrn->display->virtualX, - pScrn->display->virtualY, - pNv->videoRam * 1024 - G80_RESERVED_VIDMEM, - LOOKUP_BEST_REFRESH); - if(i == -1) goto fail; - xf86PruneDriverModes(pScrn); - if(i == 0 || !pScrn->modes) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + if(!pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); goto fail; } - xf86SetCrtcForModes(pScrn, 0); pScrn->currentMode = pScrn->modes; xf86PrintModes(pScrn); xf86SetDpi(pScrn, 0, 0); - /* Custom backend timings */ - pNv->BackendMode = NULL; - if((s = xf86GetOptValString(pNv->Options, OPTION_BACKEND_MODE))) { - DisplayModePtr mode; - - for(mode = pScrn->modes; ; mode = mode->next) { - if(!strcmp(mode->name, s)) - break; - if(mode->next == pScrn->modes) { - mode = NULL; - break; - } - } - - pNv->BackendMode = mode; - - if(mode) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BackendMode: Using mode " - "\"%s\" for display timings\n", mode->name); - else - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Cannot honor " - "\"BackendMode\" option: no mode named \"%s\" " - "found.\n", s); - } - /* Load fb */ if(!xf86LoadSubModule(pScrn, "fb")) goto fail; xf86LoaderReqSymLists(fbSymbols, NULL); @@ -401,15 +395,11 @@ fail: static Bool AcquireDisplay(ScrnInfoPtr pScrn) { - G80Ptr pNv = G80PTR(pScrn); - if(!G80DispInit(pScrn)) return FALSE; - if(!G80CursorAcquire(pNv)) - return FALSE; - if(!G80DispSetMode(pScrn, pScrn->currentMode)) + if(!G80CursorAcquire(pScrn)) return FALSE; - G80DispDPMSSet(pScrn, DPMSModeOn, 0); + xf86SetDesiredModes(pScrn); return TRUE; } @@ -422,7 +412,7 @@ ReleaseDisplay(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); - G80CursorRelease(pNv); + G80CursorRelease(pScrn); G80DispShutdown(pScrn); if(pNv->int10 && pNv->int10Mode) { @@ -450,8 +440,7 @@ G80CloseScreen(int scrnIndex, ScreenPtr pScreen) if(pNv->xaa) XAADestroyInfoRec(pNv->xaa); - if(pNv->HWCursor) - xf86DestroyCursorInfoRec(pNv->CursorInfo); + xf86_cursors_fini(pScreen); if(xf86ServerIsExiting()) { if(pNv->int10) xf86FreeInt10(pNv->int10); @@ -477,6 +466,8 @@ G80BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) if(pNv->DMAKickoffCallback) (*pNv->DMAKickoffCallback)(pScrnInfo); + G80OutputResetCachedStatus(pScrnInfo); + pScreen->BlockHandler = pNv->BlockHandler; (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); pScreen->BlockHandler = G80BlockHandler; @@ -485,13 +476,7 @@ G80BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask) static Bool G80SaveScreen(ScreenPtr pScreen, int mode) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - - if(!pScrn->vtSema) return FALSE; - - G80DispBlankScreen(pScrn, !xf86IsUnblank(mode)); - - return TRUE; + return FALSE; } static void @@ -731,8 +716,6 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* pad the screen pitch to 256 bytes */ pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); - pitch = (pitch + 0xff) & ~0xff; - pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); /* fb init */ if(!fbScreenInit(pScreen, pNv->mem, @@ -779,7 +762,7 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if(!G80XAAInit(pScreen)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Hardware acceleration initialization failed\n"); - pNv->NoAccel = FALSE; + return FALSE; } } @@ -808,7 +791,7 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) CMAP_PALETTED_TRUECOLOR)) return FALSE; - xf86DPMSInit(pScreen, G80DispDPMSSet, 0); + xf86DPMSInit(pScreen, xf86DPMSSet, 0); /* Clear the screen */ if(pNv->xaa) { @@ -834,6 +817,9 @@ G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pNv->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = G80BlockHandler; + if(!xf86CrtcScreenInit(pScreen)) + return FALSE; + return TRUE; } @@ -847,22 +833,12 @@ static Bool G80SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - - return G80DispSetMode(pScrn, mode); + return xf86SetSingleMode(pScrn, mode, RR_Rotate_0); } static void G80AdjustFrame(int scrnIndex, int x, int y, int flags) { - ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - G80Ptr pNv = G80PTR(pScrn); - - if(x + pScrn->currentMode->HDisplay > pScrn->virtualX || - y + pScrn->currentMode->VDisplay > pScrn->virtualY || - x < 0 || y < 0) - /* Ignore bogus panning */ - return; - G80DispAdjustFrame(pNv, x, y); } static Bool diff --git a/src/g80_ddc.c b/src/g80_output.c index 4fa076e..354d39a 100644 --- a/src/g80_ddc.c +++ b/src/g80_output.c @@ -30,8 +30,7 @@ #include <xf86DDC.h> #include "g80_type.h" -#include "g80_ddc.h" -#include "g80_display.h" +#include "g80_output.h" static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv) { @@ -111,7 +110,7 @@ fail: static void G80_I2CPutBits(I2CBusPtr b, int clock, int data) { G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]); - const int off = b->DriverPrivate.val; + const int off = b->DriverPrivate.val * 0x18; pNv->reg[(0x0000E138+off)/4] = 4 | clock | data << 1; } @@ -119,7 +118,7 @@ static void G80_I2CPutBits(I2CBusPtr b, int clock, int data) static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data) { G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]); - const int off = b->DriverPrivate.val; + const int off = b->DriverPrivate.val * 0x18; unsigned char val; val = pNv->reg[(0x0000E138+off)/4]; @@ -127,18 +126,16 @@ static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data) *data = !!(val & 2); } -static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus) +static I2CBusPtr +G80I2CInit(ScrnInfoPtr pScrn, const char *name, const int port) { - G80Ptr pNv = G80PTR(pScrn); I2CBusPtr i2c; - xf86MonPtr monInfo = NULL; - const int off = bus * 0x18; /* Allocate the I2C bus structure */ i2c = xf86CreateI2CBusRec(); if(!i2c) return NULL; - i2c->BusName = "DDC"; + i2c->BusName = strdup(name); i2c->scrnIndex = pScrn->scrnIndex; i2c->I2CPutBits = G80_I2CPutBits; i2c->I2CGetBits = G80_I2CGetBits; @@ -147,15 +144,62 @@ static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus) i2c->BitTimeout = 40; i2c->ByteTimeout = 40; i2c->AcknTimeout = 40; - i2c->DriverPrivate.val = off; + i2c->DriverPrivate.val = port; - if(!xf86I2CBusInit(i2c)) goto done; + if(xf86I2CBusInit(i2c)) { + return i2c; + } else { + xfree(i2c); + return NULL; + } +} + +void +G80OutputSetPClk(xf86OutputPtr output, int pclk) +{ + G80OutputPrivPtr pPriv = output->driver_private; + pPriv->set_pclk(output, pclk); +} + +int +G80OutputModeValid(xf86OutputPtr output, DisplayModePtr mode) +{ + if(mode->Clock > 400000 || mode->Clock < 25000) + return MODE_CLOCK_RANGE; + + return MODE_OK; +} + +Bool +G80OutputModeFixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +void +G80OutputPrepare(xf86OutputPtr output) +{ +} + +void +G80OutputCommit(xf86OutputPtr output) +{ +} + +static xf86MonPtr +ProbeDDC(I2CBusPtr i2c) +{ + ScrnInfoPtr pScrn = xf86Screens[i2c->scrnIndex]; + G80Ptr pNv = G80PTR(pScrn); + xf86MonPtr monInfo = NULL; + const int bus = i2c->DriverPrivate.val, off = bus * 0x18; - pNv->reg[(0x0000E138+off)/4] = 7; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for EDID on I2C bus %i...\n", bus); + pNv->reg[(0x0000E138+off)/4] = 7; + /* Should probably use xf86OutputGetEDID here */ monInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, i2c); - pNv->reg[(0x0000E138+off)/4] = 3; if(monInfo) { @@ -167,64 +211,137 @@ static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus) xf86DrvMsg(pScrn->scrnIndex, X_INFO, " ... none found\n"); } -done: - xf86DestroyI2CBusRec(i2c, TRUE, TRUE); - return monInfo; } /* - * Try DDC on each bus until we find one that works. + * Read an EDID from the i2c port. Perform load detection on the DAC (if + * present) to see if the display is connected via VGA. Sets the cached status + * of both outputs. The status is marked dirty again in the BlockHandler. + */ +void G80OutputPartnersDetect(xf86OutputPtr dac, xf86OutputPtr sor, I2CBusPtr i2c) +{ + xf86MonPtr monInfo = ProbeDDC(i2c); + xf86OutputPtr connected = NULL; + Bool load = dac && G80DacLoadDetect(dac); + + if(dac) { + G80OutputPrivPtr pPriv = dac->driver_private; + + if(load) { + pPriv->cached_status = XF86OutputStatusConnected; + connected = dac; + } else { + pPriv->cached_status = XF86OutputStatusDisconnected; + } + } + + if(sor) { + G80OutputPrivPtr pPriv = sor->driver_private; + + if(monInfo && !load) { + pPriv->cached_status = XF86OutputStatusConnected; + connected = sor; + } else { + pPriv->cached_status = XF86OutputStatusDisconnected; + } + } + + if(connected) + xf86OutputSetEDID(connected, monInfo); +} + +/* + * Reset the cached output status for all outputs. Called from G80BlockHandler. */ -Bool G80ProbeDDC(ScrnInfoPtr pScrn) +void +G80OutputResetCachedStatus(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + + for(i = 0; i < xf86_config->num_output; i++) { + G80OutputPrivPtr pPriv = xf86_config->output[i]->driver_private; + pPriv->cached_status = XF86OutputStatusUnknown; + } +} + +DisplayModePtr +G80OutputGetDDCModes(xf86OutputPtr output) +{ + /* The EDID is read as part of the detect step */ + output->funcs->detect(output); + return xf86OutputGetEDIDModes(output); +} + +void +G80OutputDestroy(xf86OutputPtr output) +{ + G80OutputPrivPtr pPriv = output->driver_private; + + if(pPriv->partner) + ((G80OutputPrivPtr)pPriv->partner->driver_private)->partner = NULL; + else + xf86DestroyI2CBusRec(pPriv->i2c, TRUE, TRUE); + pPriv->i2c = NULL; +} + +Bool +G80CreateOutputs(ScrnInfoPtr pScrn) { G80Ptr pNv = G80PTR(pScrn); - xf86MonPtr monInfo; - int port; - Bool flatPanel; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; if(!G80ReadPortMapping(pScrn->scrnIndex, pNv)) return FALSE; - for(port = 0; port < 4; port++) { - if(pNv->i2cMap[port].dac == -1 && pNv->i2cMap[port].sor == -1) - /* No outputs on this port. Skip it. */ + /* For each DDC port, create an output for the attached ORs */ + for(i = 0; i < 4; i++) { + xf86OutputPtr dac = NULL, sor = NULL; + I2CBusPtr i2c; + char i2cName[16]; + + if(pNv->i2cMap[i].dac == -1 && pNv->i2cMap[i].sor == -1) + /* No outputs on this port */ continue; - monInfo = G80ProbeDDCBus(pScrn, port); - if(!monInfo) - /* No EDID on this port. */ + snprintf(i2cName, sizeof(i2cName), "I2C%i", i); + i2c = G80I2CInit(pScrn, i2cName, i); + if(!i2c) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to initialize I2C for port %i.\n", + i); continue; + } - flatPanel = (monInfo->features.input_type == 1); + if(pNv->i2cMap[i].dac != -1) + dac = G80CreateDac(pScrn, pNv->i2cMap[i].dac); + if(pNv->i2cMap[i].sor != -1) + sor = G80CreateSor(pScrn, pNv->i2cMap[i].sor); - if(pNv->i2cMap[port].dac != -1 && - G80DispDetectLoad(pScrn, pNv->i2cMap[port].dac)) { - pNv->orType = DAC; - pNv->or = pNv->i2cMap[port].dac; - } else if(pNv->i2cMap[port].sor != -1) { - pNv->orType = SOR; - pNv->or = pNv->i2cMap[port].sor; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Saw an EDID on I2C port %i but no DAC load was " - "detected and no SOR is connected to this port. Using " - "DAC%i.\n", port, - pNv->or); - pNv->orType = DAC; - pNv->or = pNv->i2cMap[port].dac; + if(dac) { + G80OutputPrivPtr pPriv = dac->driver_private; + + pPriv->partner = sor; + pPriv->i2c = i2c; } + if(sor) { + G80OutputPrivPtr pPriv = sor->driver_private; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "Found a %s on I2C port %i, assigning %s%i\n", - flatPanel ? "flat panel" : "CRT", - port, pNv->orType == SOR ? "SOR" : "DAC", pNv->or); + pPriv->partner = dac; + pPriv->i2c = i2c; + } + } - pScrn->monitor->DDC = monInfo; - xf86SetDDCproperties(pScrn, monInfo); + /* For each output, set the crtc and clone masks */ + for(i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; - return TRUE; + /* Any output can connect to any head */ + output->possible_crtcs = 0x3; + output->possible_clones = 0; } - return FALSE; + return TRUE; } diff --git a/src/g80_output.h b/src/g80_output.h new file mode 100644 index 0000000..0b666f5 --- /dev/null +++ b/src/g80_output.h @@ -0,0 +1,29 @@ +typedef struct G80OutputPrivRec { + ORType type; + ORNum or; + + xf86OutputPtr partner; + I2CBusPtr i2c; + + xf86OutputStatus cached_status; + + void (*set_pclk)(xf86OutputPtr, int pclk); +} G80OutputPrivRec, *G80OutputPrivPtr; + +void G80OutputSetPClk(xf86OutputPtr, int pclk); +int G80OutputModeValid(xf86OutputPtr, DisplayModePtr); +Bool G80OutputModeFixup(xf86OutputPtr, DisplayModePtr mode, DisplayModePtr adjusted_mode); +void G80OutputPrepare(xf86OutputPtr); +void G80OutputCommit(xf86OutputPtr); +void G80OutputPartnersDetect(xf86OutputPtr dac, xf86OutputPtr sor, I2CBusPtr i2c); +void G80OutputResetCachedStatus(ScrnInfoPtr); +DisplayModePtr G80OutputGetDDCModes(xf86OutputPtr); +void G80OutputDestroy(xf86OutputPtr); +Bool G80CreateOutputs(ScrnInfoPtr); + +/* g80_dac.c */ +xf86OutputPtr G80CreateDac(ScrnInfoPtr, ORNum); +Bool G80DacLoadDetect(xf86OutputPtr); + +/* g80_sor.c */ +xf86OutputPtr G80CreateSor(ScrnInfoPtr, ORNum); diff --git a/src/g80_sor.c b/src/g80_sor.c new file mode 100644 index 0000000..90119f0 --- /dev/null +++ b/src/g80_sor.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2007 NVIDIA, Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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 + +#define DPMS_SERVER +#include <X11/extensions/dpms.h> + +#include "g80_type.h" +#include "g80_display.h" +#include "g80_output.h" + +static void +G80SorSetPClk(xf86OutputPtr output, int pclk) +{ + G80Ptr pNv = G80PTR(output->scrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int orOff = 0x800 * pPriv->or; + + pNv->reg[(0x00614300+orOff)/4] = (pclk > 165000) ? 0x101 : 0; +} + +static void +G80SorDPMSSet(xf86OutputPtr output, int mode) +{ + G80Ptr pNv = G80PTR(output->scrn); + G80OutputPrivPtr pPriv = output->driver_private; + const int off = 0x800 * pPriv->or; + CARD32 tmp; + + while(pNv->reg[(0x0061C004+off)/4] & 0x80000000); + + tmp = pNv->reg[(0x0061C004+off)/4]; + tmp |= 0x80000000; + + if(mode == DPMSModeOn) + tmp |= 1; + else + tmp &= ~1; + + pNv->reg[(0x0061C004+off)/4] = tmp; +} + +static void +G80SorModeSet(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + G80OutputPrivPtr pPriv = output->driver_private; + const int sorOff = 0x40 * pPriv->or; + + if(!adjusted_mode) { + /* Disconnect the SOR */ + C(0x00000600 + sorOff, 0); + return; + } + + // This wouldn't be necessary, but the server is stupid and calls + // G80SorDPMSSet after the output is disconnected, even though the hardware + // turns it off automatically. + G80SorDPMSSet(output, DPMSModeOn); + + C(0x00000600 + sorOff, + (G80CrtcGetHead(output->crtc) == HEAD0 ? 1 : 2) | + (adjusted_mode->Clock > 165000 ? 0x500 : 0x100) | + ((adjusted_mode->Flags & V_NHSYNC) ? 0x1000 : 0) | + ((adjusted_mode->Flags & V_NVSYNC) ? 0x2000 : 0)); +} + +static xf86OutputStatus +G80SorDetect(xf86OutputPtr output) +{ + + G80OutputPrivPtr pPriv = output->driver_private; + + /* Assume physical status isn't going to change before the BlockHandler */ + if(pPriv->cached_status != XF86OutputStatusUnknown) + return pPriv->cached_status; + + G80OutputPartnersDetect(pPriv->partner, output, pPriv->i2c); + return pPriv->cached_status; +} + +static void +G80SorDestroy(xf86OutputPtr output) +{ + G80OutputDestroy(output); + + xfree(output->driver_private); + output->driver_private = NULL; +} + +static const xf86OutputFuncsRec G80SorOutputFuncs = { + .dpms = G80SorDPMSSet, + .save = NULL, + .restore = NULL, + .mode_valid = G80OutputModeValid, + .mode_fixup = G80OutputModeFixup, + .prepare = G80OutputPrepare, + .commit = G80OutputCommit, + .mode_set = G80SorModeSet, + .detect = G80SorDetect, + .get_modes = G80OutputGetDDCModes, + .destroy = G80SorDestroy, +}; + +xf86OutputPtr +G80CreateSor(ScrnInfoPtr pScrn, ORNum or) +{ + G80OutputPrivPtr pPriv = xnfcalloc(sizeof(*pPriv), 1); + xf86OutputPtr output; + char orName[5]; + + if(!pPriv) + return FALSE; + + snprintf(orName, 5, "DVI%i", or); + output = xf86OutputCreate(pScrn, &G80SorOutputFuncs, orName); + + pPriv->type = SOR; + pPriv->or = or; + pPriv->cached_status = XF86OutputStatusUnknown; + pPriv->set_pclk = G80SorSetPClk; + output->driver_private = pPriv; + output->interlaceAllowed = TRUE; + output->doubleScanAllowed = TRUE; + + return output; +} diff --git a/src/g80_type.h b/src/g80_type.h index 39d737c..95517e3 100644 --- a/src/g80_type.h +++ b/src/g80_type.h @@ -2,6 +2,9 @@ #include <xf86.h> #include <xf86int10.h> #include <xf86Cursor.h> +#include <xf86DDC.h> +#include <xf86Crtc.h> +#include <xf86int10.h> typedef enum Head { HEAD0 = 0, @@ -36,12 +39,6 @@ typedef struct G80Rec { ORNum sor; } i2cMap[4]; - float pclk; /* Current mode pclk in kHz */ - - Head head; - ORType orType; - ORNum or; - xf86Int10InfoPtr int10; int int10Mode; /* Console mode to restore */ @@ -49,12 +46,6 @@ typedef struct G80Rec { OptionInfoPtr Options; Bool HWCursor; Bool NoAccel; - DisplayModePtr BackendMode; - - /* Cursor */ - xf86CursorInfoPtr CursorInfo; - Bool cursorVisible; - CARD32 tmpCursor[256]; /* Temporary 1bpp cursor image */ /* XAA */ XAAInfoRecPtr xaa; @@ -68,8 +59,8 @@ typedef struct G80Rec { CARD32 * dmaBase; void (*DMAKickoffCallback)(ScrnInfoPtr); - CloseScreenProcPtr CloseScreen; - ScreenBlockHandlerProcPtr BlockHandler; + CloseScreenProcPtr CloseScreen; + ScreenBlockHandlerProcPtr BlockHandler; } G80Rec, *G80Ptr; #define G80PTR(p) ((G80Ptr)((p)->driverPrivate)) diff --git a/src/local_xf86Rename.h b/src/local_xf86Rename.h new file mode 100644 index 0000000..f3a07c6 --- /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) nv_##x diff --git a/src/nv_driver.c b/src/nv_driver.c index d90dd37..c8b98b8 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -333,7 +333,7 @@ static SymTabRec NVKnownChipsets[] = { 0x10DE0244, "GeForce Go 6150" }, { 0x10DE0247, "GeForce Go 6100" }, -#if SUPPORT_G80 +/*************** G8x ***************/ { 0x10DE0191, "GeForce 8800 GTX" }, { 0x10DE0193, "GeForce 8800 GTS" }, { 0x10DE019D, "Quadro FX 5600" }, @@ -343,7 +343,6 @@ static SymTabRec NVKnownChipsets[] = { 0x10DE0421, "GeForce 8500 GT" }, { 0x10DE0422, "GeForce 8400 GS" }, { 0x10DE0423, "GeForce 8300 GS" }, -#endif {-1, NULL} }; @@ -660,7 +659,6 @@ NVGetPCIXpressChip (pciVideoPtr pVideo) return pciid; } -#if SUPPORT_G80 static Bool NVIsG80(int chipType) { @@ -673,7 +671,6 @@ NVIsG80(int chipType) return FALSE; } -#endif /* Mandatory */ static Bool @@ -759,10 +756,8 @@ NVProbe(DriverPtr drv, int flags) default: break; /* we don't recognize it */ } -#if SUPPORT_G80 if(NVIsG80((*ppPci)->chipType)) canHandle = TRUE; -#endif if(canHandle) { NVChipsets[numUsed].token = pciid; @@ -800,11 +795,9 @@ NVProbe(DriverPtr drv, int flags) if(pPci->vendor == PCI_VENDOR_NVIDIA_SGS) { if(RivaGetScrnInfoRec(NVPciChipsets, usedChips[i])) foundScreen = TRUE; -#if SUPPORT_G80 } else if (NVIsG80(pPci->chipType)) { if(G80GetScrnInfoRec(NVPciChipsets, usedChips[i])) foundScreen = TRUE; -#endif } else { if(NVGetScrnInfoRec(NVPciChipsets, usedChips[i])) foundScreen = TRUE; @@ -1027,7 +1020,6 @@ Bool NVI2CInit(ScrnInfoPtr pScrn) } -#ifdef USE_CVTMODE_FUNC /* Copied from ddc/Property.c */ static DisplayModePtr NVModesAdd(DisplayModePtr Modes, DisplayModePtr Additions) @@ -1051,7 +1043,6 @@ NVModesAdd(DisplayModePtr Modes, DisplayModePtr Additions) return Modes; } -#endif /* Mandatory */ Bool @@ -1062,9 +1053,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) int i, max_width, max_height; ClockRangePtr clockRanges; const char *s; -#ifdef USE_CVTMODE_FUNC - int config_mon_rates; -#endif + Bool config_mon_rates; if (flags & PROBE_DETECT) { EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[0]); @@ -1522,13 +1511,11 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) pNv->alphaCursor = (pNv->Architecture >= NV_ARCH_10) && ((pNv->Chipset & 0x0ff0) != 0x0100); -#ifdef USE_CVTMODE_FUNC if ((pScrn->monitor->nHsync == 0) && (pScrn->monitor->nVrefresh == 0)) config_mon_rates = FALSE; else config_mon_rates = TRUE; -#endif NVCommonSetup(pScrn); @@ -1599,7 +1586,6 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) max_height = 4096; } -#ifdef USE_CVTMODE_FUNC /* If DFP, add a modeline corresponding to its panel size */ if (pNv->FlatPanel && !pNv->Television && pNv->fpWidth && pNv->fpHeight) { DisplayModePtr Mode; @@ -1628,7 +1614,6 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) pScrn->monitor->nVrefresh = 1; } } -#endif /* * xf86ValidateModes will check that the mode HTotal and VTotal values diff --git a/src/nv_include.h b/src/nv_include.h index 03f2997..648ac31 100644 --- a/src/nv_include.h +++ b/src/nv_include.h @@ -3,19 +3,14 @@ #ifndef __NV_INCLUDE_H__ #define __NV_INCLUDE_H__ -#if !USE_LIBC_WRAPPER #include <string.h> #include <math.h> #include <unistd.h> -#endif /* All drivers should typically include these */ #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Resources.h" -#if USE_LIBC_WRAPPER -#include "xf86_ansic.h" -#endif #include "compiler.h" /* Drivers for PCI hardware need this */ diff --git a/src/nv_local.h b/src/nv_local.h index 6cb0264..3d5d202 100644 --- a/src/nv_local.h +++ b/src/nv_local.h @@ -46,9 +46,6 @@ * HW. Put all affected includes, typdefs, etc. here so the riva_hw.* files * can stay generic in nature. */ -#if USE_LIBC_WRAPPER -#include "xf86_ansic.h" -#endif #include "compiler.h" #include "xf86_OSproc.h" diff --git a/src/nv_video.c b/src/nv_video.c index 1a428fb..c9ee5fe 100644 --- a/src/nv_video.c +++ b/src/nv_video.c @@ -7,9 +7,6 @@ #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Resources.h" -#if USE_LIBC_WRAPPER -#include "xf86_ansic.h" -#endif #include "compiler.h" #include "xf86PciInfo.h" #include "xf86Pci.h" @@ -83,11 +80,7 @@ static int NVGetBlitPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); static void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool); static void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool); -#if HAVE_XV_DRAWABLE static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr); -#else -static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer); -#endif static void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer); static int NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *); @@ -1012,10 +1005,8 @@ static int NVPutImage short height, Bool Sync, RegionPtr clipBoxes, - pointer data -#if HAVE_XV_DRAWABLE - , DrawablePtr pDraw -#endif + pointer data, + DrawablePtr pDraw ) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; diff --git a/src/riva_include.h b/src/riva_include.h index 675899b..2f269df 100644 --- a/src/riva_include.h +++ b/src/riva_include.h @@ -3,17 +3,12 @@ #ifndef __RIVA_INCLUDE_H__ #define __RIVA_INCLUDE_H__ -#if !USE_LIBC_WRAPPER #include <string.h> -#endif /* All drivers should typically include these */ #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Resources.h" -#if USE_LIBC_WRAPPER -#include "xf86_ansic.h" -#endif #include "compiler.h" /* Drivers for PCI hardware need this */ diff --git a/src/riva_local.h b/src/riva_local.h index bdfe2b9..833ed04 100644 --- a/src/riva_local.h +++ b/src/riva_local.h @@ -46,9 +46,6 @@ * HW. Put all affected includes, typdefs, etc. here so the riva_hw.* files * can stay generic in nature. */ -#if USE_LIBC_WRAPPER -#include "xf86_ansic.h" -#endif #include "compiler.h" #include "xf86_OSproc.h" |