summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2007-04-24 15:43:48 -0700
committerAaron Plattner <aplattner@nvidia.com>2007-04-24 15:43:48 -0700
commitc6e4105ce40ef053e026cc0ffe4925ab568ea700 (patch)
treefc0dc085da1e894a95ae8fddd6d06e4703d143ad
parent5d9b75b432dbc525e10c1c00436a1820456f6fb4 (diff)
parent4ff648c85f8aa90b343b7e2df176c0511b3cdaa5 (diff)
Merge branch 'randr-1.2'
Conflicts: configure.ac man/Makefile.am man/nv.man src/g80_display.h src/g80_output.c src/nv_driver.c
-rw-r--r--Makefile.am2
-rw-r--r--compat/.gitignore2
-rw-r--r--compat/Makefile.am15
-rw-r--r--compat/README7
-rw-r--r--configure.ac70
-rw-r--r--man/Makefile.am9
-rw-r--r--man/nv.man13
-rw-r--r--src/Makefile.am29
-rw-r--r--src/g80_cursor.c150
-rw-r--r--src/g80_cursor.h8
-rw-r--r--src/g80_dac.c199
-rw-r--r--src/g80_ddc.h1
-rw-r--r--src/g80_display.c410
-rw-r--r--src/g80_display.h21
-rw-r--r--src/g80_driver.c164
-rw-r--r--src/g80_output.c (renamed from src/g80_ddc.c)219
-rw-r--r--src/g80_output.h29
-rw-r--r--src/g80_sor.c151
-rw-r--r--src/g80_type.h19
-rw-r--r--src/local_xf86Rename.h23
-rw-r--r--src/nv_driver.c19
-rw-r--r--src/nv_include.h5
-rw-r--r--src/nv_local.h3
-rw-r--r--src/nv_video.c13
-rw-r--r--src/riva_include.h5
-rw-r--r--src/riva_local.h3
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
diff --git a/man/nv.man b/man/nv.man
index 0d8d079..6ef62c5 100644
--- a/man/nv.man
+++ b/man/nv.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"