mirror of
https://github.com/X11Libre/xf86-video-nv.git
synced 2026-04-14 11:04:25 +00:00
Initial G80 support. Bump to 1.99.1.
This commit is contained in:
26
COPYING
26
COPYING
@@ -1,12 +1,20 @@
|
||||
This is a stub file. This package has not yet had its complete licensing
|
||||
information compiled. Please see the individual source files for details on
|
||||
your rights to use and modify this software.
|
||||
Copyright (c) 2007 NVIDIA, Corporation
|
||||
|
||||
Please submit updated COPYING files to the Xorg bugzilla:
|
||||
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:
|
||||
|
||||
https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
All licensing questions regarding this software should be directed at the
|
||||
Xorg mailing list:
|
||||
|
||||
http://lists.freedesktop.org/mailman/listinfo/xorg
|
||||
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.
|
||||
|
||||
13
configure.ac
13
configure.ac
@@ -22,7 +22,7 @@
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([xf86-video-nv],
|
||||
1.2.2.1,
|
||||
1.99.1,
|
||||
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
|
||||
xf86-video-nv)
|
||||
|
||||
@@ -63,6 +63,17 @@ PKG_CHECK_EXISTS([xorg-server >= 1.0.99.901],
|
||||
PKG_CHECK_MODULES(XORG, [xorg-server xproto fontsproto $REQUIRED_MODULES])
|
||||
sdkdir=$(pkg-config --variable=sdkdir xorg-server)
|
||||
|
||||
# Check for optional compile-time support
|
||||
AC_ARG_ENABLE(g80, AC_HELP_STRING([--enable-g80],
|
||||
[Enable G80 support [[default=no]]]),
|
||||
[SUPPORT_G80="$enableval"],
|
||||
[SUPPORT_G80=no])
|
||||
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.
|
||||
|
||||
@@ -41,6 +41,12 @@ 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)"|' \
|
||||
@@ -51,7 +57,8 @@ 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|__filemansuffix__|$(FILE_MAN_SUFFIX)|g' \
|
||||
-e 's|__support_g80__|$(MAN_SUPPORT_G80)|g'
|
||||
|
||||
SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
|
||||
|
||||
|
||||
80
man/nv.man
80
man/nv.man
@@ -58,6 +58,12 @@ NV40, NV41, NV43, NV44, NV45, C51
|
||||
.TP 22
|
||||
.B GeForce 7XXX
|
||||
G70, G71, G72, G73
|
||||
.de G8
|
||||
.TP 22
|
||||
.B GeForce 8XXX
|
||||
G80
|
||||
..
|
||||
.if __support_g80__ .G8
|
||||
|
||||
.SH CONFIGURATION DETAILS
|
||||
Please refer to __xconfigfile__(__filemansuffix__) for general configuration
|
||||
@@ -69,7 +75,7 @@ present for all chips.
|
||||
.PP
|
||||
The following driver
|
||||
.B Options
|
||||
are supported:
|
||||
are supported for pre-G80 hardware:
|
||||
.TP
|
||||
.BI "Option \*qHWCursor\*q \*q" boolean \*q
|
||||
Enable or disable the HW cursor. Default: on.
|
||||
@@ -128,42 +134,54 @@ Default: no rotation support.
|
||||
.TP
|
||||
.BI "Option \*qShadowFB\*q \*q" boolean \*q
|
||||
Enable or disable use of the shadow framebuffer layer. Default: off.
|
||||
.
|
||||
.\" ******************** begin G80 section ********************
|
||||
.de G8
|
||||
.PP
|
||||
The following driver
|
||||
.B Options
|
||||
are available for G80:
|
||||
.TP
|
||||
.BI "Option \*qHWCursor\*q \*q" boolean \*q
|
||||
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"
|
||||
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
|
||||
.SH AUTHORS
|
||||
Authors include: David McKay, Jarno Paananen, Chas Inman, Dave Schmenk,
|
||||
Mark Vojkovich
|
||||
Mark Vojkovich, Aaron Plattner
|
||||
.SH COPYRIGHT
|
||||
.LP
|
||||
NOTICE TO USER: The source code is copyrighted under U.S. and
|
||||
international laws. Users and possessors of this source code are
|
||||
hereby granted a nonexclusive, royalty-free copyright license to
|
||||
use this code in individual and commercial software.
|
||||
Copyright (c) 2003 - 2007 NVIDIA, Corporation
|
||||
.LP
|
||||
Any use of this source code must include, in the user documentation and
|
||||
internal comments to the code, notices to the end user as follows:
|
||||
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:
|
||||
.LP
|
||||
Copyright 1993-2003 NVIDIA, Corporation. All rights reserved.
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
.LP
|
||||
NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY
|
||||
OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
|
||||
WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPORATION
|
||||
DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE,
|
||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT,
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
|
||||
NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL,
|
||||
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 SOURCE CODE.
|
||||
.LP
|
||||
U.S. Government End Users. This source code is a "commercial
|
||||
item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995),
|
||||
consisting of "commercial computer software" and "commercial
|
||||
computer software documentation," as such terms are used in
|
||||
48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Government
|
||||
only as a commercial end item. Consistent with 48 C.F.R.
|
||||
12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995),
|
||||
all U.S. Government End Users acquire the source code with only
|
||||
those rights set forth herein.
|
||||
|
||||
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.
|
||||
|
||||
@@ -28,7 +28,9 @@ nv_drv_la_LTLIBRARIES = nv_drv.la
|
||||
nv_drv_la_LDFLAGS = -module -avoid-version
|
||||
nv_drv_ladir = @moduledir@/drivers
|
||||
|
||||
nv_drv_la_SOURCES = \
|
||||
nv_drv_la_SOURCES = $(nv_sources) $(riva_sources) $(g80_sources)
|
||||
|
||||
nv_sources = \
|
||||
nv_const.h \
|
||||
nv_cursor.c \
|
||||
nv_dac.c \
|
||||
@@ -45,7 +47,9 @@ nv_drv_la_SOURCES = \
|
||||
nv_type.h \
|
||||
nvvga.h \
|
||||
nv_video.c \
|
||||
nv_xaa.c \
|
||||
nv_xaa.c
|
||||
|
||||
riva_sources = \
|
||||
riva_const.h \
|
||||
riva_cursor.c \
|
||||
riva_dac.c \
|
||||
@@ -61,3 +65,19 @@ nv_drv_la_SOURCES = \
|
||||
riva_tbl.h \
|
||||
riva_type.h \
|
||||
riva_xaa.c
|
||||
|
||||
if SUPPORT_G80
|
||||
g80_sources = \
|
||||
g80_cursor.c \
|
||||
g80_cursor.h \
|
||||
g80_ddc.c \
|
||||
g80_ddc.h \
|
||||
g80_display.c \
|
||||
g80_display.h \
|
||||
g80_dma.c \
|
||||
g80_dma.h \
|
||||
g80_driver.c \
|
||||
g80_type.h \
|
||||
g80_xaa.c \
|
||||
g80_xaa.h
|
||||
endif
|
||||
|
||||
185
src/g80_cursor.c
Normal file
185
src/g80_cursor.c
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include <cursorstr.h>
|
||||
|
||||
#include "g80_type.h"
|
||||
#include "g80_cursor.h"
|
||||
#include "g80_display.h"
|
||||
|
||||
#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)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
const int headOff = 0x1000*pNv->head;
|
||||
|
||||
x &= 0xffff;
|
||||
y &= 0xffff;
|
||||
pNv->reg[(0x00647084 + headOff)/4] = y << 16 | x;
|
||||
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)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
pNv->cursorVisible = FALSE;
|
||||
G80DispHideCursor(G80PTR(pScrn), TRUE);
|
||||
}
|
||||
|
||||
static void G80ShowCursor(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
pNv->cursorVisible = TRUE;
|
||||
G80DispShowCursor(G80PTR(pScrn), TRUE);
|
||||
}
|
||||
|
||||
static Bool G80UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef ARGB_CURSOR
|
||||
static Bool G80UseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
|
||||
{
|
||||
if((pCurs->bits->width <= 64) && (pCurs->bits->height <= 64))
|
||||
return TRUE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const int headOff = 0x10 * pNv->head;
|
||||
|
||||
if(!pNv->HWCursor) return;
|
||||
|
||||
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);
|
||||
}
|
||||
3
src/g80_cursor.h
Normal file
3
src/g80_cursor.h
Normal file
@@ -0,0 +1,3 @@
|
||||
Bool G80CursorInit(ScreenPtr);
|
||||
Bool G80CursorAcquire(G80Ptr);
|
||||
void G80CursorRelease(G80Ptr);
|
||||
232
src/g80_ddc.c
Normal file
232
src/g80_ddc.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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 <strings.h>
|
||||
#include <xf86DDC.h>
|
||||
|
||||
#include "g80_type.h"
|
||||
#include "g80_ddc.h"
|
||||
|
||||
static Bool G80ReadPortMapping(int scrnIndex, G80Ptr pNv)
|
||||
{
|
||||
unsigned char *table2;
|
||||
unsigned char headerSize, entries;
|
||||
int i;
|
||||
CARD16 a;
|
||||
CARD32 b;
|
||||
|
||||
/* Clear the i2c map to invalid */
|
||||
for(i = 0; i < 4; i++)
|
||||
pNv->i2cMap[i].dac = pNv->i2cMap[i].sor = -1;
|
||||
|
||||
if(*(CARD16*)pNv->table1 != 0xaa55) goto fail;
|
||||
|
||||
a = *(CARD16*)(pNv->table1 + 0x36);
|
||||
table2 = (unsigned char*)pNv->table1 + a;
|
||||
|
||||
if(table2[0] != 0x40) goto fail;
|
||||
|
||||
b = *(CARD32*)(table2 + 6);
|
||||
if(b != 0x4edcbdcb) goto fail;
|
||||
|
||||
headerSize = table2[1];
|
||||
entries = table2[2];
|
||||
|
||||
for(i = 0; i < entries; i++) {
|
||||
CARD32 type, port;
|
||||
ORNum or;
|
||||
|
||||
b = *(CARD32*)&table2[headerSize + 8*i];
|
||||
type = b & 0xf;
|
||||
port = (b >> 4) & 0xf;
|
||||
or = ffs((b >> 24) & 0xf) - 1;
|
||||
|
||||
if(type < 4 && port != 0xf) {
|
||||
switch(type) {
|
||||
case 0: /* CRT */
|
||||
case 1: /* TV */
|
||||
if(pNv->i2cMap[port].dac != -1) {
|
||||
xf86DrvMsg(scrnIndex, X_WARNING,
|
||||
"DDC routing table corrupt! DAC %i -> %i "
|
||||
"for port %i\n",
|
||||
or, pNv->i2cMap[port].dac, port);
|
||||
}
|
||||
pNv->i2cMap[port].dac = or;
|
||||
break;
|
||||
case 2: /* TMDS */
|
||||
case 3: /* LVDS */
|
||||
if(pNv->i2cMap[port].sor != -1)
|
||||
xf86DrvMsg(scrnIndex, X_WARNING,
|
||||
"DDC routing table corrupt! SOR %i -> %i "
|
||||
"for port %i\n",
|
||||
or, pNv->i2cMap[port].sor, port);
|
||||
pNv->i2cMap[port].sor = or;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xf86DrvMsg(scrnIndex, X_PROBED, "I2C map:\n");
|
||||
for(i = 0; i < 4; i++) {
|
||||
if(pNv->i2cMap[i].dac != -1)
|
||||
xf86DrvMsg(scrnIndex, X_PROBED, " Bus %i -> DAC%i\n", i, pNv->i2cMap[i].dac);
|
||||
if(pNv->i2cMap[i].sor != -1)
|
||||
xf86DrvMsg(scrnIndex, X_PROBED, " Bus %i -> SOR%i\n", i, pNv->i2cMap[i].sor);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
xf86DrvMsg(scrnIndex, X_ERROR, "Couldn't find the DDC routing table. "
|
||||
"Mode setting will probably fail!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void G80_I2CPutBits(I2CBusPtr b, int clock, int data)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
|
||||
const int off = b->DriverPrivate.val;
|
||||
|
||||
pNv->reg[(0x0000E138+off)/4] = 4 | clock | data << 1;
|
||||
}
|
||||
|
||||
static void G80_I2CGetBits(I2CBusPtr b, int *clock, int *data)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(xf86Screens[b->scrnIndex]);
|
||||
const int off = b->DriverPrivate.val;
|
||||
unsigned char val;
|
||||
|
||||
val = pNv->reg[(0x0000E138+off)/4];
|
||||
*clock = !!(val & 1);
|
||||
*data = !!(val & 2);
|
||||
}
|
||||
|
||||
static xf86MonPtr G80ProbeDDCBus(ScrnInfoPtr pScrn, int bus)
|
||||
{
|
||||
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->scrnIndex = pScrn->scrnIndex;
|
||||
i2c->I2CPutBits = G80_I2CPutBits;
|
||||
i2c->I2CGetBits = G80_I2CGetBits;
|
||||
i2c->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
|
||||
i2c->StartTimeout = 550;
|
||||
i2c->BitTimeout = 40;
|
||||
i2c->ByteTimeout = 40;
|
||||
i2c->AcknTimeout = 40;
|
||||
i2c->DriverPrivate.val = off;
|
||||
|
||||
if(!xf86I2CBusInit(i2c)) goto done;
|
||||
|
||||
pNv->reg[(0x0000E138+off)/4] = 7;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||||
"Probing for EDID on I2C bus %i...\n", bus);
|
||||
monInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, i2c);
|
||||
|
||||
pNv->reg[(0x0000E138+off)/4] = 3;
|
||||
|
||||
if(monInfo) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||||
"DDC detected a %s:\n", monInfo->features.input_type ?
|
||||
"DFP" : "CRT");
|
||||
xf86PrintEDID(monInfo);
|
||||
} else {
|
||||
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.
|
||||
*/
|
||||
Bool G80ProbeDDC(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
xf86MonPtr monInfo;
|
||||
int port;
|
||||
Bool flatPanel;
|
||||
|
||||
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. */
|
||||
continue;
|
||||
|
||||
monInfo = G80ProbeDDCBus(pScrn, port);
|
||||
if(!monInfo)
|
||||
/* No EDID on this port. */
|
||||
continue;
|
||||
|
||||
flatPanel = (monInfo->features.input_type == 1);
|
||||
|
||||
if(flatPanel) {
|
||||
if(pNv->i2cMap[port].sor == -1) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Saw a flat panel EDID "
|
||||
"on I2C port %i but no SOR outputs were registered for "
|
||||
"that port.\n", port);
|
||||
continue;
|
||||
}
|
||||
pNv->orType = SOR;
|
||||
pNv->or = pNv->i2cMap[port].sor;
|
||||
} else {
|
||||
if(pNv->i2cMap[port].dac == -1) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Saw a flat panel EDID "
|
||||
"on I2C port %i but no DAC outputs were registered for "
|
||||
"that port.\n", port);
|
||||
continue;
|
||||
}
|
||||
pNv->orType = DAC;
|
||||
pNv->or = pNv->i2cMap[port].dac;
|
||||
}
|
||||
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||||
"Found a %s on I2C port %i, assigning %s%i\n",
|
||||
flatPanel ? "flat panel" : "CRT",
|
||||
port, flatPanel ? "SOR" : "DAC", pNv->or);
|
||||
|
||||
pScrn->monitor->DDC = monInfo;
|
||||
xf86SetDDCproperties(pScrn, monInfo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
1
src/g80_ddc.h
Normal file
1
src/g80_ddc.h
Normal file
@@ -0,0 +1 @@
|
||||
Bool G80ProbeDDC(ScrnInfoPtr pScrn);
|
||||
515
src/g80_display.c
Normal file
515
src/g80_display.c
Normal file
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* 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 <float.h>
|
||||
#include <math.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "g80_type.h"
|
||||
#include "g80_display.h"
|
||||
|
||||
#define DPMS_SERVER
|
||||
#include <X11/extensions/dpms.h>
|
||||
|
||||
/*
|
||||
* PLL calculation. pclk is in kHz.
|
||||
*/
|
||||
static void
|
||||
G80CalcPLL(float pclk, int *pNA, int *pMA, int *pNB, int *pMB, int *pP)
|
||||
{
|
||||
const float refclk = 27000.0f;
|
||||
const float minVcoA = 100000;
|
||||
const float maxVcoA = 400000;
|
||||
const float minVcoB = 600000;
|
||||
float maxVcoB = 1400000;
|
||||
const float minUA = 2000;
|
||||
const float maxUA = 400000;
|
||||
const float minUB = 50000;
|
||||
const float maxUB = 200000;
|
||||
const int minNA = 1, maxNA = 255;
|
||||
const int minNB = 1, maxNB = 31;
|
||||
const int minMA = 1, maxMA = 255;
|
||||
const int minMB = 1, maxMB = 31;
|
||||
const int minP = 0, maxP = 6;
|
||||
int lowP, highP;
|
||||
float vcoB;
|
||||
|
||||
int na, ma, nb, mb, p;
|
||||
float bestError = FLT_MAX;
|
||||
|
||||
*pNA = *pMA = *pNB = *pMB = *pP = 0;
|
||||
|
||||
if(maxVcoB < pclk + pclk / 200)
|
||||
maxVcoB = pclk + pclk / 200;
|
||||
if(minVcoB / (1 << maxP) > pclk)
|
||||
pclk = minVcoB / (1 << maxP);
|
||||
|
||||
vcoB = maxVcoB - maxVcoB / 200;
|
||||
lowP = minP;
|
||||
vcoB /= 1 << (lowP + 1);
|
||||
|
||||
while(pclk <= vcoB && lowP < maxP)
|
||||
{
|
||||
vcoB /= 2;
|
||||
lowP++;
|
||||
}
|
||||
|
||||
vcoB = maxVcoB + maxVcoB / 200;
|
||||
highP = lowP;
|
||||
vcoB /= 1 << (highP + 1);
|
||||
|
||||
while(pclk <= vcoB && highP < maxP)
|
||||
{
|
||||
vcoB /= 2;
|
||||
highP++;
|
||||
}
|
||||
|
||||
for(p = lowP; p <= highP; p++)
|
||||
{
|
||||
for(ma = minMA; ma <= maxMA; ma++)
|
||||
{
|
||||
if(refclk / ma < minUA)
|
||||
break;
|
||||
else if(refclk / ma > maxUA)
|
||||
continue;
|
||||
|
||||
for(na = minNA; na <= maxNA; na++)
|
||||
{
|
||||
if(refclk * na / ma < minVcoA || refclk * na / ma > maxVcoA)
|
||||
continue;
|
||||
|
||||
for(mb = minMB; mb <= maxMB; mb++)
|
||||
{
|
||||
if(refclk * na / ma / mb < minUB)
|
||||
break;
|
||||
else if(refclk * na / ma / mb > maxUB)
|
||||
continue;
|
||||
|
||||
nb = rint(pclk * (1 << p) * (ma / (float)na) * mb / refclk);
|
||||
|
||||
if(nb > maxNB)
|
||||
break;
|
||||
else if(nb < minNB)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
float freq = refclk * (na / (float)ma) * (nb / (float)mb) / (1 << p);
|
||||
float error = fabsf(pclk - freq);
|
||||
if(error < bestError) {
|
||||
*pNA = na;
|
||||
*pMA = ma;
|
||||
*pNB = nb;
|
||||
*pMB = mb;
|
||||
*pP = p;
|
||||
bestError = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
G80DispCommand(G80Ptr pNv, CARD32 addr, CARD32 data)
|
||||
{
|
||||
pNv->reg[0x00610304/4] = data;
|
||||
pNv->reg[0x00610300/4] = addr | 0x80010001;
|
||||
|
||||
while(pNv->reg[0x00610300/4] & 0x80000000) {
|
||||
const int super = ffs((pNv->reg[0x00610024/4] >> 4) & 7);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
pNv->reg[0x00610024/4] = 8 << super;
|
||||
pNv->reg[0x00610030/4] = 0x80000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
#define C(mthd, data) G80DispCommand(pNv, (mthd), (data))
|
||||
|
||||
/*
|
||||
* 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++) {
|
||||
const int dacOff = 2048 * or;
|
||||
CARD32 load, tmp;
|
||||
|
||||
xf86DrvMsg(scrnIndex, X_PROBED, "Trying load detection on DAC%i ... ", or);
|
||||
|
||||
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;
|
||||
if((load & 0x38000000) == 0x38000000) {
|
||||
xf86ErrorF("found one!\n");
|
||||
pNv->or = or;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
xf86ErrorF("nothing.\n");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Bool
|
||||
G80DispInit(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
pNv->reg[0x00610184/4] = pNv->reg[0x00614004/4];
|
||||
pNv->reg[0x00610190/4] = pNv->reg[0x00616100/4];
|
||||
pNv->reg[0x006101a0/4] = pNv->reg[0x00616900/4];
|
||||
pNv->reg[0x00610194/4] = pNv->reg[0x00616104/4];
|
||||
pNv->reg[0x006101a4/4] = pNv->reg[0x00616904/4];
|
||||
pNv->reg[0x00610198/4] = pNv->reg[0x00616108/4];
|
||||
pNv->reg[0x006101a8/4] = pNv->reg[0x00616908/4];
|
||||
pNv->reg[0x0061019C/4] = pNv->reg[0x0061610C/4];
|
||||
pNv->reg[0x006101ac/4] = pNv->reg[0x0061690c/4];
|
||||
pNv->reg[0x006101D0/4] = pNv->reg[0x0061A000/4];
|
||||
pNv->reg[0x006101D4/4] = pNv->reg[0x0061A800/4];
|
||||
pNv->reg[0x006101D8/4] = pNv->reg[0x0061B000/4];
|
||||
pNv->reg[0x006101E0/4] = pNv->reg[0x0061C000/4];
|
||||
pNv->reg[0x006101E4/4] = pNv->reg[0x0061C800/4];
|
||||
pNv->reg[0x0061c00c/4] = 0x03010700;
|
||||
pNv->reg[0x0061c010/4] = 0x0000152f;
|
||||
pNv->reg[0x0061c014/4] = 0x00000000;
|
||||
pNv->reg[0x0061c018/4] = 0x00245af8;
|
||||
pNv->reg[0x0061c80c/4] = 0x03010700;
|
||||
pNv->reg[0x0061c810/4] = 0x0000152f;
|
||||
pNv->reg[0x0061c814/4] = 0x00000000;
|
||||
pNv->reg[0x0061c818/4] = 0x00245af8;
|
||||
pNv->reg[0x0061A004/4] = 0x80550000;
|
||||
pNv->reg[0x0061A010/4] = 0x00000001;
|
||||
pNv->reg[0x0061A804/4] = 0x80550000;
|
||||
pNv->reg[0x0061A810/4] = 0x00000001;
|
||||
pNv->reg[0x0061B004/4] = 0x80550000;
|
||||
pNv->reg[0x0061B010/4] = 0x00000001;
|
||||
|
||||
if(pNv->reg[0x00610024/4] & 0x100) {
|
||||
pNv->reg[0x00610024/4] = 0x100;
|
||||
pNv->reg[0x006194E8/4] &= ~1;
|
||||
while(pNv->reg[0x006194E8/4] & 2);
|
||||
}
|
||||
|
||||
pNv->reg[0x00610200/4] = 0x2b00;
|
||||
while((pNv->reg[0x00610200/4] & 0x1e0000) != 0);
|
||||
pNv->reg[0x00610300/4] = 1;
|
||||
pNv->reg[0x00610200/4] = 0x1000b03;
|
||||
while(!(pNv->reg[0x00610200/4] & 0x40000000));
|
||||
|
||||
C(0x00000084, 0);
|
||||
C(0x00000088, 0);
|
||||
C(0x00000874, 0);
|
||||
C(0x00000800, 0);
|
||||
C(0x00000810, 0);
|
||||
C(0x0000082C, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
G80DispShutdown(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
CARD32 mask;
|
||||
|
||||
G80DispBlankScreen(pScrn, TRUE);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
const int HDisplay = mode->HDisplay, VDisplay = mode->VDisplay;
|
||||
const int headOff = 0x400 * pNv->head;
|
||||
int interlaceDiv, fudge;
|
||||
|
||||
if(pNv->BackendMode)
|
||||
mode = pNv->BackendMode;
|
||||
|
||||
pNv->pclk = mode->SynthClock;
|
||||
|
||||
/* 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(0x00000808 + headOff, (mode->Flags & V_INTERLACE) ? 2 : 0);
|
||||
C(0x00000810 + headOff, 0);
|
||||
C(0x0000082C + headOff, 0);
|
||||
C(0x00000814 + headOff, mode->CrtcVTotal << 16 | mode->CrtcHTotal);
|
||||
C(0x00000818 + headOff,
|
||||
((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) / interlaceDiv - 1) << 16 |
|
||||
(mode->CrtcHSyncEnd - mode->CrtcHSyncStart - 1));
|
||||
C(0x0000081C + headOff,
|
||||
((mode->CrtcVBlankEnd - mode->CrtcVSyncStart) / interlaceDiv - fudge) << 16 |
|
||||
(mode->CrtcHBlankEnd - mode->CrtcHSyncStart - 1));
|
||||
C(0x00000820 + headOff,
|
||||
((mode->CrtcVTotal - mode->CrtcVSyncStart + mode->CrtcVBlankStart) / interlaceDiv - fudge) << 16 |
|
||||
(mode->CrtcHTotal - mode->CrtcHSyncStart + mode->CrtcHBlankStart - 1));
|
||||
if(mode->Flags & V_INTERLACE) {
|
||||
C(0x00000824 + headOff,
|
||||
((mode->CrtcVTotal + mode->CrtcVBlankEnd - mode->CrtcVSyncStart) / 2 - 2) << 16 |
|
||||
((2*mode->CrtcVTotal - mode->CrtcVSyncStart + mode->CrtcVBlankStart) / 2 - 2));
|
||||
}
|
||||
C(0x00000868 + headOff, pScrn->virtualY << 16 | pScrn->virtualX);
|
||||
C(0x0000086C + headOff, pScrn->displayWidth * (pScrn->bitsPerPixel / 8) | 0x100000);
|
||||
switch(pScrn->depth) {
|
||||
case 8: C(0x00000870 + headOff, 0x1E00); break;
|
||||
case 15: C(0x00000870 + headOff, 0xE900); break;
|
||||
case 16: C(0x00000870 + headOff, 0xE800); break;
|
||||
case 24: C(0x00000870 + headOff, 0xCF00); break;
|
||||
}
|
||||
C(0x000008A0 + headOff, 0);
|
||||
if((mode->Flags & V_DBLSCAN) || (mode->Flags & V_INTERLACE) ||
|
||||
mode->CrtcHDisplay != HDisplay || mode->CrtcVDisplay != VDisplay) {
|
||||
C(0x000008A4 + headOff, 9);
|
||||
} else {
|
||||
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(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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
const int headOff = 0x400 * pNv->head;
|
||||
|
||||
if(blank) {
|
||||
G80DispHideCursor(pNv, FALSE);
|
||||
|
||||
C(0x00000840 + headOff, 0);
|
||||
C(0x00000844 + headOff, 0);
|
||||
if(pNv->architecture != 0x50)
|
||||
C(0x0000085C + headOff, 0);
|
||||
C(0x00000874 + headOff, 0);
|
||||
if(pNv->architecture != 0x50)
|
||||
C(0x0000089C + headOff, 0);
|
||||
} else {
|
||||
C(0x00000860 + headOff, 0);
|
||||
C(0x00000864 + headOff, 0);
|
||||
pNv->reg[0x00610380/4] = 0;
|
||||
pNv->reg[0x00610384/4] = pNv->RamAmountKBytes * 1024 - 1;
|
||||
pNv->reg[0x00610388/4] = 0x150000;
|
||||
pNv->reg[0x0061038C/4] = 0;
|
||||
C(0x00000884 + headOff, (pNv->videoRam << 2) - 0x40);
|
||||
if(pNv->architecture != 0x50)
|
||||
C(0x0000089C + headOff, 1);
|
||||
if(pNv->cursorVisible)
|
||||
G80DispShowCursor(pNv, 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
const int headOff = 0x400 * pNv->head;
|
||||
|
||||
C(0x00000880 + headOff, 0x85000000);
|
||||
if(update) C(0x00000080, 0);
|
||||
}
|
||||
|
||||
void G80DispHideCursor(G80Ptr pNv, Bool update)
|
||||
{
|
||||
const int headOff = 0x400 * pNv->head;
|
||||
|
||||
C(0x00000880 + headOff, 0x5000000);
|
||||
if(update) C(0x00000080, 0);
|
||||
}
|
||||
9
src/g80_display.h
Normal file
9
src/g80_display.h
Normal file
@@ -0,0 +1,9 @@
|
||||
Bool G80LoadDetect(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);
|
||||
65
src/g80_dma.c
Normal file
65
src/g80_dma.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 "g80_type.h"
|
||||
#include "g80_dma.h"
|
||||
|
||||
void G80DmaKickoff(G80Ptr pNv)
|
||||
{
|
||||
if(pNv->dmaCurrent != pNv->dmaPut) {
|
||||
pNv->dmaPut = pNv->dmaCurrent;
|
||||
pNv->reg[0x00c02040/4] = pNv->dmaPut << 2;
|
||||
}
|
||||
}
|
||||
|
||||
void G80DmaWait(G80Ptr pNv, int size)
|
||||
{
|
||||
CARD32 dmaGet;
|
||||
|
||||
size++;
|
||||
|
||||
while(pNv->dmaFree < size) {
|
||||
dmaGet = pNv->reg[0x00c02044/4] >> 2;
|
||||
|
||||
if(pNv->dmaPut >= dmaGet) {
|
||||
pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
|
||||
if(pNv->dmaFree < size) {
|
||||
G80DmaNext(pNv, 0x20000000);
|
||||
if(dmaGet <= SKIPS) {
|
||||
if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
|
||||
pNv->reg[0x00c02040/4] = (SKIPS + 1) << 2;
|
||||
do { dmaGet = pNv->reg[0x00c02044/4] >> 2; }
|
||||
while(dmaGet <= SKIPS);
|
||||
}
|
||||
pNv->reg[0x00c02040/4] = SKIPS << 2;
|
||||
pNv->dmaCurrent = pNv->dmaPut = SKIPS;
|
||||
pNv->dmaFree = dmaGet - (SKIPS + 1);
|
||||
}
|
||||
} else
|
||||
pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
|
||||
}
|
||||
}
|
||||
14
src/g80_dma.h
Normal file
14
src/g80_dma.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#define SKIPS 8
|
||||
|
||||
#define G80DmaNext(pNv, data) \
|
||||
(pNv)->dmaBase[(pNv)->dmaCurrent++] = (data)
|
||||
|
||||
#define G80DmaStart(pNv, tag, size) { \
|
||||
if((pNv)->dmaFree <= (size)) \
|
||||
G80DmaWait(pNv, size); \
|
||||
G80DmaNext(pNv, ((size) << 18) | (tag)); \
|
||||
(pNv)->dmaFree -= ((size) + 1); \
|
||||
}
|
||||
|
||||
void G80DmaKickoff(G80Ptr pNv);
|
||||
void G80DmaWait(G80Ptr pNv, int size);
|
||||
916
src/g80_driver.c
Normal file
916
src/g80_driver.c
Normal file
@@ -0,0 +1,916 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include <xf86_OSproc.h>
|
||||
#include <xf86Resources.h>
|
||||
#include <mipointer.h>
|
||||
#include <mibstore.h>
|
||||
#include <micmap.h>
|
||||
#include <xf86cmap.h>
|
||||
#include <fb.h>
|
||||
#define DPMS_SERVER
|
||||
#include <X11/extensions/dpms.h>
|
||||
|
||||
#include "nv_const.h"
|
||||
#include "g80_type.h"
|
||||
#include "g80_cursor.h"
|
||||
#include "g80_display.h"
|
||||
#include "g80_ddc.h"
|
||||
#include "g80_dma.h"
|
||||
#include "g80_xaa.h"
|
||||
|
||||
#define G80_REG_SIZE (1024 * 1024 * 16)
|
||||
#define G80_RESERVED_VIDMEM 0xd000
|
||||
|
||||
static const char *fbSymbols[] = {
|
||||
"fbPictureInit",
|
||||
"fbScreenInit",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *xaaSymbols[] = {
|
||||
"XAACopyROP",
|
||||
"XAACreateInfoRec",
|
||||
"XAADestroyInfoRec",
|
||||
"XAAFallbackOps",
|
||||
"XAAInit",
|
||||
"XAAPatternROP",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *i2cSymbols[] = {
|
||||
"xf86CreateI2CBusRec",
|
||||
"xf86I2CBusInit",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *ramdacSymbols[] = {
|
||||
"xf86CreateCursorInfoRec",
|
||||
"xf86DestroyCursorInfoRec",
|
||||
"xf86InitCursor",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *ddcSymbols[] = {
|
||||
"xf86PrintEDID",
|
||||
"xf86DoEDID_DDC2",
|
||||
"xf86SetDDCproperties",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *int10Symbols[] = {
|
||||
"xf86FreeInt10",
|
||||
"xf86InitInt10",
|
||||
"xf86ExecX86int10",
|
||||
NULL
|
||||
};
|
||||
|
||||
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 }
|
||||
};
|
||||
|
||||
static Bool
|
||||
G80GetRec(ScrnInfoPtr pScrn)
|
||||
{
|
||||
if(pScrn->driverPrivate == NULL)
|
||||
pScrn->driverPrivate = xcalloc(sizeof(G80Rec), 1);
|
||||
|
||||
return (pScrn->driverPrivate != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
G80FreeRec(ScrnInfoPtr pScrn)
|
||||
{
|
||||
xfree(pScrn->driverPrivate);
|
||||
pScrn->driverPrivate = NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if(flags & PROBE_DETECT) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"G80 PROBE_DETECT unimplemented\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check the number of entities, and fail if it isn't one. */
|
||||
if(pScrn->numEntities != 1)
|
||||
return FALSE;
|
||||
|
||||
/* Allocate the NVRec driverPrivate */
|
||||
if(!G80GetRec(pScrn)) {
|
||||
return FALSE;
|
||||
}
|
||||
pNv = G80PTR(pScrn);
|
||||
|
||||
/* Get the entity, and make sure it is PCI. */
|
||||
pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
|
||||
if(pEnt->location.type != BUS_PCI) goto fail;
|
||||
pPci = xf86GetPciInfoForEntity(pEnt->index);
|
||||
pcitag = pciTag(pPci->bus, pPci->device, pPci->func);
|
||||
primary = xf86IsPrimaryPci(pPci);
|
||||
|
||||
/* The ROM size sometimes isn't read correctly, so fix it up here. */
|
||||
if(pPci->biosSize == 0)
|
||||
/* The BIOS is 64k */
|
||||
pPci->biosSize = 16;
|
||||
|
||||
pNv->int10 = NULL;
|
||||
pNv->int10Mode = 0;
|
||||
if(xf86LoadSubModule(pScrn, "int10")) {
|
||||
xf86LoaderReqSymLists(int10Symbols, NULL);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
|
||||
pNv->int10 = xf86InitInt10(pEnt->index);
|
||||
}
|
||||
|
||||
if(!pNv->int10) {
|
||||
if(primary) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
|
||||
"Failed to initialize the int10 module; the console "
|
||||
"will not be restored.\n");
|
||||
} else {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Failed to initialize the int10 module; this screen "
|
||||
"will not be initialized.\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if(primary && pNv->int10) {
|
||||
const xf86Int10InfoPtr int10 = pNv->int10;
|
||||
|
||||
/* Get the current video mode */
|
||||
int10->num = 0x10;
|
||||
int10->ax = 0x4f03;
|
||||
int10->bx = int10->cx = int10->dx = 0;
|
||||
xf86ExecX86int10(int10);
|
||||
pNv->int10Mode = int10->bx & 0x3fff;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Console is VGA mode 0x%x\n",
|
||||
pNv->int10Mode);
|
||||
}
|
||||
|
||||
/* Disable VGA access */
|
||||
xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr);
|
||||
xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr);
|
||||
|
||||
pScrn->monitor = pScrn->confScreen->monitor;
|
||||
|
||||
if(!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) goto fail;
|
||||
switch (pScrn->depth) {
|
||||
case 8:
|
||||
case 15:
|
||||
case 16:
|
||||
case 24:
|
||||
/* OK */
|
||||
break;
|
||||
default:
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Given depth (%d) is not supported by this driver\n",
|
||||
pScrn->depth);
|
||||
goto fail;
|
||||
}
|
||||
xf86PrintDepthBpp(pScrn);
|
||||
|
||||
if(!xf86SetWeight(pScrn, zeros, zeros)) goto fail;
|
||||
if(!xf86SetDefaultVisual(pScrn, -1)) goto fail;
|
||||
|
||||
/* We use a programmable clock */
|
||||
pScrn->progClock = TRUE;
|
||||
|
||||
/* Process options */
|
||||
xf86CollectOptions(pScrn, NULL);
|
||||
if(!(pNv->Options = xalloc(sizeof(G80Options)))) goto fail;
|
||||
memcpy(pNv->Options, G80Options, sizeof(G80Options));
|
||||
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNv->Options);
|
||||
|
||||
from = X_DEFAULT;
|
||||
pNv->HWCursor = TRUE;
|
||||
if(xf86GetOptValBool(pNv->Options, OPTION_HW_CURSOR, &pNv->HWCursor))
|
||||
from = X_CONFIG;
|
||||
xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
|
||||
pNv->HWCursor ? "hardware" : "software");
|
||||
if(xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) {
|
||||
pNv->NoAccel = TRUE;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
|
||||
}
|
||||
|
||||
/* Set the bits per RGB for 8bpp mode */
|
||||
if(pScrn->depth == 8)
|
||||
pScrn->rgbBits = 8;
|
||||
|
||||
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]);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lx\n",
|
||||
pPci->memBase[1]);
|
||||
pScrn->memPhysBase = pPci->memBase[1];
|
||||
pScrn->fbOffset = 0;
|
||||
|
||||
pNv->reg = xf86MapPciMem(pScrn->scrnIndex,
|
||||
VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
|
||||
pcitag, pPci->memBase[0], G80_REG_SIZE);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MMIO registers mapped at %p\n",
|
||||
(void*)pNv->reg);
|
||||
|
||||
if(xf86RegisterResources(pEnt->index, NULL, ResExclusive)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86RegisterResources() found "
|
||||
"resource conflicts\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pNv->architecture = pNv->reg[0] >> 20 & 0x1ff;
|
||||
pNv->RamAmountKBytes = pNv->RamAmountKBytes = (pNv->reg[0x0010020C/4] & 0xFFF00000) >> 10;
|
||||
pNv->videoRam = pNv->RamAmountKBytes;
|
||||
/* Limit videoRam to the max BAR1 size of 256MB */
|
||||
if(pNv->videoRam <= 1024) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to determine the amount of "
|
||||
"available video memory\n");
|
||||
goto fail;
|
||||
}
|
||||
pNv->videoRam -= 1024;
|
||||
if(pNv->videoRam > 256 * 1024)
|
||||
pNv->videoRam = 256 * 1024;
|
||||
pScrn->videoRam = pNv->videoRam;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Mapping %.1f of %.1f MB of video RAM\n",
|
||||
pScrn->videoRam / 1024.0, pNv->RamAmountKBytes / 1024.0);
|
||||
pNv->mem = xf86MapPciMem(pScrn->scrnIndex,
|
||||
VIDMEM_MMIO | VIDMEM_READSIDEEFFECT,
|
||||
pcitag, pPci->memBase[1], pScrn->videoRam * 1024);
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Linear framebuffer mapped at %p\n",
|
||||
(void*)pNv->mem);
|
||||
|
||||
pNv->table1 = (unsigned const char*)&pNv->reg[0x00800000/4];
|
||||
tmp = pNv->reg[0x00619F04/4] >> 8;
|
||||
if(tmp)
|
||||
pNv->table1 -= ((pNv->RamAmountKBytes << 10) - (tmp << 16));
|
||||
else
|
||||
pNv->table1 -= 0x10000;
|
||||
|
||||
/* Probe DDC */
|
||||
/* If no DDC info found, try DAC load detection */
|
||||
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");
|
||||
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");
|
||||
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);
|
||||
|
||||
if(!pNv->NoAccel) {
|
||||
if(!xf86LoadSubModule(pScrn, "xaa")) goto fail;
|
||||
xf86LoaderReqSymLists(xaaSymbols, NULL);
|
||||
}
|
||||
|
||||
/* Load ramdac if needed */
|
||||
if(pNv->HWCursor) {
|
||||
if(!xf86LoadSubModule(pScrn, "ramdac")) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to load ramdac. "
|
||||
"Falling back to software cursor.\n");
|
||||
pNv->HWCursor = FALSE;
|
||||
} else {
|
||||
xf86LoaderReqSymLists(ramdacSymbols, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
if(pNv->int10) xf86FreeInt10(pNv->int10);
|
||||
G80FreeRec(pScrn);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the display and set the current mode.
|
||||
*/
|
||||
static Bool
|
||||
AcquireDisplay(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
if(!G80DispInit(pScrn))
|
||||
return FALSE;
|
||||
if(!G80CursorAcquire(pNv))
|
||||
return FALSE;
|
||||
if(!G80DispSetMode(pScrn, pScrn->currentMode))
|
||||
return FALSE;
|
||||
G80DispDPMSSet(pScrn, DPMSModeOn, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tear down the display and restore the console mode.
|
||||
*/
|
||||
static Bool
|
||||
ReleaseDisplay(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
G80CursorRelease(pNv);
|
||||
G80DispShutdown(pScrn);
|
||||
|
||||
if(pNv->int10 && pNv->int10Mode) {
|
||||
xf86Int10InfoPtr int10 = pNv->int10;
|
||||
|
||||
/* Use int10 to restore the console mode */
|
||||
int10->num = 0x10;
|
||||
int10->ax = 0x4f02;
|
||||
int10->bx = pNv->int10Mode | 0x8000;
|
||||
int10->cx = int10->dx = 0;
|
||||
xf86ExecX86int10(int10);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
G80CloseScreen(int scrnIndex, ScreenPtr pScreen)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
if(pScrn->vtSema)
|
||||
ReleaseDisplay(pScrn);
|
||||
|
||||
if(pNv->xaa)
|
||||
XAADestroyInfoRec(pNv->xaa);
|
||||
if(pNv->HWCursor)
|
||||
xf86DestroyCursorInfoRec(pNv->CursorInfo);
|
||||
|
||||
if(xf86ServerIsExiting()) {
|
||||
if(pNv->int10) xf86FreeInt10(pNv->int10);
|
||||
xf86UnMapVidMem(pScrn->scrnIndex, pNv->mem, pNv->videoRam * 1024);
|
||||
xf86UnMapVidMem(pScrn->scrnIndex, (void*)pNv->reg, G80_REG_SIZE);
|
||||
pNv->reg = NULL;
|
||||
pNv->mem = NULL;
|
||||
}
|
||||
|
||||
pScrn->vtSema = FALSE;
|
||||
pScreen->CloseScreen = pNv->CloseScreen;
|
||||
pScreen->BlockHandler = pNv->BlockHandler;
|
||||
return (*pScreen->CloseScreen)(scrnIndex, pScreen);
|
||||
}
|
||||
|
||||
static void
|
||||
G80BlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
|
||||
{
|
||||
ScreenPtr pScreen = screenInfo.screens[i];
|
||||
ScrnInfoPtr pScrnInfo = xf86Screens[i];
|
||||
G80Ptr pNv = G80PTR(pScrnInfo);
|
||||
|
||||
if(pNv->DMAKickoffCallback)
|
||||
(*pNv->DMAKickoffCallback)(pScrnInfo);
|
||||
|
||||
pScreen->BlockHandler = pNv->BlockHandler;
|
||||
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
|
||||
pScreen->BlockHandler = G80BlockHandler;
|
||||
}
|
||||
|
||||
static Bool
|
||||
G80SaveScreen(ScreenPtr pScreen, int mode)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
||||
|
||||
if(!pScrn->vtSema) return FALSE;
|
||||
|
||||
G80DispBlankScreen(pScrn, !xf86IsUnblank(mode));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
G80InitHW(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
CARD32 bar0_pramin = 0;
|
||||
const int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
|
||||
volatile CARD32 *p;
|
||||
|
||||
/* Clear registers */
|
||||
for(p = &pNv->reg[0x00700000/4]; p < (const CARD32*)pNv->table1; p++)
|
||||
*p = 0;
|
||||
|
||||
bar0_pramin = pNv->reg[0x00001700/4] << 16;
|
||||
|
||||
pNv->reg[0x00000200/4] = 0xffff00ff;
|
||||
pNv->reg[0x00000200/4] = 0xffffffff;
|
||||
pNv->reg[0x00002100/4] = 0xffffffff;
|
||||
pNv->reg[0x0000250c/4] = 0x6f3cfc34;
|
||||
pNv->reg[0x00400804/4] = 0xc0000000;
|
||||
pNv->reg[0x00406800/4] = 0xc0000000;
|
||||
pNv->reg[0x00400c04/4] = 0xc0000000;
|
||||
pNv->reg[0x00401800/4] = 0xc0000000;
|
||||
pNv->reg[0x00405018/4] = 0xc0000000;
|
||||
pNv->reg[0x00402000/4] = 0xc0000000;
|
||||
pNv->reg[0x00400108/4] = 0xffffffff;
|
||||
pNv->reg[0x00400100/4] = 0xffffffff;
|
||||
|
||||
if(pNv->architecture != 0x50) {
|
||||
pNv->reg[0x00700000/4] = 0x00000001;
|
||||
pNv->reg[0x00700004/4] = bar0_pramin + 0x00200;
|
||||
pNv->reg[0x00700020/4] = 0x00190002;
|
||||
pNv->reg[0x00700024/4] = bar0_pramin + 0x7ffff;
|
||||
pNv->reg[0x00700028/4] = bar0_pramin + 0x20000;
|
||||
pNv->reg[0x00700034/4] = 0x00010000;
|
||||
} else {
|
||||
pNv->reg[0x00700200/4] = 0x00190002;
|
||||
pNv->reg[0x00700204/4] = bar0_pramin + 0x7ffff;
|
||||
pNv->reg[0x00700208/4] = bar0_pramin + 0x20000;
|
||||
pNv->reg[0x00700214/4] = 0x00010000;
|
||||
}
|
||||
|
||||
pNv->reg[0x00710004/4] = 0x00100642;
|
||||
pNv->reg[0x00710008/4] = 0x80000011;
|
||||
pNv->reg[0x0071000c/4] = 0x00000644;
|
||||
pNv->reg[0x00710010/4] = 0x80000012;
|
||||
pNv->reg[0x00710014/4] = 0x00100646;
|
||||
pNv->reg[0x00710018/4] = 0x80000013;
|
||||
pNv->reg[0x0071001c/4] = 0x00100648;
|
||||
pNv->reg[0x00710020/4] = 0x80000014;
|
||||
pNv->reg[0x00710024/4] = 0x0000064a;
|
||||
pNv->reg[0x00706420/4] = 0x00190030;
|
||||
pNv->reg[0x00706434/4] = 0x00010000;
|
||||
pNv->reg[0x00706440/4] = 0x0019003d;
|
||||
pNv->reg[0x00706444/4] = (pNv->videoRam << 10) - 0x4001;
|
||||
pNv->reg[0x00706448/4] = (pNv->videoRam << 10) - G80_RESERVED_VIDMEM;
|
||||
pNv->reg[0x00706454/4] = 0x00010000;
|
||||
pNv->reg[0x00706460/4] = 0x0000502d;
|
||||
pNv->reg[0x00706474/4] = 0x00010000;
|
||||
pNv->reg[0x00706480/4] = 0x0019003d;
|
||||
pNv->reg[0x00706484/4] = (pNv->videoRam << 10) - G80_RESERVED_VIDMEM;
|
||||
pNv->reg[0x00706494/4] = 0x00010000;
|
||||
pNv->reg[0x007064a0/4] = 0x0019003d;
|
||||
pNv->reg[0x007064a4/4] = bar0_pramin + 0x1100f;
|
||||
pNv->reg[0x007064a8/4] = bar0_pramin + 0x11000;
|
||||
pNv->reg[0x007064b4/4] = 0x00010000;
|
||||
|
||||
if(pNv->architecture != 0x50) {
|
||||
pNv->reg[0x00002604/4] = 0x80000002 | (bar0_pramin >> 8);
|
||||
} else {
|
||||
pNv->reg[0x00002604/4] = 0x80000000 | (bar0_pramin >> 12);
|
||||
}
|
||||
|
||||
pNv->reg[0x00003224/4] = 0x000f0078;
|
||||
pNv->reg[0x0000322c/4] = 0x00000644;
|
||||
pNv->reg[0x00003234/4] = G80_RESERVED_VIDMEM - 0x5001;
|
||||
pNv->reg[0x00003254/4] = 0x00000001;
|
||||
pNv->reg[0x00002210/4] = 0x1c001000;
|
||||
|
||||
if(pNv->architecture != 0x50) {
|
||||
pNv->reg[0x0000340c/4] = (bar0_pramin + 0x1000) >> 10;
|
||||
pNv->reg[0x00003410/4] = (bar0_pramin >> 12);
|
||||
}
|
||||
|
||||
pNv->reg[0x00400824/4] = 0x00004000;
|
||||
pNv->reg[0x00400784/4] = 0x80000000 | (bar0_pramin >> 12);
|
||||
pNv->reg[0x00400320/4] = 0x00000004;
|
||||
pNv->reg[0x0040032C/4] = 0x80000000 | (bar0_pramin >> 12);
|
||||
pNv->reg[0x00400500/4] = 0x00010001;
|
||||
pNv->reg[0x00003250/4] = 0x00000001;
|
||||
pNv->reg[0x00003200/4] = 0x00000001;
|
||||
pNv->reg[0x00003220/4] = 0x00001001;
|
||||
pNv->reg[0x00003204/4] = 0x00010001;
|
||||
|
||||
pNv->dmaBase = (CARD32*)(pNv->mem + (pNv->videoRam << 10) -
|
||||
G80_RESERVED_VIDMEM);
|
||||
memset(pNv->dmaBase, 0, SKIPS*4);
|
||||
|
||||
pNv->dmaPut = 0;
|
||||
pNv->dmaCurrent = SKIPS;
|
||||
pNv->dmaMax = (G80_RESERVED_VIDMEM - 0x5000) / 4 - 2;
|
||||
pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
|
||||
|
||||
G80DmaStart(pNv, 0, 1);
|
||||
G80DmaNext (pNv, 0x80000012);
|
||||
G80DmaStart(pNv, 0x180, 3);
|
||||
G80DmaNext (pNv, 0x80000014);
|
||||
G80DmaNext (pNv, 0x80000013);
|
||||
G80DmaNext (pNv, 0x80000013);
|
||||
G80DmaStart(pNv, 0x200, 2);
|
||||
switch(pScrn->depth) {
|
||||
case 8: G80DmaNext (pNv, 0x000000f3); break;
|
||||
case 15: G80DmaNext (pNv, 0x000000f8); break;
|
||||
case 16: G80DmaNext (pNv, 0x000000e8); break;
|
||||
case 24: G80DmaNext (pNv, 0x000000e6); break;
|
||||
}
|
||||
G80DmaNext (pNv, 0x00000001);
|
||||
G80DmaStart(pNv, 0x214, 5);
|
||||
G80DmaNext (pNv, pitch);
|
||||
G80DmaNext (pNv, pitch);
|
||||
G80DmaNext (pNv, pNv->offscreenHeight);
|
||||
G80DmaNext (pNv, 0x00000000);
|
||||
G80DmaNext (pNv, 0x00000000);
|
||||
G80DmaStart(pNv, 0x230, 2);
|
||||
switch(pScrn->depth) {
|
||||
case 8: G80DmaNext (pNv, 0x000000f3); break;
|
||||
case 15: G80DmaNext (pNv, 0x000000f8); break;
|
||||
case 16: G80DmaNext (pNv, 0x000000e8); break;
|
||||
case 24: G80DmaNext (pNv, 0x000000e6); break;
|
||||
}
|
||||
G80DmaNext (pNv, 0x00000001);
|
||||
G80DmaStart(pNv, 0x244, 5);
|
||||
G80DmaNext (pNv, pitch);
|
||||
G80DmaNext (pNv, pitch);
|
||||
G80DmaNext (pNv, pNv->offscreenHeight);
|
||||
G80DmaNext (pNv, 0x00000000);
|
||||
G80DmaNext (pNv, 0x00000000);
|
||||
G80DmaStart(pNv, 0x260, 1);
|
||||
G80DmaNext (pNv, 0x00000001);
|
||||
G80DmaStart(pNv, 0x290, 1);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaStart(pNv, 0x29c, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaStart(pNv, 0x2e8, 2);
|
||||
switch(pScrn->depth) {
|
||||
case 8: G80DmaNext (pNv, 3); break;
|
||||
case 15: G80DmaNext (pNv, 1); break;
|
||||
case 16: G80DmaNext (pNv, 0); break;
|
||||
case 24: G80DmaNext (pNv, 2); break;
|
||||
}
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaStart(pNv, 0x584, 1);
|
||||
switch(pScrn->depth) {
|
||||
case 8: G80DmaNext (pNv, 0xf3); break;
|
||||
case 15: G80DmaNext (pNv, 0xf8); break;
|
||||
case 16: G80DmaNext (pNv, 0xe8); break;
|
||||
case 24: G80DmaNext (pNv, 0xe6); break;
|
||||
}
|
||||
G80DmaStart(pNv, 0x58c, 1);
|
||||
G80DmaNext (pNv, 0x111);
|
||||
G80DmaStart(pNv, 0x804, 1);
|
||||
switch(pScrn->depth) {
|
||||
case 8: G80DmaNext (pNv, 0xf3); break;
|
||||
case 15: G80DmaNext (pNv, 0xf8); break;
|
||||
case 16: G80DmaNext (pNv, 0xe8); break;
|
||||
case 24: G80DmaNext (pNv, 0xe6); break;
|
||||
}
|
||||
|
||||
pNv->currentRop = ~0; /* Set to something invalid */
|
||||
}
|
||||
|
||||
#define DEPTH_SHIFT(val, w) ((val << (8 - w)) | (val >> ((w << 1) - 8)))
|
||||
#define COLOR(c) (unsigned int)(0x3fff * ((c)/255.0))
|
||||
static void
|
||||
G80LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
|
||||
VisualPtr pVisual)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
int i, index;
|
||||
volatile struct {
|
||||
unsigned short red, green, blue, unused;
|
||||
} *lut = (void*)&pNv->mem[pNv->videoRam * 1024 - 0x5000];
|
||||
|
||||
switch(pScrn->depth) {
|
||||
case 15:
|
||||
for(i = 0; i < numColors; i++) {
|
||||
index = indices[i];
|
||||
lut[DEPTH_SHIFT(index, 5)].red = COLOR(colors[index].red);
|
||||
lut[DEPTH_SHIFT(index, 5)].green = COLOR(colors[index].green);
|
||||
lut[DEPTH_SHIFT(index, 5)].blue = COLOR(colors[index].blue);
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
for(i = 0; i < numColors; i++) {
|
||||
index = indices[i];
|
||||
lut[DEPTH_SHIFT(index, 6)].green = COLOR(colors[index].green);
|
||||
if(index < 32) {
|
||||
lut[DEPTH_SHIFT(index, 5)].red = COLOR(colors[index].red);
|
||||
lut[DEPTH_SHIFT(index, 5)].blue = COLOR(colors[index].blue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for(i = 0; i < numColors; i++) {
|
||||
index = indices[i];
|
||||
lut[index].red = COLOR(colors[index].red);
|
||||
lut[index].green = COLOR(colors[index].green);
|
||||
lut[index].blue = COLOR(colors[index].blue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static Bool
|
||||
G80ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
|
||||
{
|
||||
ScrnInfoPtr pScrn;
|
||||
G80Ptr pNv;
|
||||
CARD32 pitch;
|
||||
int visualMask;
|
||||
BoxRec AvailFBArea;
|
||||
|
||||
/* First get the ScrnInfoRec */
|
||||
pScrn = xf86Screens[pScreen->myNum];
|
||||
pNv = G80PTR(pScrn);
|
||||
|
||||
pScrn->vtSema = TRUE;
|
||||
|
||||
/* DIX visual init */
|
||||
miClearVisualTypes();
|
||||
visualMask = miGetDefaultVisualMask(pScrn->depth);
|
||||
if(!miSetVisualTypes(pScrn->depth, visualMask, 8, pScrn->defaultVisual))
|
||||
return FALSE;
|
||||
if(!miSetPixmapDepths())
|
||||
return FALSE;
|
||||
|
||||
/* 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,
|
||||
pScrn->virtualX, pScrn->virtualY,
|
||||
pScrn->xDpi, pScrn->yDpi,
|
||||
pScrn->displayWidth, pScrn->bitsPerPixel))
|
||||
return FALSE;
|
||||
|
||||
if(pScrn->bitsPerPixel > 8) {
|
||||
VisualPtr visual;
|
||||
|
||||
/* Fixup RGB ordering */
|
||||
visual = pScreen->visuals + pScreen->numVisuals;
|
||||
while(--visual >= pScreen->visuals) {
|
||||
if((visual->class | DynamicClass) == DirectColor) {
|
||||
visual->offsetRed = pScrn->offset.red;
|
||||
visual->offsetGreen = pScrn->offset.green;
|
||||
visual->offsetBlue = pScrn->offset.blue;
|
||||
visual->redMask = pScrn->mask.red;
|
||||
visual->greenMask = pScrn->mask.green;
|
||||
visual->blueMask = pScrn->mask.blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fbPictureInit(pScreen, 0, 0);
|
||||
|
||||
xf86SetBlackWhitePixels(pScreen);
|
||||
|
||||
pNv->offscreenHeight = ((pNv->videoRam << 10) - G80_RESERVED_VIDMEM) / pitch;
|
||||
if(pNv->offscreenHeight > 32767) pNv->offscreenHeight = 32767;
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||||
"%.2f MB available for offscreen pixmaps\n",
|
||||
(pNv->offscreenHeight - pScrn->virtualY) * pitch / 1024.0 / 1024.0);
|
||||
|
||||
AvailFBArea.x1 = 0;
|
||||
AvailFBArea.y1 = 0;
|
||||
AvailFBArea.x2 = pScrn->displayWidth;
|
||||
AvailFBArea.y2 = pNv->offscreenHeight;
|
||||
xf86InitFBManager(pScreen, &AvailFBArea);
|
||||
|
||||
if(!pNv->NoAccel) {
|
||||
G80InitHW(pScrn);
|
||||
if(!G80XAAInit(pScreen)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Hardware acceleration initialization failed\n");
|
||||
pNv->NoAccel = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
miInitializeBackingStore(pScreen);
|
||||
xf86SetBackingStore(pScreen);
|
||||
xf86SetSilkenMouse(pScreen);
|
||||
|
||||
/* Initialize software cursor.
|
||||
Must precede creation of the default colormap */
|
||||
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
|
||||
|
||||
/* Initialize hardware cursor. Must follow software cursor initialization. */
|
||||
if(pNv->HWCursor && !G80CursorInit(pScreen)) {
|
||||
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||||
"Hardware cursor initialization failed\n");
|
||||
pNv->HWCursor = FALSE;
|
||||
}
|
||||
|
||||
/* Initialize default colormap */
|
||||
if(!miCreateDefColormap(pScreen))
|
||||
return FALSE;
|
||||
|
||||
/* Initialize colormap layer.
|
||||
Must follow initialization of the default colormap */
|
||||
if(!xf86HandleColormaps(pScreen, 256, 8, G80LoadPalette, NULL,
|
||||
CMAP_PALETTED_TRUECOLOR))
|
||||
return FALSE;
|
||||
|
||||
xf86DPMSInit(pScreen, G80DispDPMSSet, 0);
|
||||
|
||||
/* Clear the screen */
|
||||
if(pNv->xaa) {
|
||||
/* Use the acceleration engine */
|
||||
pNv->xaa->SetupForSolidFill(pScrn, 0, GXcopy, ~0);
|
||||
pNv->xaa->SubsequentSolidFillRect(pScrn,
|
||||
0, 0, pScrn->displayWidth, pNv->offscreenHeight);
|
||||
G80DmaKickoff(pNv);
|
||||
} else {
|
||||
/* Use a slow software clear path */
|
||||
memset(pNv->mem, 0, pitch * pNv->offscreenHeight);
|
||||
}
|
||||
|
||||
/* Initialize the display */
|
||||
if(!AcquireDisplay(pScrn))
|
||||
return FALSE;
|
||||
|
||||
pScreen->SaveScreen = G80SaveScreen;
|
||||
|
||||
pNv->CloseScreen = pScreen->CloseScreen;
|
||||
pScreen->CloseScreen = G80CloseScreen;
|
||||
|
||||
pNv->BlockHandler = pScreen->BlockHandler;
|
||||
pScreen->BlockHandler = G80BlockHandler;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
G80FreeScreen(int scrnIndex, int flags)
|
||||
{
|
||||
G80FreeRec(xf86Screens[scrnIndex]);
|
||||
}
|
||||
|
||||
static Bool
|
||||
G80SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
||||
|
||||
return G80DispSetMode(pScrn, mode);
|
||||
}
|
||||
|
||||
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
|
||||
G80EnterVT(int scrnIndex, int flags)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
/* Reinit the hardware */
|
||||
if(pNv->xaa)
|
||||
G80InitHW(pScrn);
|
||||
|
||||
if(!AcquireDisplay(pScrn))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
G80LeaveVT(int scrnIndex, int flags)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
|
||||
|
||||
ReleaseDisplay(pScrn);
|
||||
}
|
||||
|
||||
Bool G80GetScrnInfoRec(PciChipsets *chips, int chip)
|
||||
{
|
||||
ScrnInfoPtr pScrn;
|
||||
|
||||
pScrn = xf86ConfigPciEntity(NULL, 0, chip,
|
||||
chips, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
if(!pScrn) return FALSE;
|
||||
|
||||
pScrn->driverVersion = NV_VERSION;
|
||||
pScrn->driverName = NV_DRIVER_NAME;
|
||||
pScrn->name = NV_NAME;
|
||||
|
||||
pScrn->PreInit = G80PreInit;
|
||||
pScrn->ScreenInit = G80ScreenInit;
|
||||
pScrn->SwitchMode = G80SwitchMode;
|
||||
pScrn->AdjustFrame = G80AdjustFrame;
|
||||
pScrn->EnterVT = G80EnterVT;
|
||||
pScrn->LeaveVT = G80LeaveVT;
|
||||
pScrn->FreeScreen = G80FreeScreen;
|
||||
// pScrn->ValidMode = G80ValidMode;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
75
src/g80_type.h
Normal file
75
src/g80_type.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <xaa.h>
|
||||
#include <xf86.h>
|
||||
#include <xf86int10.h>
|
||||
#include <xf86Cursor.h>
|
||||
|
||||
typedef enum Head {
|
||||
HEAD0 = 0,
|
||||
HEAD1
|
||||
} Head;
|
||||
|
||||
typedef enum ORType {
|
||||
DAC,
|
||||
SOR
|
||||
} ORType;
|
||||
|
||||
typedef enum ORNum {
|
||||
DAC0 = 0,
|
||||
DAC1 = 1,
|
||||
DAC2 = 2,
|
||||
SOR0 = 0,
|
||||
SOR1 = 1
|
||||
} ORNum;
|
||||
|
||||
typedef struct G80Rec {
|
||||
volatile CARD32 * reg;
|
||||
unsigned char * mem;
|
||||
|
||||
/* Probed data */
|
||||
CARD32 architecture;
|
||||
CARD32 RamAmountKBytes; /* Total vidmem */
|
||||
CARD32 videoRam; /* Mapped vidmem */
|
||||
const unsigned char*table1;
|
||||
int offscreenHeight;
|
||||
struct {
|
||||
ORNum dac;
|
||||
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 */
|
||||
|
||||
/* Options */
|
||||
OptionInfoPtr Options;
|
||||
Bool HWCursor;
|
||||
Bool NoAccel;
|
||||
DisplayModePtr BackendMode;
|
||||
|
||||
/* Cursor */
|
||||
xf86CursorInfoPtr CursorInfo;
|
||||
Bool cursorVisible;
|
||||
CARD32 tmpCursor[256]; /* Temporary 1bpp cursor image */
|
||||
|
||||
/* XAA */
|
||||
XAAInfoRecPtr xaa;
|
||||
CARD32 currentRop;
|
||||
|
||||
/* DMA command buffer */
|
||||
CARD32 dmaPut;
|
||||
CARD32 dmaCurrent;
|
||||
CARD32 dmaFree;
|
||||
CARD32 dmaMax;
|
||||
CARD32 * dmaBase;
|
||||
void (*DMAKickoffCallback)(ScrnInfoPtr);
|
||||
|
||||
CloseScreenProcPtr CloseScreen;
|
||||
ScreenBlockHandlerProcPtr BlockHandler;
|
||||
} G80Rec, *G80Ptr;
|
||||
|
||||
#define G80PTR(p) ((G80Ptr)((p)->driverPrivate))
|
||||
554
src/g80_xaa.c
Normal file
554
src/g80_xaa.c
Normal file
@@ -0,0 +1,554 @@
|
||||
/*
|
||||
* 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 <miline.h>
|
||||
|
||||
#include "g80_type.h"
|
||||
#include "g80_dma.h"
|
||||
#include "g80_xaa.h"
|
||||
|
||||
static void
|
||||
G80Sync(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
volatile CARD16 *pSync = (volatile CARD16*)&pNv->reg[0x00711008/4] + 1;
|
||||
|
||||
G80DmaStart(pNv, 0x104, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaStart(pNv, 0x100, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
|
||||
*pSync = 0x8000;
|
||||
G80DmaKickoff(pNv);
|
||||
while(*pSync);
|
||||
}
|
||||
|
||||
static void
|
||||
G80DMAKickoffCallback(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
G80DmaKickoff(pNv);
|
||||
pNv->DMAKickoffCallback = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
G80SetPattern(G80Ptr pNv, int bg, int fg, int pat0, int pat1)
|
||||
{
|
||||
G80DmaStart(pNv, 0x2f0, 4);
|
||||
G80DmaNext (pNv, bg);
|
||||
G80DmaNext (pNv, fg);
|
||||
G80DmaNext (pNv, pat0);
|
||||
G80DmaNext (pNv, pat1);
|
||||
}
|
||||
|
||||
static void
|
||||
G80SetRopSolid(G80Ptr pNv, CARD32 rop, CARD32 planemask)
|
||||
{
|
||||
static const int rops[] = {
|
||||
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0,
|
||||
0x30, 0xB0, 0x70, 0xF0
|
||||
};
|
||||
|
||||
if(planemask != ~0) {
|
||||
G80SetPattern(pNv, 0, planemask, ~0, ~0);
|
||||
if(pNv->currentRop != (rop + 32)) {
|
||||
pNv->currentRop = rop + 32;
|
||||
|
||||
rop = rops[rop] | 0xA;
|
||||
G80DmaStart(pNv, 0x2a0, 1);
|
||||
G80DmaNext (pNv, rop);
|
||||
}
|
||||
} else if(pNv->currentRop != rop) {
|
||||
if(pNv->currentRop >= 16)
|
||||
G80SetPattern(pNv, ~0, ~0, ~0, ~0);
|
||||
pNv->currentRop = rop;
|
||||
|
||||
rop = rops[rop];
|
||||
rop |= rop >> 4;
|
||||
G80DmaStart(pNv, 0x2a0, 1);
|
||||
G80DmaNext (pNv, rop);
|
||||
}
|
||||
}
|
||||
|
||||
static void inline
|
||||
G80SetClip(G80Ptr pNv, int x, int y, int w, int h)
|
||||
{
|
||||
G80DmaStart(pNv, 0x280, 4);
|
||||
G80DmaNext (pNv, x);
|
||||
G80DmaNext (pNv, y);
|
||||
G80DmaNext (pNv, w);
|
||||
G80DmaNext (pNv, h);
|
||||
}
|
||||
|
||||
/* Screen to screen copies */
|
||||
|
||||
static void
|
||||
G80SetupForScreenToScreenCopy(
|
||||
ScrnInfoPtr pScrn,
|
||||
int xdir, int ydir,
|
||||
int rop,
|
||||
unsigned planemask,
|
||||
int transparency_color
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
planemask |= ~0 << pScrn->depth;
|
||||
|
||||
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
||||
G80DmaStart(pNv, 0x2ac, 1);
|
||||
if(rop == GXcopy && planemask == ~0) {
|
||||
G80DmaNext (pNv, 3);
|
||||
} else {
|
||||
G80DmaNext (pNv, 1);
|
||||
G80SetRopSolid(pNv, rop, planemask);
|
||||
}
|
||||
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
||||
}
|
||||
|
||||
static void
|
||||
G80SubsequentScreenToScreenCopy(
|
||||
ScrnInfoPtr pScrn,
|
||||
int x1, int y1,
|
||||
int x2, int y2,
|
||||
int w, int h
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
G80DmaStart(pNv, 0x110, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaStart(pNv, 0x8b0, 12);
|
||||
G80DmaNext (pNv, x2);
|
||||
G80DmaNext (pNv, y2);
|
||||
G80DmaNext (pNv, w);
|
||||
G80DmaNext (pNv, h);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, x1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, y1);
|
||||
|
||||
if(w * h >= 512)
|
||||
G80DmaKickoff(pNv);
|
||||
}
|
||||
|
||||
/* Solid fills */
|
||||
|
||||
static void
|
||||
G80SetupForSolidFill(
|
||||
ScrnInfoPtr pScrn,
|
||||
int color,
|
||||
int rop,
|
||||
unsigned planemask
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
planemask |= ~0 << pScrn->depth;
|
||||
|
||||
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
||||
G80DmaStart(pNv, 0x2ac, 1);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80SetRopSolid(pNv, rop, planemask);
|
||||
G80DmaStart(pNv, 0x580, 1);
|
||||
G80DmaNext (pNv, 4);
|
||||
G80DmaStart(pNv, 0x588, 1);
|
||||
G80DmaNext (pNv, color);
|
||||
|
||||
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
||||
}
|
||||
|
||||
static void
|
||||
G80SubsequentFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
G80DmaStart(pNv, 0x600, 4);
|
||||
G80DmaNext (pNv, x);
|
||||
G80DmaNext (pNv, y);
|
||||
G80DmaNext (pNv, x + w);
|
||||
G80DmaNext (pNv, y + h);
|
||||
|
||||
if(w * h >= 512)
|
||||
G80DmaKickoff(pNv);
|
||||
}
|
||||
|
||||
/* 8x8 pattern fills */
|
||||
|
||||
static void
|
||||
G80SetupForMono8x8PatternFill(
|
||||
ScrnInfoPtr pScrn,
|
||||
int patternx, int patterny,
|
||||
int fg, int bg,
|
||||
int rop,
|
||||
unsigned planemask
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
static const int rops[] = {
|
||||
0x00, 0xA0, 0x50, 0xF0, 0x0A, 0xAA, 0x5A, 0xFA, 0x05, 0xA5, 0x55, 0xF5,
|
||||
0x0F, 0xAF, 0x5F, 0xFF
|
||||
};
|
||||
|
||||
planemask = ~0 << pScrn->depth;
|
||||
|
||||
fg |= planemask;
|
||||
if(bg == -1) bg = 0;
|
||||
else bg |= planemask;
|
||||
|
||||
if(pNv->currentRop != (rop + 16)) {
|
||||
G80DmaStart(pNv, 0x2a0, 1);
|
||||
G80DmaNext (pNv, rops[rop]);
|
||||
pNv->currentRop = rop + 16;
|
||||
}
|
||||
|
||||
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
||||
G80SetPattern(pNv, bg, fg, patternx, patterny);
|
||||
|
||||
G80DmaStart(pNv, 0x2ac, 1);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaStart(pNv, 0x580, 1);
|
||||
G80DmaNext (pNv, 4);
|
||||
G80DmaStart(pNv, 0x588, 1);
|
||||
G80DmaNext (pNv, fg);
|
||||
|
||||
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
||||
}
|
||||
|
||||
static void
|
||||
G80SubsequentMono8x8PatternFillRect(
|
||||
ScrnInfoPtr pScrn,
|
||||
int patternx, int patterny,
|
||||
int x, int y,
|
||||
int w, int h
|
||||
)
|
||||
{
|
||||
G80SubsequentFillRect(pScrn, x, y, w, h);
|
||||
}
|
||||
|
||||
/* Color expansion fills */
|
||||
|
||||
static CARD32 _color_expand_dwords;
|
||||
static int _remaining;
|
||||
static unsigned char *_storage_buffer[1];
|
||||
|
||||
static void
|
||||
G80SetupForScanlineCPUToScreenColorExpandFill(
|
||||
ScrnInfoPtr pScrn,
|
||||
int fg, int bg,
|
||||
int rop,
|
||||
unsigned int planemask
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
CARD32 mask = ~0 << pScrn->depth;
|
||||
|
||||
planemask |= mask;
|
||||
|
||||
G80DmaStart(pNv, 0x2ac, 1);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80SetRopSolid(pNv, rop, planemask);
|
||||
G80DmaStart(pNv, 0x800, 1);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaStart(pNv, 0x808, 6);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, bg | mask);
|
||||
G80DmaNext (pNv, fg | mask);
|
||||
G80DmaNext (pNv, (bg == -1) ? 0 : 1);
|
||||
}
|
||||
|
||||
static void
|
||||
G80SubsequentScanlineCPUToScreenColorExpandFill(
|
||||
ScrnInfoPtr pScrn,
|
||||
int x, int y,
|
||||
int w, int h,
|
||||
int skipleft
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
int bw = (w + 31) & ~31;
|
||||
|
||||
_color_expand_dwords = bw >> 5;
|
||||
_remaining = h;
|
||||
|
||||
G80SetClip(pNv, x + skipleft, y, w - skipleft, h);
|
||||
|
||||
G80DmaStart(pNv, 0x838, 10);
|
||||
G80DmaNext (pNv, bw);
|
||||
G80DmaNext (pNv, h);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, x);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, y);
|
||||
|
||||
G80DmaStart(pNv, 0x40000860, _color_expand_dwords);
|
||||
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
||||
}
|
||||
|
||||
static void
|
||||
G80SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
pNv->dmaCurrent += _color_expand_dwords;
|
||||
|
||||
if(--_remaining) {
|
||||
G80DmaStart(pNv, 0x40000860, _color_expand_dwords);
|
||||
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
||||
} else {
|
||||
G80DmaKickoff(pNv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scaline image write */
|
||||
|
||||
static void
|
||||
G80SetupForScanlineImageWrite(
|
||||
ScrnInfoPtr pScrn, int rop,
|
||||
unsigned int planemask,
|
||||
int trans_color,
|
||||
int bpp, int depth
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
planemask |= ~0 << pScrn->depth;
|
||||
|
||||
G80DmaStart(pNv, 0x2ac, 1);
|
||||
if(rop == GXcopy && planemask == ~0) {
|
||||
G80DmaNext (pNv, 3);
|
||||
} else {
|
||||
G80DmaNext (pNv, 1);
|
||||
G80SetRopSolid(pNv, rop, planemask);
|
||||
}
|
||||
|
||||
G80DmaStart(pNv, 0x800, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
}
|
||||
|
||||
static CARD32 _image_dwords;
|
||||
|
||||
static void
|
||||
G80SubsequentScanlineImageWriteRect(
|
||||
ScrnInfoPtr pScrn,
|
||||
int x, int y,
|
||||
int w, int h,
|
||||
int skipleft
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
int Bpp = pScrn->bitsPerPixel >> 3;
|
||||
|
||||
_remaining = h;
|
||||
_image_dwords = (w * Bpp + 3) / 4;
|
||||
|
||||
G80SetClip(pNv, x + skipleft, y, w - skipleft, h);
|
||||
|
||||
G80DmaStart(pNv, 0x838, 10);
|
||||
G80DmaNext (pNv, w);
|
||||
G80DmaNext (pNv, h);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, x);
|
||||
G80DmaNext (pNv, 0);
|
||||
G80DmaNext (pNv, y);
|
||||
|
||||
G80DmaStart(pNv, 0x40000860, _image_dwords);
|
||||
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
||||
}
|
||||
|
||||
static void G80SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
pNv->dmaCurrent += _image_dwords;
|
||||
|
||||
if(--_remaining) {
|
||||
G80DmaStart(pNv, 0x40000860, _image_dwords);
|
||||
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
||||
} else {
|
||||
G80DmaKickoff(pNv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Solid lines */
|
||||
|
||||
static void
|
||||
G80SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
planemask |= ~0 << pScrn->depth;
|
||||
|
||||
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
||||
G80DmaStart(pNv, 0x2ac, 1);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80SetRopSolid(pNv, rop, planemask);
|
||||
G80DmaStart(pNv, 0x580, 1);
|
||||
G80DmaNext (pNv, 1);
|
||||
G80DmaStart(pNv, 0x588, 1);
|
||||
G80DmaNext (pNv, color);
|
||||
|
||||
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
||||
}
|
||||
|
||||
static void
|
||||
G80SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
G80DmaStart(pNv, 0x400005e0, 2);
|
||||
G80DmaNext (pNv, (y << 16) | (x & 0xffff));
|
||||
if(dir == DEGREES_0) {
|
||||
G80DmaNext (pNv, (y << 16) | ((x + len) & 0xffff));
|
||||
} else {
|
||||
G80DmaNext (pNv, ((y + len) << 16) | (x & 0xffff));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
G80SubsequentSolidTwoPointLine(
|
||||
ScrnInfoPtr pScrn,
|
||||
int x1, int y1,
|
||||
int x2, int y2,
|
||||
int flags
|
||||
)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
Bool drawLast = !(flags & OMIT_LAST);
|
||||
|
||||
G80DmaStart(pNv, 0x400005e0, drawLast ? 4 : 2);
|
||||
G80DmaNext (pNv, (y1 << 16) | (x1 & 0xffff));
|
||||
G80DmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
|
||||
if(drawLast) {
|
||||
G80DmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
|
||||
G80DmaNext (pNv, ((y2 + 1) << 16) | (x2 & 0xffff));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
G80SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
int h = y2 - y1 + 1;
|
||||
int w = x2 - x1 + 1;
|
||||
|
||||
G80SetClip(pNv, x1, y1, w, h);
|
||||
}
|
||||
|
||||
static void
|
||||
G80DisableClipping(ScrnInfoPtr pScrn)
|
||||
{
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
|
||||
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
||||
}
|
||||
|
||||
|
||||
Bool
|
||||
G80XAAInit(ScreenPtr pScreen)
|
||||
{
|
||||
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
||||
G80Ptr pNv = G80PTR(pScrn);
|
||||
XAAInfoRecPtr xaa;
|
||||
|
||||
xaa = pNv->xaa = XAACreateInfoRec();
|
||||
if(!xaa) return FALSE;
|
||||
|
||||
xaa->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
|
||||
xaa->Sync = G80Sync;
|
||||
|
||||
/* Screen to screen copies */
|
||||
xaa->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
|
||||
xaa->SetupForScreenToScreenCopy = G80SetupForScreenToScreenCopy;
|
||||
xaa->SubsequentScreenToScreenCopy = G80SubsequentScreenToScreenCopy;
|
||||
|
||||
/* Solid fills */
|
||||
xaa->SolidFillFlags = 0;
|
||||
xaa->SetupForSolidFill = G80SetupForSolidFill;
|
||||
xaa->SubsequentSolidFillRect = G80SubsequentFillRect;
|
||||
|
||||
/* 8x8 pattern fills */
|
||||
xaa->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN |
|
||||
HARDWARE_PATTERN_PROGRAMMED_BITS |
|
||||
NO_PLANEMASK;
|
||||
xaa->SetupForMono8x8PatternFill = G80SetupForMono8x8PatternFill;
|
||||
xaa->SubsequentMono8x8PatternFillRect = G80SubsequentMono8x8PatternFillRect;
|
||||
|
||||
/* Color expansion fills */
|
||||
xaa->ScanlineCPUToScreenColorExpandFillFlags =
|
||||
BIT_ORDER_IN_BYTE_LSBFIRST |
|
||||
CPU_TRANSFER_PAD_DWORD |
|
||||
LEFT_EDGE_CLIPPING |
|
||||
LEFT_EDGE_CLIPPING_NEGATIVE_X;
|
||||
xaa->NumScanlineColorExpandBuffers = 1;
|
||||
xaa->SetupForScanlineCPUToScreenColorExpandFill =
|
||||
G80SetupForScanlineCPUToScreenColorExpandFill;
|
||||
xaa->SubsequentScanlineCPUToScreenColorExpandFill =
|
||||
G80SubsequentScanlineCPUToScreenColorExpandFill;
|
||||
xaa->SubsequentColorExpandScanline =
|
||||
G80SubsequentColorExpandScanline;
|
||||
xaa->ScanlineColorExpandBuffers = _storage_buffer;
|
||||
|
||||
/* Scaline image write */
|
||||
xaa->ScanlineImageWriteFlags = NO_GXCOPY |
|
||||
NO_TRANSPARENCY |
|
||||
LEFT_EDGE_CLIPPING |
|
||||
LEFT_EDGE_CLIPPING_NEGATIVE_X;
|
||||
xaa->NumScanlineImageWriteBuffers = 1;
|
||||
xaa->SetupForScanlineImageWrite = G80SetupForScanlineImageWrite;
|
||||
xaa->SubsequentScanlineImageWriteRect = G80SubsequentScanlineImageWriteRect;
|
||||
xaa->SubsequentImageWriteScanline = G80SubsequentImageWriteScanline;
|
||||
xaa->ScanlineImageWriteBuffers = _storage_buffer;
|
||||
|
||||
/* Solid lines */
|
||||
xaa->SolidLineFlags = 0;
|
||||
xaa->SetupForSolidLine = G80SetupForSolidLine;
|
||||
xaa->SubsequentSolidHorVertLine = G80SubsequentSolidHorVertLine;
|
||||
xaa->SubsequentSolidTwoPointLine = G80SubsequentSolidTwoPointLine;
|
||||
xaa->SetClippingRectangle = G80SetClippingRectangle;
|
||||
xaa->DisableClipping = G80DisableClipping;
|
||||
xaa->ClippingFlags = HARDWARE_CLIP_SOLID_LINE;
|
||||
|
||||
miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6);
|
||||
|
||||
return XAAInit(pScreen, xaa);
|
||||
}
|
||||
1
src/g80_xaa.h
Normal file
1
src/g80_xaa.h
Normal file
@@ -0,0 +1 @@
|
||||
Bool G80XAAInit(ScreenPtr);
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
const OptionInfoRec * RivaAvailableOptions(int chipid, int busid);
|
||||
Bool RivaGetScrnInfoRec(PciChipsets *chips, int chip);
|
||||
Bool G80GetScrnInfoRec(PciChipsets *chips, int chip);
|
||||
|
||||
/*
|
||||
* Forward definitions for the functions that make up the driver.
|
||||
@@ -332,6 +333,13 @@ static SymTabRec NVKnownChipsets[] =
|
||||
{ 0x10DE0244, "GeForce Go 6150" },
|
||||
{ 0x10DE0247, "GeForce Go 6100" },
|
||||
|
||||
#if SUPPORT_G80
|
||||
{ 0x10DE0191, "GeForce 8800 GTX" },
|
||||
{ 0x10DE0193, "GeForce 8800 GTS" },
|
||||
{ 0x10DE019D, "Quadro FX 5600" },
|
||||
{ 0x10DE019E, "Quadro FX 4600" },
|
||||
#endif
|
||||
|
||||
{-1, NULL}
|
||||
};
|
||||
|
||||
@@ -647,6 +655,20 @@ NVGetPCIXpressChip (pciVideoPtr pVideo)
|
||||
return pciid;
|
||||
}
|
||||
|
||||
#if SUPPORT_G80
|
||||
static Bool
|
||||
NVIsG80(int chipType)
|
||||
{
|
||||
switch(chipType & 0xfff0) {
|
||||
case 0x0190:
|
||||
case 0x0400:
|
||||
case 0x0420:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Mandatory */
|
||||
static Bool
|
||||
@@ -700,6 +722,8 @@ NVProbe(DriverPtr drv, int flags)
|
||||
NVPciChipsets[numUsed].resList = RES_SHARED_VGA;
|
||||
numUsed++;
|
||||
} else if ((*ppPci)->vendor == PCI_VENDOR_NVIDIA) {
|
||||
Bool canHandle = FALSE;
|
||||
|
||||
/* look for a compatible devices which may be newer than
|
||||
the NVKnownChipsets list above. */
|
||||
switch(token & 0xfff0) {
|
||||
@@ -725,14 +749,23 @@ NVProbe(DriverPtr drv, int flags)
|
||||
case 0x0290:
|
||||
case 0x0390:
|
||||
case 0x03D0:
|
||||
canHandle = TRUE;
|
||||
break;
|
||||
default: break; /* we don't recognize it */
|
||||
}
|
||||
|
||||
#if SUPPORT_G80
|
||||
if(NVIsG80((*ppPci)->chipType))
|
||||
canHandle = TRUE;
|
||||
#endif
|
||||
|
||||
if(canHandle) {
|
||||
NVChipsets[numUsed].token = pciid;
|
||||
NVChipsets[numUsed].name = "Unknown NVIDIA chip";
|
||||
NVPciChipsets[numUsed].numChipset = pciid;
|
||||
NVPciChipsets[numUsed].PCIid = pciid;
|
||||
NVPciChipsets[numUsed].resList = RES_SHARED_VGA;
|
||||
numUsed++;
|
||||
break;
|
||||
default: break; /* we don't recognize it */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -762,6 +795,11 @@ 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;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#if !USE_LIBC_WRAPPER
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* All drivers should typically include these */
|
||||
@@ -55,7 +56,6 @@
|
||||
#include "vgaHW.h"
|
||||
|
||||
#include "xf86Cursor.h"
|
||||
#include "xf86DDC.h"
|
||||
|
||||
#include "region.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user