diff options
author | Alan Hourihane <alanh@tungstengraphics.com> | 2007-03-28 15:11:23 +0100 |
---|---|---|
committer | Alan Hourihane <alanh@tungstengraphics.com> | 2007-03-28 15:11:23 +0100 |
commit | 430440787c85eb8b3a8ff2b33b8bd408a72658f0 (patch) | |
tree | 7610dd372a1ec2630fc69cbc724afab1bbf515cb |
Initial commit of the vermilion driver
-rw-r--r-- | COPYING | 12 | ||||
-rw-r--r-- | ChangeLog | 84 | ||||
-rw-r--r-- | Makefile.am | 22 | ||||
-rwxr-xr-x | autogen.sh | 12 | ||||
-rw-r--r-- | configure.ac | 77 | ||||
-rw-r--r-- | man/Makefile.am | 59 | ||||
-rw-r--r-- | man/vermilion.man | 74 | ||||
-rw-r--r-- | src/Makefile.am | 41 | ||||
-rw-r--r-- | src/vermilion.c | 1415 | ||||
-rw-r--r-- | src/vermilion.h | 223 | ||||
-rw-r--r-- | src/vermilion_accel.c | 255 | ||||
-rw-r--r-- | src/vermilion_kernel.h | 81 | ||||
-rw-r--r-- | src/vermilion_mbx.h | 117 | ||||
-rw-r--r-- | src/vermilion_mode.c | 316 | ||||
-rw-r--r-- | src/vermilion_panels.c | 63 | ||||
-rw-r--r-- | src/vermilion_reg.h | 187 | ||||
-rw-r--r-- | src/vermilion_sys.c | 444 | ||||
-rw-r--r-- | src/vermilion_sys.h | 87 |
18 files changed, 3569 insertions, 0 deletions
@@ -0,0 +1,12 @@ +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. + +Please submit updated COPYING files to the Xorg bugzilla: + +https://bugs.freedesktop.org/enter_bug.cgi?product=xorg + +All licensing questions regarding this software should be directed at the +Xorg mailing list: + +http://lists.freedesktop.org/mailman/listinfo/xorg diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..9095e7b --- /dev/null +++ b/ChangeLog @@ -0,0 +1,84 @@ +2006-04-07 Adam Jackson <ajax@freedesktop.org> + + * configure.ac: + * src/nsc_driver.c: + Bump to 2.8.1 for Xv changes. + +2006-04-07 Aaron Plattner <aplattner@nvidia.com> + + * src/nsc_gx1_video.c: (GX1PutImage): + * src/nsc_gx2_video.c: (GX2PutImage): + Add a DrawablePtr argument to the XV functions to pave the way for + redirected video. + +2006-04-07 Adam Jackson <ajax@freedesktop.org> + + * configure.ac: + * src/durango.c: + * src/nsc.h: + * src/nsc_driver.c: + * src/nsc_galstub.c: + * src/nsc_gx1_accel.c: + * src/nsc_gx1_cursor.c: + * src/nsc_gx1_dga.c: + * src/nsc_gx1_driver.c: + * src/nsc_gx1_shadow.c: + * src/nsc_gx1_video.c: + * src/nsc_gx2_accel.c: + * src/nsc_gx2_cursor.c: + * src/nsc_gx2_dga.c: + * src/nsc_gx2_driver.c: + * src/nsc_gx2_shadow.c: + * src/nsc_gx2_video.c: + Unlibcwrap. Bump server version requirement. Bump to 2.8.0. + +2006-02-27 Alan Coopersmith <alan.coopersmith@sun.com> + + * man/nsc.man: + Typo fix (Nicholas Joly, XFree86 bugzilla #1658) + +2005-12-20 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version for X11R7 release. + +2005-12-14 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version number for final X11R7 release candidate. + +2005-12-06 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * man/Makefile.am: + Change *man_SOURCES ==> *man_PRE to fix autotools warnings. + +2005-12-03 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version number for X11R7 RC3 release. + +2005-12-01 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Remove extraneous AC_MSG_RESULT. + +2005-11-29 Adam Jackson <ajax@freedesktop.org> + + * configure.ac: + Only build dlloader modules by default. + +2005-11-15 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Add check for DGA extension to fix issues when building with + separate build roots. + +2005-11-09 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update package version number for X11R7 RC2 release. + +2005-11-01 Kevin E. Martin <kem-at-freedesktop-dot-org> + + * configure.ac: + Update pkgcheck dependencies to work with separate build roots. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..7052905 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,22 @@ +# Copyright 2005 Adam Jackson. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON 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. + +AUTOMAKE_OPTIONS = foreign +SUBDIRS = src man diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..904cd67 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +ORIGDIR=`pwd` +cd $srcdir + +autoreconf -v --install || exit 1 +cd $ORIGDIR || exit $? + +$srcdir/configure --enable-maintainer-mode "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..de5072a --- /dev/null +++ b/configure.ac @@ -0,0 +1,77 @@ +# Copyright 2005 Adam Jackson. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON 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. +# +# Process this file with autoconf to produce a configure script + +AC_PREREQ(2.57) +AC_INIT([xf86-video-vermilion], + 1.0.0, + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], + xf86-video-vermilion) + +AC_CONFIG_SRCDIR([Makefile.am]) +AM_CONFIG_HEADER([config.h]) +AC_CONFIG_AUX_DIR(.) + +AM_INIT_AUTOMAKE([dist-bzip2]) + +AM_MAINTAINER_MODE + +# Checks for programs. +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +AC_PROG_CC + +AH_TOP([#include "xorg-server.h"]) + +AC_ARG_WITH(xorg-module-dir, + AC_HELP_STRING([--with-xorg-module-dir=DIR], + [Default xorg module directory [[default=$libdir/xorg/modules]]]), + [moduledir="$withval"], + [moduledir="$libdir/xorg/modules"]) + +# Checks for extensions +XORG_DRIVER_CHECK_EXT(RENDER, renderproto) +XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) +XORG_DRIVER_CHECK_EXT(XFreeXDGA, xf86dgaproto) + +# Checks for pkg-config packages +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.0.99.901 xproto fontsproto $REQUIRED_MODULES]) +sdkdir=$(pkg-config --variable=sdkdir xorg-server) + +# Checks for libraries. + +# Checks for header files. +AC_HEADER_STDC + +AC_SUBST([XORG_CFLAGS]) +AC_SUBST([moduledir]) + +DRIVER_NAME=vermilion +AC_SUBST([DRIVER_NAME]) + +XORG_MANPAGE_SECTIONS +XORG_RELEASE_VERSION + +AC_OUTPUT([ + Makefile + src/Makefile + man/Makefile +]) diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 0000000..bf7ec17 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,59 @@ +# $Id$ +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation. +# +# 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 OPEN GROUP 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. +# +# Except as contained in this notice, the name of the copyright holders shall +# not be used in advertising or otherwise to promote the sale, use or +# other dealings in this Software without prior written authorization +# from the copyright holders. +# + +drivermandir = $(DRIVER_MAN_DIR) + +driverman_PRE = @DRIVER_NAME@.man + +driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@) + +EXTRA_DIST = @DRIVER_NAME@.man + +CLEANFILES = $(driverman_DATA) + +SED = sed + +# Strings to replace in man pages +XORGRELSTRING = @PACKAGE_STRING@ + XORGMANNAME = X Version 11 + +MAN_SUBSTS = \ + -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ + -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \ + -e 's|__xservername__|Xorg|g' \ + -e 's|__xconfigfile__|xorg.conf|g' \ + -e 's|__projectroot__|$(prefix)|g' \ + -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \ + -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' + +SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man + +.man.$(DRIVER_MAN_SUFFIX): + sed $(MAN_SUBSTS) < $< > $@ diff --git a/man/vermilion.man b/man/vermilion.man new file mode 100644 index 0000000..bb99a11 --- /dev/null +++ b/man/vermilion.man @@ -0,0 +1,74 @@ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH VERMILION __drivermansuffix__ __vendorversion__ +.SH NAME +vermilion \- Generic VERMILION video driver +.SH SYNOPSIS +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" devname \*q +.B " Driver \*qvermilion\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B vermilion +is an __xservername__ driver for generic VERMILION video cards. It can drive most +VERMILION-compatible video cards, but only makes use of the basic standard +VERMILION core that is common to these cards. The driver supports depths 15 +and 24. +.SH SUPPORTED HARDWARE +The +.B vermilion +driver supports most VERMILION-compatible video cards. There are some known +exceptions, and those should be listed here. +.SH CONFIGURATION DETAILS +Please refer to __xconfigfile__(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to this +driver. +.PP +The driver auto-detects the presence of VERMILION-compatible hardware. The +.B ChipSet +name may optionally be specified in the config file +.B \*qDevice\*q +section, and will override the auto-detection: +.PP +.RS 4 +"vermilion" +.RE +.PP +The following driver +.B Options +are supported: +.TP +.BI "Option \*qShadowFB\*q \*q" boolean \*q +Enable or disable use of the shadow framebuffer layer. This is currently +enabled for depth 15 because of hardware restrictions, but disabled for +depth 24 where the accelerator is used to give higher performance. +.TP +.BI "Option \*qPanelType\*q \*q" integer \*q +Sets the panel timing constraints to the timing of one of the +pre-programmed panel types, and makes sure that the panel and panel +backlight are switched on an off as appropriate. If this value is set +to \*q-1\*q the driver ignores any panel timings and avoids trying to +manipulate panel and backlight power. The currently supported values are: +\*q-1\*q; don't assmume any panel timing constraints and +\*q0\*q, assume that the connected panel is a SHARP LQ150X1LGN2A. Default: \*q0\*q. +.TP +.BI "Option \*qFusedClock\*q \*q" integer \*q +The driver by default supports a set of 9 discrete dotclocks. These +clocks are: (given as MHz (index)): 6.75(0), 13.5(1), 27.0(2), 29.7(3), +37.125(4), 54.0(5), 59.4(6), 74.25(7) and 120.0(8). The driver can be +forced to support only one of these clocks by giving the corresponding +index as argument to this option. If an index of \*q-1\*q is given, +the driver will support all of the above clocks. Default: \*q-1\* (All +clocks supported). +.TP +.BI "Option \*qDebug\*q \*q" boolean \*q +Enable a debug printout of the modesetting registers. Default: false. + +.SH "SEE ALSO" +__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgcfg(__appmansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) +.SH AUTHORS +Authors include: Michel Danzer <michel-at-tungstengraphics-dot-com>, Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> and Alan Hourihane <alanh-at-tungstengraphics-dot-com> +.TP diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..37141c3 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,41 @@ +# Copyright 2005 Adam Jackson. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# ADAM JACKSON 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. + +# this is obnoxious: +# -module lets us name the module exactly how we want +# -avoid-version prevents gratuitous .0.0.0 version numbers on the end +# _ladir passes a dummy rpath to libtool so the thing will actually link +# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. +AM_CFLAGS = @XORG_CFLAGS@ +vermilion_drv_la_LTLIBRARIES = vermilion_drv.la +vermilion_drv_la_LDFLAGS = -module -avoid-version +vermilion_drv_ladir = @moduledir@/drivers + +vermilion_drv_la_SOURCES = \ + vermilion.c \ + vermilion.h \ + vermilion_accel.c \ + vermilion_kernel.h \ + vermilion_mbx.h \ + vermilion_mode.c \ + vermilion_panels.c \ + vermilion_reg.h \ + vermilion_sys.c \ + vermilion_sys.h diff --git a/src/vermilion.c b/src/vermilion.c new file mode 100644 index 0000000..6686b59 --- /dev/null +++ b/src/vermilion.c @@ -0,0 +1,1415 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: + * Michel Dänzer <michel-at-tungstengraphics-dot-com> + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * Alan Hourihane <alanh-at-tungstengraphics-dot-com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <sys/mman.h> + + +#include "vermilion_kernel.h" +#include "vermilion.h" +#include "vermilion_reg.h" + +/* All drivers initialising the SW cursor need this */ +#include "mipointer.h" + +/* All drivers implementing backing store need this */ +#include "mibstore.h" + +/* Colormap handling */ +#include "micmap.h" +#include "xf86cmap.h" + +/* DPMS */ +#define DPMS_SERVER +#include <X11/extensions/dpms.h> +#include "xf86Priv.h" + +#define KERNELNAME "Vermilion Range" +#define PROCFB "/proc/fb" +#define DEVFB "/dev/fb" + +/* Mandatory functions */ +static const OptionInfoRec *VERMILIONAvailableOptions(int chipid, int busid); +static void VERMILIONIdentify(int flags); +static Bool VERMILIONProbe(DriverPtr drv, int flags); +static Bool VERMILIONPreInit(ScrnInfoPtr pScrn, int flags); +static Bool VERMILIONScreenInit(int Index, ScreenPtr pScreen, int argc, + char **argv); +static Bool VERMILIONEnterVT(int scrnIndex, int flags); +static void VERMILIONLeaveVT(int scrnIndex, int flags); +static Bool VERMILIONCloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool VERMILIONSaveScreen(ScreenPtr pScreen, int mode); + +static Bool VERMILIONSwitchMode(int scrnIndex, DisplayModePtr pMode, + int flags); +static Bool VERMILIONSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); +static void VERMILIONAdjustFrame(int scrnIndex, int x, int y, int flags); +static void VERMILIONFreeScreen(int scrnIndex, int flags); +static void VERMILIONFreeRec(ScrnInfoPtr pScrn); + +static void +VERMILIONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, int flags); + +/* locally used functions */ +static Bool VERMILIONMapMem(ScrnInfoPtr pScrn); +static void VERMILIONUnmapMem(ScrnInfoPtr pScrn); +static void VERMILIONLoadPalette(ScrnInfoPtr pScrn, int numColors, + int *indices, LOCO * colors, VisualPtr pVisual); +static Bool VERMILIONRestore(ScrnInfoPtr pScrn); +static Bool VERMILIONSave(ScrnInfoPtr pScrn); + +#ifndef makedev +#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) +#endif + +/* + * This contains the functions needed by the server after loading the + * driver module. It must be supplied, and gets added the driver list by + * the Module Setup funtion in the dynamic case. In the static case a + * reference to this is compiled in, and this requires that the name of + * this DriverRec be an upper-case version of the driver name. + */ + +_X_EXPORT DriverRec VERMILION = { + VERMILION_VERSION, + VERMILION_DRIVER_NAME, + VERMILIONIdentify, + VERMILIONProbe, + VERMILIONAvailableOptions, + NULL, + 0 +}; + +#define PCI_CHIP_VERMILION 0x5009 +#define PCI_CHIP_VM_MBX 0x5002 + +enum GenericTypes +{ + CHIP_VERMILION +}; + +/* Supported chipsets */ +static SymTabRec VERMILIONChipsets[] = { + {CHIP_VERMILION, "vermilion"}, + {-1, NULL} +}; + +static PciChipsets VERMILIONPCIchipsets[] = { + {CHIP_VERMILION, PCI_CHIP_VERMILION, NULL}, + {-1, -1, RES_UNDEFINED}, +}; + +typedef enum +{ + OPTION_SHADOWFB, + OPTION_ACCEL, + OPTION_FUSEDCLOCK, + OPTION_PANELTYPE, + OPTION_DEBUG +} VERMILIONOpts; + +static const OptionInfoRec VERMILIONOptions[] = { + {OPTION_SHADOWFB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_ACCEL, "Accel", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_FUSEDCLOCK, "FusedClock", OPTV_INTEGER, {0}, FALSE}, + {OPTION_PANELTYPE, "PanelType", OPTV_INTEGER, {0}, FALSE}, + {OPTION_DEBUG, "Debug", OPTV_BOOLEAN, {0}, FALSE}, + {-1, NULL, OPTV_NONE, {0}, FALSE} +}; + +/* + * List of symbols from other modules that this module references. This + * list is used to tell the loader that it is OK for symbols here to be + * unresolved providing that it hasn't been told that they haven't been + * told that they are essential via a call to xf86LoaderReqSymbols() or + * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about + * unresolved symbols that are not required. + */ + +static const char *fbSymbols[] = { + "fbPictureInit", + "fbScreenInit", + NULL +}; + +static const char *wfbSymbols[] = { + "wfbPictureInit", + "wfbScreenInit", + NULL +}; + +static const char *shadowSymbols[] = { + "shadowAdd", + "shadowAlloc", + "shadowInit", + "shadowSetup", + NULL +}; + +static const char *xaaSymbols[] = { + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAInit", + "XAAGetCopyROP", + "XAAGetPatternROP", + NULL +}; + +static const char *ddcSymbols[] = { + "xf86PrintEDID", + "xf86SetDDCproperties", + NULL +}; + +#ifdef XFree86LOADER + +/* Module loader interface */ +static MODULESETUPPROTO(vermilionSetup); + +static XF86ModuleVersionInfo vermilionVersionRec = { + "vermilion", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + VERMILION_MAJOR_VERSION, VERMILION_MINOR_VERSION, VERMILION_PATCHLEVEL, + ABI_CLASS_VIDEODRV, /* This is a video driver */ + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0, 0, 0, 0} +}; + +/* + * This data is accessed by the loader. The name must be the module name + * followed by "ModuleData". + */ +_X_EXPORT XF86ModuleData vermilionModuleData = + { &vermilionVersionRec, vermilionSetup, NULL }; + +static pointer +vermilionSetup(pointer Module, pointer Options, int *ErrorMajor, + int *ErrorMinor) +{ + static Bool Initialised = FALSE; + + if (!Initialised) { + Initialised = TRUE; + xf86AddDriver(&VERMILION, Module, 0); + LoaderRefSymLists(fbSymbols, wfbSymbols, ddcSymbols, shadowSymbols, xaaSymbols, + NULL); + return (pointer) TRUE; + } + + if (ErrorMajor) + *ErrorMajor = LDR_ONCEONLY; + return (NULL); +} + +#endif + +static const OptionInfoRec * +VERMILIONAvailableOptions(int chipid, int busid) +{ + return (VERMILIONOptions); +} + +static void +VERMILIONIdentify(int flags) +{ + xf86PrintChipsets(VERMILION_NAME, "driver for VERMILION chipsets", + VERMILIONChipsets); +} + +/* + * This function is called once, at the start of the first server generation to + * do a minimal probe for supported hardware. + */ + +static Bool +VERMILIONProbe(DriverPtr drv, int flags) +{ + Bool foundScreen = FALSE; + int numDevSections, numUsed; + GDevPtr *devSections; + int *usedChips; + int i; + + /* + * Find the config file Device sections that match this + * driver, and return if there are none. + */ + if ((numDevSections = xf86MatchDevice(VERMILION_NAME, &devSections)) <= 0) + return (FALSE); + + /* PCI BUS */ + if (xf86GetPciVideoInfo()) { + numUsed = xf86MatchPciInstances(VERMILION_NAME, PCI_VENDOR_INTEL, + VERMILIONChipsets, VERMILIONPCIchipsets, + devSections, numDevSections, drv, &usedChips); + if (numUsed > 0) { + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else { + for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + + /* Allocate a ScrnInfoRec */ + if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], + VERMILIONPCIchipsets, NULL, + NULL, NULL, NULL, NULL))) { + pScrn->driverVersion = VERMILION_VERSION; + pScrn->driverName = VERMILION_DRIVER_NAME; + pScrn->name = VERMILION_NAME; + pScrn->Probe = VERMILIONProbe; + pScrn->PreInit = VERMILIONPreInit; + pScrn->ScreenInit = VERMILIONScreenInit; + pScrn->SwitchMode = VERMILIONSwitchMode; + pScrn->AdjustFrame = VERMILIONAdjustFrame; + pScrn->EnterVT = VERMILIONEnterVT; + pScrn->LeaveVT = VERMILIONLeaveVT; + pScrn->FreeScreen = VERMILIONFreeScreen; + pScrn->ValidMode = VERMILIONValidMode; + foundScreen = TRUE; + } + } + } + xfree(usedChips); + } + } + + xfree(devSections); + + return (foundScreen); +} + +static VERMILIONPtr +VERMILIONGetRec(ScrnInfoPtr pScrn) +{ + if (!pScrn->driverPrivate) + pScrn->driverPrivate = xcalloc(sizeof(VERMILIONRec), 1); + + return ((VERMILIONPtr) pScrn->driverPrivate); +} + +static void +VERMILIONFreeRec(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONGetRec(pScrn); + + xfree(pVermilion->monitor); + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +void * +VERMILIONMapPciVideo(ScrnInfoPtr pScrn, char *deviceType, + PCITAG tag, + unsigned long offset, unsigned long size, char type, int mapType) +{ + void *ptr; + + if (type) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s device had incorrect pci " + "resource type %d\n", deviceType, (int)type); + return NULL; + } + + ptr = xf86MapPciMem(pScrn->scrnIndex, mapType, tag, offset, size); + if (ptr) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mapped %s memory at " + "offset 0x%08lx size %lu\n", deviceType, offset, size); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not map %s memory at " + "offset 0x%08lx size %lu\n", deviceType, offset, size); + } + return ptr; + +} + +static int +VERMILIONKernelOpen(ScrnInfoPtr pScrn) +{ +#define PROCBUFSIZE 100 + + FILE *proc; + char buffer[PROCBUFSIZE]; + Bool found = FALSE; + char *eptr; + int device; + int ret = -1; + + proc = fopen(PROCFB, "r"); + + if (proc == NULL) + goto out; + + while (!feof(proc)) { + fgets(buffer, PROCBUFSIZE, proc); + if (strstr(buffer, KERNELNAME) == NULL) + continue; + found = TRUE; + break; + } + + if (!found) + goto out; + + device = strtol(buffer, &eptr, 10); + if (buffer == eptr) + goto out; + + ret = snprintf(buffer, PROCBUFSIZE, "%s%d", DEVFB, device); + if (ret < 0 || ret >= PROCBUFSIZE) { + ret = -1; + goto out; + } + + ret = open(buffer, O_RDWR); + if (ret < 0) { + /* If we can't get /dev/fbX, then try /dev/fb/X */ + ret = snprintf(buffer, PROCBUFSIZE, "%s/%d", DEVFB, device); + if (ret < 0 || ret >= PROCBUFSIZE) { + ret = -1; + goto out; + } + ret = open(buffer, O_RDWR); + } + + out: + fclose(proc); + return ret; +} + +void +VERMILIONUnmap(void *virtual) +{ +} + +static Bool +VERMILIONPreInitAccel(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONGetRec(pScrn); + MessageType from; + + from = + xf86GetOptValBool(pVermilion->Options, OPTION_ACCEL, + &pVermilion->accelOn) + ? X_CONFIG : X_DEFAULT; + + if (pVermilion->accelOn) { + if (!xf86LoadSubModule(pScrn, "xaa")) + return FALSE; + + xf86LoaderReqSymLists(xaaSymbols, NULL); + } + + xf86DrvMsg(pScrn->scrnIndex, from, "Acceleration %sabled\n", + pVermilion->accelOn ? "en" : "dis"); + + return TRUE; +} + +static Bool +VERMILIONPreInitShadowFB(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONGetRec(pScrn); + MessageType from; + + from = + xf86GetOptValBool(pVermilion->Options, OPTION_SHADOWFB, + &pVermilion->shadowFB) + ? X_CONFIG : X_DEFAULT; + + if (pVermilion->shadowFB) { + if (!xf86LoadSubModule(pScrn, "shadow")) + return FALSE; + + xf86LoaderReqSymLists(shadowSymbols, NULL); + } + + xf86DrvMsg(pScrn->scrnIndex, from, "Shadow framebuffer %sabled\n", + pVermilion->shadowFB ? "en" : "dis"); + + return TRUE; +} + +static int +VERMILIONAllocInstance(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + int ret; + vml_init_t arg; + vml_init_req_t *req = &arg.req; + vml_init_rep_t *rep = &arg.rep; + + req->major = VML_KI_MAJOR; + req->minor = VML_KI_MINOR; + req->pipe = 0; + req->vdc_tag.bus = pVermilion->pciInfo->bus; + req->vdc_tag.slot = pVermilion->pciInfo->device; + req->vdc_tag.function = pVermilion->pciInfo->func; + + ret = ioctl(pVermilion->fbFD, VML_INIT_DEVICE, &arg); + + if (!ret) { + pVermilion->fbSize = rep->vram_contig_size; + pScrn->memPhysBase = rep->vram_offset; + pVermilion->kernelmbx = pciTag(rep->gpu_tag.bus, + rep->gpu_tag.slot, rep->gpu_tag.function); + ErrorF("AllocInstance 0x%08lx %ld\n", pScrn->memPhysBase, pVermilion->fbSize); + } + + return ret; +} + +/* + * This function is called once for each screen at the start of the first + * server generation to initialise the screen for all server generations. + */ +static Bool +VERMILIONPreInit(ScrnInfoPtr pScrn, int flags) +{ + VERMILIONPtr pVermilion; + VERMILIONSys *sys; + DisplayModePtr pMode; + Gamma gzeros = { 0.0, 0.0, 0.0 }; + rgb rzeros = { 0, 0, 0 }; + pointer pDDCModule; + int i; + int ret; + int mbxCount; + MessageType from; + unsigned ssVendor, ssDevice; + const char *ssName, *fbmod, **fbsym; + + ClockRangePtr clockRanges; + + if (flags & PROBE_DETECT) + return (FALSE); + + pVermilion = VERMILIONGetRec(pScrn); + pVermilion->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + + if (pVermilion->pEnt->location.type == BUS_PCI) { + pVermilion->pciInfo = + xf86GetPciInfoForEntity(pVermilion->pEnt->index); + pVermilion->pciTag = + pciTag(pVermilion->pciInfo->bus, pVermilion->pciInfo->device, + pVermilion->pciInfo->func); + } + + pVermilion->fbFD = VERMILIONKernelOpen(pScrn); + + if (pVermilion->fbFD < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to open the %s kernel fb driver. Make sure it is loaded.\n", + KERNELNAME); + return FALSE; + } + + ret = VERMILIONAllocInstance(pScrn); + + if (ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate a vermilion device: %s. Check kernel output.\n", + strerror(errno)); + return FALSE; + } + + pVermilion->sys = sys = VERMILIONCreateSys(pScrn); + if (!sys) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to determine system type.\n"); + return FALSE; + } + sys->subSys(sys, &ssName, &ssVendor, &ssDevice); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Subsystem Vendor 0x%04x Device 0x%04x.\n", ssVendor, ssDevice); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "This is a %s board.\n", ssName); + + pVermilion->device = xf86GetDevFromEntity(pScrn->entityList[0], + pScrn->entityInstanceList[0]); + + mbxCount = 0; + do { + pVermilion->mbx = xf86FindPciDeviceVendor(PCI_VENDOR_INTEL, + PCI_CHIP_VM_MBX, mbxCount, NULL); + + /* + * Check that the mbx device is the one the kernel allocated for us. + */ + + if (pVermilion->mbx && + pciTag(pVermilion->mbx->bus, + pVermilion->mbx->device, + pVermilion->mbx->func) == pVermilion->kernelmbx) + break; + + mbxCount++; + } while (pVermilion->mbx); + + if (!pVermilion->mbx) { + ErrorF("Could not find MBX device\n"); + return FALSE; + } + + if (!xf86SetDepthBpp(pScrn, 15, 0, 0, Support32bppFb)) { + return (FALSE); + } + if (pScrn->depth != 15 && pScrn->depth != 24) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Invalid depth %d, only 15 and 24 supported\n", pScrn->depth); + return (FALSE); + } + xf86PrintDepthBpp(pScrn); + + if (pScrn->depth == 15) { + fbmod = "wfb"; + fbsym = wfbSymbols; + } else { + fbmod = "fb"; + fbsym = fbSymbols; + } + + /* Load (w)fb module */ + if (!xf86LoadSubModule(pScrn, fbmod)) + return (FALSE); + + xf86LoaderReqSymLists(fbsym, NULL); + + pScrn->chipset = "vermilion"; + pScrn->monitor = pScrn->confScreen->monitor; + pScrn->rgbBits = 8; + pScrn->videoRam = pVermilion->fbSize / 1024; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Linear framebuffer at 0x%lX\n", + (unsigned long)pScrn->memPhysBase); + + if (xf86RegisterResources(pVermilion->pEnt->index, NULL, ResExclusive)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "xf86RegisterResources() found resource conflicts\n"); + return FALSE; + } + + /* color weight */ + if (!xf86SetWeight(pScrn, rzeros, rzeros)) { + return (FALSE); + } + /* visual init */ + if (!xf86SetDefaultVisual(pScrn, -1)) { + return (FALSE); + } + + /* We can't do this until we have a + * pScrn->display. */ + xf86CollectOptions(pScrn, NULL); + if (!(pVermilion->Options = xalloc(sizeof(VERMILIONOptions)))) + return (FALSE); + + memcpy(pVermilion->Options, VERMILIONOptions, sizeof(VERMILIONOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pVermilion->Options); + + pVermilion->shadowFB = FALSE; + pVermilion->accelOn = TRUE; + + if (!VERMILIONPreInitShadowFB(pScrn)) + return (FALSE); + + if (!pVermilion->shadowFB && !VERMILIONPreInitAccel(pScrn)) + return (FALSE); + + /* + * Check panel option. + */ + + pVermilion->panel = sys->panel(sys); + from = xf86GetOptValInteger(pVermilion->Options, OPTION_PANELTYPE, + &pVermilion->panel) + ? X_CONFIG : X_DEFAULT; + + if (pVermilion->panel >= VERMILIONNumPanels) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unknown panel type %d\n", pVermilion->panel); + return FALSE; + } + pVermilion->usePanel = (pVermilion->panel >= 0); + if (pVermilion->usePanel) { + xf86DrvMsg(pScrn->scrnIndex, from, + "Using panel type %d, which is a %s.\n", + pVermilion->panel, VERMILIONPanels[pVermilion->panel]->name); + } else { + xf86DrvMsg(pScrn->scrnIndex, from, "Not using panel\n"); + } + + pScrn->progClock = sys->progClock(sys); + + if (!pScrn->progClock) + sys->clocks(sys, &pScrn->numClocks, pScrn->clock); + + pVermilion->fusedClockIndex = -1; + from = xf86GetOptValInteger(pVermilion->Options, OPTION_FUSEDCLOCK, + &pVermilion->fusedClockIndex) + ? X_CONFIG : X_DEFAULT; + + if (pVermilion->panel >= pScrn->numClocks) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Unknown fused clock index %d\n", pVermilion->fusedClockIndex); + return FALSE; + } + pVermilion->fusedClock = (pVermilion->fusedClockIndex >= 0); + if (pVermilion->fusedClock) { + xf86DrvMsg(pScrn->scrnIndex, from, + "Fused dotclock index %d which is %d kHz.\n", + pVermilion->fusedClockIndex, + pScrn->clock[pVermilion->fusedClockIndex]); + } + + pVermilion->debug = FALSE; + from = + xf86GetOptValBool(pVermilion->Options, OPTION_DEBUG, + &pVermilion->debug) + ? X_CONFIG : X_DEFAULT; + + xf86DrvMsg(pScrn->scrnIndex, from, + "Modesetting debugging printout is %sabled.\n", + pVermilion->debug ? "en" : "dis"); + + xf86SetGamma(pScrn, gzeros); + + /* Load ddc module */ + if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) { +#if 0 + if ((pVermilion->monitor = + vbeDoEDID(pVermilion->pVbe, pDDCModule)) != NULL) { + xf86PrintEDID(pVermilion->monitor); + } +#endif + xf86UnloadSubModule(pDDCModule); + } + + if ((pScrn->monitor->DDC = pVermilion->monitor) != NULL) + xf86SetDDCproperties(pScrn, pVermilion->monitor); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Searching for matching VERMILION mode(s):\n"); + + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + sys->clockRanges(sys, &clockRanges->minClock, &clockRanges->maxClock); + clockRanges->clockIndex = -1; + clockRanges->interlaceAllowed = FALSE; + clockRanges->doubleScanAllowed = FALSE; + pVermilion->cpp = pScrn->bitsPerPixel >> 3; + pScrn->xInc = 1; + + if (pVermilion->fusedClock) { + pScrn->clock[0] = pScrn->clock[pVermilion->fusedClockIndex]; + pScrn->numClocks = 1; + } + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, + clockRanges, NULL, 0, 2048, 64 << 3, 0, 2048, + pScrn->display->virtualX, + pScrn->display->virtualY, pScrn->videoRam * 1024, + pVermilion->usePanel ? LOOKUP_CLOSEST_CLOCK : LOOKUP_BEST_REFRESH); + + if (i <= 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes\n"); + return (FALSE); + } + + pVermilion->stride = pVermilion->cpp * pScrn->displayWidth; + xf86PruneDriverModes(pScrn); + + pMode = pScrn->modes; + pScrn->currentMode = pScrn->modes; + xf86PrintModes(pScrn); + + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); + + if (pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes\n"); + return (FALSE); + } + + return (TRUE); +} + +void +VERMILIONUpdatePackedDepth15(ScreenPtr pScreen, shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS(damage); + BoxPtr pbox = REGION_RECTS(damage); + FbBits *shaBase, *shaLine, *sha; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + FbBits *winBase = NULL, *win; + CARD32 winSize; + + fbGetDrawable(&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, + shaYoff); + while (nbox--) { + x = pbox->x1 * shaBpp; + y = pbox->y1; + w = (pbox->x2 - pbox->x1) * shaBpp; + h = pbox->y2 - pbox->y1; + + scrLine = (x >> FB_SHIFT); + shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); + + x &= FB_MASK; + w = (w + x + FB_MASK) >> FB_SHIFT; + + while (h--) { + winSize = 0; + scrBase = 0; + width = w; + scr = scrLine; + sha = shaLine; + while (width) { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) { + winBase = (FbBits *) (*pBuf->window) (pScreen, + y, + scr * sizeof(FbBits), + SHADOW_WINDOW_WRITE, &winSize, pBuf->closure); + if (!winBase) + return; + scrBase = scr; + winSize /= sizeof(FbBits); + i = winSize; + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; + /* Here we set the high bit on upload for depth 15 because + * the hardware requires it. - AlanH. + */ + while (i--) + *win++ = 0x80008000 | *sha++; + } + shaLine += shaStride; + y++; + } + pbox++; + } +} + +void +VERMILIONUpdatePackedDepth24(ScreenPtr pScreen, shadowBufPtr pBuf) +{ + RegionPtr damage = &pBuf->damage; + PixmapPtr pShadow = pBuf->pPixmap; + int nbox = REGION_NUM_RECTS(damage); + BoxPtr pbox = REGION_RECTS(damage); + FbBits *shaBase, *shaLine, *sha; + FbStride shaStride; + int scrBase, scrLine, scr; + int shaBpp; + int shaXoff, shaYoff; /* XXX assumed to be zero */ + int x, y, w, h, width; + int i; + FbBits *winBase = NULL, *win; + CARD32 winSize; + + fbGetDrawable(&pShadow->drawable, shaBase, shaStride, shaBpp, shaXoff, + shaYoff); + while (nbox--) { + x = pbox->x1 * shaBpp; + y = pbox->y1; + w = (pbox->x2 - pbox->x1) * shaBpp; + h = pbox->y2 - pbox->y1; + + scrLine = (x >> FB_SHIFT); + shaLine = shaBase + y * shaStride + (x >> FB_SHIFT); + + x &= FB_MASK; + w = (w + x + FB_MASK) >> FB_SHIFT; + + while (h--) { + winSize = 0; + scrBase = 0; + width = w; + scr = scrLine; + sha = shaLine; + while (width) { + /* how much remains in this window */ + i = scrBase + winSize - scr; + if (i <= 0 || scr < scrBase) { + winBase = (FbBits *) (*pBuf->window) (pScreen, + y, + scr * sizeof(FbBits), + SHADOW_WINDOW_WRITE, &winSize, pBuf->closure); + if (!winBase) + return; + scrBase = scr; + winSize /= sizeof(FbBits); + i = winSize; + } + win = winBase + (scr - scrBase); + if (i > width) + i = width; + width -= i; + scr += i; + while (i--) + *win++ = *sha++; + } + shaLine += shaStride; + y++; + } + pbox++; + } +} + +static void * +VERMILIONWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, + CARD32 * size, void *closure) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VERMILIONPtr pVermilion = VERMILIONGetRec(pScrn); + + if (!pScrn->vtSema) + return NULL; + + *size = pVermilion->stride; + + return ((CARD8 *) pVermilion->fbMap + row * (*size) + offset); +} + +#if X_BYTE_ORDER == X_BIG_ENDIAN +#error VERMILIONReadMemory and VERMILIONWriteMemory only work on little endian +#endif + +static FbBits +VERMILIONReadMemory(const void *src, int size) +{ + FbBits bits = 0; + + memcpy(&bits, src, size); + + return bits; +} + +static void +VERMILIONWriteMemoryPassthru(void *dst, FbBits value, int size) +{ + memcpy(dst, &value, size); +} + +static void +VERMILIONWriteMemorySetAlpha(void *dst, FbBits value, int size) +{ + switch (size) { + case 4: + value |= 0x80008000; + break; + case 3: + case 2: + value |= 0x8000; + case 1: + break; + default: + FatalError("Unsupported size %d in %s", size, __func__); + } + + memcpy(dst, &value, size); +} + +static void +VERMILIONSetupWrap(ReadMemoryProcPtr *pRead, WriteMemoryProcPtr *pWrite, + DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum]; + VERMILIONPtr pVermilion = VERMILIONGetRec(pScrn); + PixmapPtr pPixmap; + + if (pDraw->type == DRAWABLE_WINDOW) + pPixmap = pScreen->GetWindowPixmap((WindowPtr)pDraw); + else + pPixmap = (PixmapPtr)pDraw; + + if (pScrn->depth == 15 && pPixmap->devPrivate.ptr >= pVermilion->fbMap && + (char*)pPixmap->devPrivate.ptr < ((char*)pVermilion->fbMap + + pVermilion->fbSize)) { + *pWrite = VERMILIONWriteMemorySetAlpha; + } else { + *pWrite = VERMILIONWriteMemoryPassthru; + } + + *pRead = VERMILIONReadMemory; +} + +static void +VERMILIONFinishWrap(DrawablePtr pDraw) +{ +} + +static Bool +VERMILIONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VERMILIONPtr pVermilion = VERMILIONGetRec(pScrn); + VisualPtr visual; + int flags; + char *fbstart; + VERMILIONSys *sys = pVermilion->sys; + + if (!VERMILIONMapMem(pScrn)) { + return (FALSE); + } + + /* save current video state */ + VERMILIONSave(pScrn); + + /* set the viewport */ + VERMILIONAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* Clear framebuffer contents before setting initial mode to prevent garbage + * or even screen contents from a previous session from being visible. + */ + + if (pScrn->bitsPerPixel == 32) { + memset(pVermilion->fbMap, 0, pScrn->virtualY * pVermilion->stride); + } else { + /* For 16 bpp, make sure the alpha bit is set. Gets trashed later on + * unfortunately. + */ + int y = pScrn->virtualY; + + while (y--) { + int x; + CARD32 *pixels = (CARD32 *) ((char *)pVermilion->fbMap + + y * pVermilion->stride); + + for (x = pScrn->virtualX; x; x -= 2, pixels++) + *pixels = 0x80008000; + } + } + + if (pVermilion->usePanel) { + sys->panelOn(sys); + } + + /* set first video mode */ + if (!VERMILIONSetMode(pScrn, pScrn->currentMode)) + return (FALSE); + + /* Blank the screen for aesthetic reasons. */ + VERMILIONSaveScreen(pScreen, SCREEN_SAVER_ON); + + /* mi layer */ + miClearVisualTypes(); + if (!xf86SetDefaultVisual(pScrn, -1)) + return (FALSE); + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, + pScrn->rgbBits, TrueColor)) + return (FALSE); + if (!miSetPixmapDepths()) + return (FALSE); + + /* shadowfb */ + if (pVermilion->shadowFB) { + if ((pVermilion->shadowmem = + shadowAlloc(pScrn->displayWidth, pScrn->virtualY, + pScrn->bitsPerPixel)) == NULL) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Allocation of shadow memory failed\n"); + return FALSE; + } + fbstart = pVermilion->shadowmem; + } else { + fbstart = pVermilion->fbMap; + } + + if (!(pScrn->depth == 15 ? + wfbScreenInit(pScreen, fbstart, pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, + pScrn->bitsPerPixel, VERMILIONSetupWrap, + VERMILIONFinishWrap) : + fbScreenInit(pScreen, fbstart, pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, + pScrn->bitsPerPixel))) + return (FALSE); + + /* 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; + } + } + + /* must be after RGB ordering fixed */ + if (pScrn->depth == 15) + wfbPictureInit(pScreen, 0, 0); + else + fbPictureInit(pScreen, 0, 0); + + if (pVermilion->shadowFB && + (!shadowSetup(pScreen) || !shadowAdd(pScreen, NULL, + pScrn->depth == + 15 ? VERMILIONUpdatePackedDepth15 : + VERMILIONUpdatePackedDepth24, VERMILIONWindowLinear, 0, + NULL))) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Shadow framebuffer initialization failed.\n"); + return FALSE; + } + + xf86SetBlackWhitePixels(pScreen); + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + + /* Enable acceleration */ + if (!pVermilion->shadowFB && pVermilion->accelOn) { + if (!VERMILIONAccelInit(pScreen)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Acceleration initialization failed\n"); + pVermilion->accelOn = FALSE; + } + } + + /* software cursor */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* colormap */ + if (!miCreateDefColormap(pScreen)) + return (FALSE); + + flags = CMAP_RELOAD_ON_MODE_SWITCH; + + if (!xf86HandleColormaps(pScreen, 256, 8, + VERMILIONLoadPalette, NULL, flags)) + return (FALSE); + + pVermilion->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = VERMILIONCloseScreen; + pScreen->SaveScreen = VERMILIONSaveScreen; + + xf86DPMSInit(pScreen, VERMILIONDisplayPowerManagementSet, 0); + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + + return (TRUE); +} + +static Bool +VERMILIONEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + VERMILIONSys *sys = pVermilion->sys; + + VERMILIONAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + if (!VERMILIONSetMode(pScrn, pScrn->currentMode)) + return FALSE; + + /* Power up the panel */ + if (pVermilion->usePanel) { + sys->panelOn(sys); + } + + return TRUE; +} + +static void +VERMILIONLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + if (pVermilion->accel) + (*pVermilion->accel->Sync) (pScrn); + + /* clear the framebuffer when we switch */ + memset(pVermilion->fbMap, 0, pScrn->virtualY * pVermilion->stride); + + VERMILIONDisablePipe(pScrn); + VERMILIONRestore(pScrn); + + pScrn->vtSema = FALSE; +} + +static Bool +VERMILIONCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + if (pVermilion->accel) { + (*pVermilion->accel->Sync) (pScrn); + XAADestroyInfoRec(pVermilion->accel); + pVermilion->accel = NULL; + } + + if (pScrn->vtSema) { + VERMILIONDisablePipe(pScrn); + VERMILIONRestore(pScrn); + VERMILIONUnmapMem(pScrn); + } + pScrn->vtSema = FALSE; + + pScreen->CloseScreen = pVermilion->CloseScreen; + return pScreen->CloseScreen(scrnIndex, pScreen); +} + +static Bool +VERMILIONSwitchMode(int scrnIndex, DisplayModePtr pMode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + if (pVermilion->accel) + (*pVermilion->accel->Sync) (pScrn); + + return VERMILIONSetMode(xf86Screens[scrnIndex], pMode); +} + +/* Set a graphics mode */ +static Bool +VERMILIONSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) +{ + pScrn->vtSema = VERMILIONDoSetMode(pScrn, pMode, 1); + return pScrn->vtSema; +} + +static void +VERMILIONAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + VERMILIONSetGraphicsOffset(pScrn, x, y); + pVermilion->x = x; + pVermilion->y = y; +} + +static void +VERMILIONFreeScreen(int scrnIndex, int flags) +{ + VERMILIONFreeRec(xf86Screens[scrnIndex]); +} + +static Bool +VERMILIONMapMem(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + if (pVermilion->fbMap != NULL) + return (TRUE); + + pVermilion->mbxRegsBase = NULL; + pVermilion->vdcRegsBase = NULL; + + pVermilion->fbMap = mmap(NULL, pVermilion->fbSize, PROT_READ | PROT_WRITE, + MAP_SHARED, pVermilion->fbFD, 0); + + if (!pVermilion->fbMap || pVermilion->fbMap == MAP_FAILED) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to map video memory\n"); + return FALSE; + } + + pVermilion->mbxSize = 1 << pVermilion->mbx->size[0]; + pVermilion->mbxRegsBase = VERMILIONMapPciVideo(pScrn, "MBX", + pciTag(pVermilion->mbx->bus, + pVermilion->mbx->device, + pVermilion->mbx->func), + pVermilion->mbx->memBase[0], + pVermilion->mbxSize, pVermilion->mbx->type[0], VIDMEM_MMIO); + + if (!pVermilion->mbxRegsBase) { + VERMILIONUnmapMem(pScrn); + return FALSE; + } + + pVermilion->vdcSize = 1 << pVermilion->pciInfo->size[0]; + pVermilion->vdcRegsBase = VERMILIONMapPciVideo(pScrn, "Video Controller", + pVermilion->pciTag, + pVermilion->pciInfo->memBase[0], + pVermilion->vdcSize, pVermilion->pciInfo->type[0], VIDMEM_MMIO); + + if (!pVermilion->vdcRegsBase) { + VERMILIONUnmapMem(pScrn); + return FALSE; + } + + return TRUE; +} + +static void +VERMILIONUnmapMem(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + if (pVermilion->fbMap != NULL) { + munmap(pVermilion->fbMap, pVermilion->fbSize); + pVermilion->fbMap = NULL; + } + + if (pVermilion->mbxRegsBase != NULL) { + xf86UnMapVidMem(pScrn->scrnIndex, pVermilion->mbxRegsBase, + pVermilion->mbxSize); + pVermilion->mbxRegsBase = NULL; + } + + if (pVermilion->vdcRegsBase != NULL) { + xf86UnMapVidMem(pScrn->scrnIndex, pVermilion->vdcRegsBase, + pVermilion->vdcSize); + pVermilion->vdcRegsBase = NULL; + } +} + +static void +VERMILIONLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO * colors, VisualPtr pVisual) +{ + /* + * Do we ever use this function? + */ +} + +static Bool +VERMILIONSaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + Bool on = xf86IsUnblank(mode); + VERMILIONSys *sys = pVermilion->sys; + + if (on) + SetTimeSinceLastInputEvent(); + + if (pScrn->vtSema) { + VERMILIONBlankScreen(pScrn, !on); + /* Power up the panel */ + if (pVermilion->usePanel) { + if (on) { + sys->backlightOn(sys); + } else { + sys->backlightOff(sys); + } + } + } + + return (TRUE); +} + +Bool +VERMILIONSave(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + VERMILIONSys *sys = pVermilion->sys; + + sys->save(sys); + return (TRUE); +} + +Bool +VERMILIONRestore(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + VERMILIONSys *sys = pVermilion->sys; + + sys->restore(sys); + return (TRUE); +} + +static void +VERMILIONDisplayPowerManagementSet(ScrnInfoPtr pScrn, int mode, int flags) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + VERMILIONSys *sys = pVermilion->sys; + + if (!pScrn->vtSema) + return; + + switch (mode) { + case DPMSModeOn: + if (pVermilion->usePanel) { + sys->panelOn(sys); + sys->backlightOn(sys); + } + VERMILIONDoSetMode(pScrn, &pVermilion->curMode, 1); + /* Screen: On; HSync: On, VSync: On */ + break; + case DPMSModeStandby: + if (pVermilion->usePanel) { + sys->backlightOff(sys); + } + /* Screen: Off; HSync: Off, VSync: On -- Not Supported */ + break; + case DPMSModeSuspend: + if (pVermilion->usePanel) { + sys->backlightOff(sys); + sys->panelOff(sys); + } + /* Screen: Off; HSync: On, VSync: Off -- Not Supported */ + break; + case DPMSModeOff: + if (pVermilion->usePanel) { + sys->backlightOff(sys); + sys->panelOff(sys); + } + VERMILIONDisablePipe(pScrn); + /* Screen: Off; HSync: Off, VSync: Off */ + break; + } +} diff --git a/src/vermilion.h b/src/vermilion.h new file mode 100644 index 0000000..ba222cd --- /dev/null +++ b/src/vermilion.h @@ -0,0 +1,223 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: + * Michel Dänzer <michel-at-tungstengraphics-dot-com> + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * Alan Hourihane <alanh-at-tungstengraphics-dot-com> + */ + +#ifndef _VERMILION_H_ +#define _VERMILION_H_ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" + +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +#include "vgaHW.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* VBE/DDC support */ +#include "vbe.h" +#include "vbeModes.h" +#include "xf86DDC.h" + +/* ShadowFB support */ +#include "shadow.h" + +/* Int 10 support */ +#include "xf86int10.h" + +/* bank switching */ +#include "mibank.h" + +/* Dga definitions */ +#include "dgaproc.h" + +#include "xf86Resources.h" +#include "xf86RAC.h" + +#include "fb.h" +#define wfbPictureInit fbPictureInit + +#include "xaa.h" +#include "vermilion_sys.h" + +#define VERMILION_VERSION 4000 +#define VERMILION_NAME "VERMILION" +#define VERMILION_DRIVER_NAME "vermilion" +#define VERMILION_MAJOR_VERSION 1 +#define VERMILION_MINOR_VERSION 0 +#define VERMILION_PATCHLEVEL 0 + + /*XXX*/ typedef struct _VERMILIONRec +{ + EntityInfoPtr pEnt; + GDevPtr device; + pciVideoPtr pciInfo; + PCITAG pciTag; + xf86MonPtr monitor; + CloseScreenProcPtr CloseScreen; + OptionInfoPtr Options; + + IOADDRESS ioBase; + pciVideoPtr mbx; + int fbFD; + +/* + * Map + */ + void *fbMap; + CARD32 *vdcRegsBase; + CARD32 *mbxRegsBase; + unsigned long fbSize; + unsigned long mbxSize; + unsigned long vdcSize; + unsigned long mchSize; + +/* + * Mode info + */ + + int x; + int y; + int cpp; + unsigned stride; + DisplayModeRec curMode; +/* + * Panel + */ + Bool usePanel; + int panel; + +/* + * System info + */ + VERMILIONSys *sys; + PCITAG kernelmbx; + Bool fusedClock; + int fusedClockIndex; + +/* + * Acceleration + */ + Bool accelOn; + XAAInfoRecPtr accel; + CARD32 mbxBpp; + CARD32 mbxFBDevAddr; + CARD32 *slavePort; + CARD32 FifoSlots; + volatile CARD32 *mbxSyncMap; + CARD32 mbxSyncDevAddr; + CARD32 ROP; + CARD32 transEnable; + CARD32 fillColour; + CARD32 dir; + +/* + * ShadowFB + */ + char *shadowmem; + Bool shadowFB; + +/* + * Debug modesetting + */ + Bool debug; + +} VERMILIONRec, *VERMILIONPtr; + +typedef struct _VERMILIONPanelRec +{ + char *name; + int clockMax; /* kHz */ + int clockMin; /* kHz */ + int hActMax; /* Clocks */ + int hActMin; /* Clocks */ + int hTotMax; /* Clocks */ + int hTotMin; /* Clocks */ + int vActMax; /* Lines */ + int vActMin; /* Lines */ + int vTotMax; /* Lines */ + int vTotMin; /* Lines */ + int hPerMax; /* ns */ + int hPerMin; /* ns */ + float gamma; /* [] */ +} VERMILIONPanelRec, *VERMILIONPanelPtr; + +#define VERMILIONPTR(_pScrn) ((VERMILIONPtr) (_pScrn)->driverPrivate) +#define ALIGN_TO(_a, _b) (((_a) + (_b) - 1) & ~((_b) - 1)) + +/* + * vermilion_accel.c + */ + +extern Bool VERMILIONAccelInit(ScreenPtr pScreen); + +/* + * vermilion_mode.c + */ + +extern Bool +VERMILIONDoSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, + Bool plane_enable); +extern ModeStatus +VERMILIONValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, + int flags); +extern void VERMILIONSetGraphicsOffset(ScrnInfoPtr pScrn, int x, int y); +extern int VERMILIONBlankScreen(ScrnInfoPtr pScrn, Bool blank); +extern int VERMILIONDimScreen(ScrnInfoPtr pScrn, CARD8 level); +extern void VERMILIONDisablePipe(ScrnInfoPtr pScrn); +void VERMILIONWaitForVblank(ScrnInfoPtr pScrn); + +/* + * vermilion_panels.c + */ + +extern VERMILIONPanelPtr VERMILIONPanels[]; +extern int VERMILIONNumPanels; + +/* + * vermilion.c + */ + +extern void * VERMILIONMapPciVideo(ScrnInfoPtr pScrn, char *deviceType, + PCITAG tag, unsigned long offset, + unsigned long size, char type, int mapType); + +#endif /* _VERMILION_H_ */ diff --git a/src/vermilion_accel.c b/src/vermilion_accel.c new file mode 100644 index 0000000..14b835d --- /dev/null +++ b/src/vermilion_accel.c @@ -0,0 +1,255 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Alan Hourihane <alanh@tungstengraphics.com> + * Michel Dänzer <michel@tungstengraphics.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "miline.h" + +#include "vermilion.h" +#include "vermilion_mbx.h" + +#include "xaarop.h" + +static void mbxSync(ScrnInfoRec * pScrn); +static void mbxSetupForFillRectSolid(ScrnInfoRec * pScrn, int color, + int rop, unsigned int planemask); +static void mbxSubsequentFillRectSolid(ScrnInfoRec * pScrn, int x, + int y, int w, int h); +static void mbxSubsequentScreenToScreenCopy(ScrnInfoRec * pScrn, + int x1, int y1, int x2, int y2, int w, int h); +static void mbxSetupForScreenToScreenCopy(ScrnInfoRec * pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color); + +#define MBX_SYNC_MAP_SIZE 4 + +Bool +VERMILIONAccelInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + XAAInfoRecPtr infoPtr; + BoxRec AvailFBArea; + + switch (pScrn->depth) { + case 15: + pVermilion->mbxBpp = MBX2D_SRC_555RGB; + break; + case 24: + pVermilion->mbxBpp = MBX2D_SRC_8888ARGB; + break; + default: + return FALSE; + } + + pVermilion->accel = infoPtr = XAACreateInfoRec(); + if (!infoPtr) + return FALSE; + + infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER; + + infoPtr->Sync = mbxSync; + + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = mbxSetupForFillRectSolid; + infoPtr->SubsequentSolidFillRect = mbxSubsequentFillRectSolid; + + infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK; + infoPtr->SetupForScreenToScreenCopy = mbxSetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = mbxSubsequentScreenToScreenCopy; + + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = + (pVermilion->fbSize - MBX_SYNC_MAP_SIZE) / pVermilion->stride; + + if (AvailFBArea.y2 > 4095) + AvailFBArea.y2 = 4095; + + xf86InitFBManager(pScreen, &AvailFBArea); + + if (!XAAInit(pScreen, infoPtr)) + return FALSE; + + pVermilion->mbxFBDevAddr = pScrn->memPhysBase; + + /* Reserve DWORD at the end of the framebuffer for mbxSync() */ + pVermilion->mbxSyncDevAddr = pVermilion->mbxFBDevAddr + + pVermilion->fbSize - MBX_SYNC_MAP_SIZE; + pVermilion->mbxSyncMap = (CARD32 *) ((char *)pVermilion->fbMap + + pVermilion->fbSize - MBX_SYNC_MAP_SIZE); + + pVermilion->slavePort = (CARD32 *) ((char *)pVermilion->mbxRegsBase + + MBX_SP_2D_SYS_PHYS_OFFSET); + + return TRUE; +} + +static void +mbxSync(ScrnInfoRec * pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + unsigned int sync_val; + volatile CARD32 *fb_sync_val; + CARD32 auBltPacket[7]; + + fb_sync_val = pVermilion->mbxSyncMap; + sync_val = ((*fb_sync_val) + 1) % 65536; + + WAITFIFO(7); + + auBltPacket[0] = MBX2D_DST_CTRL_BH | MBX2D_SRC_8888ARGB; + auBltPacket[1] = pVermilion->mbxSyncDevAddr; + auBltPacket[2] = MBX2D_BLIT_BH | ROP_P << 8 | ROP_P; + auBltPacket[3] = sync_val; + auBltPacket[4] = (0 & 0xffff) << 16 | (0 & 0xffff); + auBltPacket[5] = (1 & 0xffff) << 16 | (1 & 0xffff); + auBltPacket[6] = MBX2D_FENCE_BH; + + WRITESLAVEPORTDATA(7); + + while (*fb_sync_val != sync_val) { +#if 0 + ErrorF("WAITING 0x%x 0x%x\n", *fb_sync_val, sync_val); +#endif + usleep(10); + } +} + +static void +mbxSetupForScreenToScreenCopy(ScrnInfoRec * pScrn, + int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + CARD32 auBltPacket[4]; + + pVermilion->transEnable = 0; + + pVermilion->ROP = XAAGetCopyROP(rop); + + pVermilion->dir = MBX2D_TEXTCOPY_TL2BR; + if (xdir < 0) + pVermilion->dir |= MBX2D_TEXTCOPY_TR2BL; + if (ydir < 0) + pVermilion->dir |= MBX2D_TEXTCOPY_BL2TR; + + if (transparency_color != -1) { + pVermilion->transEnable = MBX2D_SRCCK_REJECT; + + WAITFIFO(3); + + auBltPacket[0] = MBX2D_CTRL_BH | MBX2D_SRCCK_CTRL; + if (pScrn->depth == 15) + auBltPacket[1] = transparency_color | transparency_color << 16; + else + auBltPacket[1] = transparency_color; + auBltPacket[2] = 0xffffffff; + + WRITESLAVEPORTDATA(3); + } + + WAITFIFO(4); + + auBltPacket[0] = MBX2D_SRC_CTRL_BH | MBX2D_SRC_FBMEM | pVermilion->mbxBpp; + auBltPacket[0] |= pVermilion->stride; + auBltPacket[1] = pVermilion->mbxFBDevAddr; + auBltPacket[2] = MBX2D_DST_CTRL_BH | pVermilion->mbxBpp; + auBltPacket[2] |= pVermilion->stride; + auBltPacket[3] = pVermilion->mbxFBDevAddr; + WRITESLAVEPORTDATA(4); +} + +static void +mbxSubsequentScreenToScreenCopy(ScrnInfoRec * pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + CARD32 auBltPacket[5]; + + WAITFIFO(5); + + auBltPacket[0] = MBX2D_SRC_OFF_BH | (x1 & 0xffff) << 14 | (y1 & 0xffff); + auBltPacket[1] = MBX2D_BLIT_BH | pVermilion->transEnable | + MBX2D_USE_PAT | pVermilion->dir | + (pVermilion->ROP & 0xff) << 8 | (pVermilion->ROP & 0xff); + auBltPacket[2] = (x2 & 0xffff) << 16 | (y2 & 0xffff); + auBltPacket[3] = ((x2 + w) & 0xffff) << 16 | ((y2 + h) & 0xffff); + auBltPacket[4] = MBX2D_FENCE_BH; + + WRITESLAVEPORTDATA(5); +} + +static void +mbxSetupForFillRectSolid(ScrnInfoRec * pScrn, int color, + int rop, unsigned int planemask) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + CARD32 auBltPacket[2]; + + pVermilion->ROP = XAAGetPatternROP(rop); + + if (pScrn->depth == 15) { + color |= 0x8000; + } + + pVermilion->fillColour = color; + + WAITFIFO(2); + + auBltPacket[0] = MBX2D_DST_CTRL_BH | pVermilion->mbxBpp; + auBltPacket[0] |= pVermilion->stride; + auBltPacket[1] = pVermilion->mbxFBDevAddr; + WRITESLAVEPORTDATA(2); +} + +static void +mbxSubsequentFillRectSolid(ScrnInfoRec * pScrn, int x, int y, int w, int h) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + CARD32 auBltPacket[5]; + + WAITFIFO(5); + + auBltPacket[0] = MBX2D_BLIT_BH | + (pVermilion->ROP & 0xff) << 8 | (pVermilion->ROP & 0xff); + auBltPacket[1] = pVermilion->fillColour; + auBltPacket[2] = (x & 0xffff) << 16 | (y & 0xffff); + auBltPacket[3] = ((x + w) & 0xffff) << 16 | ((y + h) & 0xffff); + auBltPacket[4] = MBX2D_FENCE_BH; + WRITESLAVEPORTDATA(5); +} diff --git a/src/vermilion_kernel.h b/src/vermilion_kernel.h new file mode 100644 index 0000000..071de51 --- /dev/null +++ b/src/vermilion_kernel.h @@ -0,0 +1,81 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: + * Michel Dänzer <michel-at-tungstengraphics-dot-com> + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * Alan Hourihane <alanh-at-tungstengraphics-dot-com> + */ +#ifndef _VERMILION_KERNEL_H_ +#define _VERMILION_KERNEL_H_ + +#ifdef __KERNEL__ +#include<linux/ioctl.h> +#include<linux/types.h> +#else +#include <stdint.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#define __u64 uint64_t +#endif + +#define VML_KI_MAJOR 2 +#define VML_KI_MINOR 0 + +typedef struct { + unsigned bus; + unsigned slot; + unsigned function; +} vml_pci_tag; + +typedef struct { + vml_pci_tag gpu_tag; + __u64 vram_offset; + __u64 vram_contig_size; + __u64 vram_total_size; +} vml_init_rep_t; + +typedef struct { + unsigned major; + unsigned minor; + vml_pci_tag vdc_tag; + unsigned pipe; +} vml_init_req_t; + +typedef union { + vml_init_req_t req; + vml_init_rep_t rep; +} vml_init_t; + +#define VML_IOC_MAGIC 0xD0 +#define VML_INIT_DEVICE _IOWR(VML_IOC_MAGIC, 0, vml_init_t) +#define VML_IOC_MAXNR 0 + +#endif diff --git a/src/vermilion_mbx.h b/src/vermilion_mbx.h new file mode 100644 index 0000000..4859455 --- /dev/null +++ b/src/vermilion_mbx.h @@ -0,0 +1,117 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Alan Hourihane <alanh@tungstengraphics.com> + * Michel Dänzer <michel@tungstengraphics.com> + */ + +#ifndef _VERMILION_MBX_H_ +#define _VERMILION_MBX_H_ + +#ifndef XFree86LOADER +#include <sys/mman.h> +#endif + +#define ReadHWReg(ui32Offset) *(volatile CARD32*)((char*)pVermilion->mbxRegsBase+ui32Offset) + +#define MBX1_GLOBREG_INT_STATUS 0x012C +#define MBX1_INT_TA_FREEVCOUNT_MASK 0x00FF0000 +#define MBX1_INT_TA_FREEVCOUNT_SHIFT 16 + +/* + MBX Slave Port's offset into the register aperture +*/ +#define MBX_SP_2D_SYS_PHYS_OFFSET 0xA00000 + +/* + MBX Slave Port FIFO Size (in units of `Bits per Write Bus Width') + Includes 5 slot safety factor for fullness register latency +*/ +#define MBX1_SP_FIFO_DWSIZE 123 + +/* + Macro to extract FIFO space from HW register value +*/ +#define MBX_EXTRACT_FIFO_COUNT(x) (((x) & MBX1_INT_TA_FREEVCOUNT_MASK) >> MBX1_INT_TA_FREEVCOUNT_SHIFT) + +static __inline__ void +MBXAcquireFifoSpace(VERMILIONPtr pVermilion, CARD32 n) +{ + while (pVermilion->FifoSlots < n) { + /* read fifo space from HW */ + pVermilion->FifoSlots = (MBX1_SP_FIFO_DWSIZE - + MBX_EXTRACT_FIFO_COUNT(ReadHWReg(MBX1_GLOBREG_INT_STATUS))); + } +} + +static __inline__ void +MBXWriteSlavePortBatch(VERMILIONPtr pVermilion, void *pvLinDataAddr, + CARD32 ui32DWORDs) +{ + CARD32 *pui32LinDataAddr = (CARD32 *) pvLinDataAddr; + CARD32 *pui32LinPortAddrBase = pVermilion->slavePort; + + /* write to the slaveport */ + while (ui32DWORDs--) { + *pui32LinPortAddrBase = *pui32LinDataAddr++; + } +} + +#define WRITESLAVEPORTDATA(n) \ + (void) MBXWriteSlavePortBatch ( pVermilion, auBltPacket, n ); + +#define WAITFIFO(n) \ + MBXAcquireFifoSpace(pVermilion, n); \ + pVermilion->FifoSlots -= n; + +/* + * Block headers + */ +#define MBX2D_CTRL_BH 0x20000000 +#define MBX2D_SRC_OFF_BH 0x30000000 +#define MBX2D_FENCE_BH 0x70000000 /* Flush between two blits */ +#define MBX2D_BLIT_BH 0x80000000 +#define MBX2D_SRC_CTRL_BH 0x90000000 +#define MBX2D_DST_CTRL_BH 0xA0000000 + +#define MBX2D_USE_PAT 0x00010000 + +#define MBX2D_TEXTCOPY_TL2BR 0x00000000 +#define MBX2D_TEXTCOPY_TR2BL 0x00800000 +#define MBX2D_TEXTCOPY_BL2TR 0x01000000 + +#define MBX2D_SRCCK_REJECT 0x00100000 +#define MBX2D_SRCCK_CTRL 0x00000001 + +#define MBX2D_SRC_FBMEM 0x04000000 +#define MBX2D_SRC_555RGB 0x00040000 +#define MBX2D_SRC_8888ARGB 0x00060000 + +#endif /* _VERMILION_MBX_H_ */ diff --git a/src/vermilion_mode.c b/src/vermilion_mode.c new file mode 100644 index 0000000..0d55371 --- /dev/null +++ b/src/vermilion_mode.c @@ -0,0 +1,316 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * Part of this code is taken from the xf86-video-intel driver. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vermilion.h" +#include "vermilion_reg.h" +#include <math.h> + +void +VERMILIONSetGraphicsOffset(ScrnInfoPtr pScrn, int x, int y) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + VML_WRITE32(VML_DSPCADDR, (CARD32) pScrn->memPhysBase + + y * pVermilion->stride + x * pVermilion->cpp); + (void)VML_READ32(VML_DSPCADDR); +} + +static int +VERMILIONNearestClock(ScrnInfoPtr pScrn, int clock, int *index) +{ + *index = xf86GetNearestClock(pScrn, clock, FALSE, 1, 1, NULL); + + return pScrn->clock[*index]; +} + +ModeStatus +VERMILIONValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, + int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + int realClock; + int hPeriod; + int dummy; + + xf86DrvMsg(scrnIndex, X_INFO, "VERMILIONValidMode: Validating %s (%d)\n", + mode->name, mode->Clock); + + realClock = VERMILIONNearestClock(pScrn, mode->Clock, &dummy); + + if (mode->Flags & V_INTERLACE) + return MODE_NO_INTERLACE; + + if (pVermilion->usePanel) { + VERMILIONPanelPtr panel = VERMILIONPanels[pVermilion->panel]; + + if (realClock < panel->clockMin) + return MODE_CLOCK_LOW; + if (realClock > panel->clockMax) + return MODE_CLOCK_HIGH; + if (mode->CrtcHTotal < panel->hTotMin || + mode->CrtcHTotal > panel->hTotMax) + return MODE_BAD_HVALUE; + if (mode->CrtcHDisplay < panel->hActMin || + mode->CrtcHDisplay > panel->hActMax) + return MODE_BAD_HVALUE; + if (mode->CrtcVTotal < panel->vTotMin || + mode->CrtcVTotal > panel->vTotMax) + return MODE_BAD_VVALUE; + if (mode->CrtcVDisplay < panel->vActMin || + mode->CrtcVDisplay > panel->vActMax) + return MODE_BAD_VVALUE; + + hPeriod = mode->CrtcHTotal * 10000 / (realClock / 100); + if (hPeriod < panel->hPerMin || hPeriod > panel->hPerMax) { + return MODE_H_ILLEGAL; + } + } + return MODE_OK; +} + +void +VERMILIONWaitForVblank(ScrnInfoPtr pScrn) +{ + /* Wait for 20ms, i.e. one cycle at 50hz. */ + usleep(20000); +} + +int +VERMILIONBlankScreen(ScrnInfoPtr pScrn, Bool blank) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + CARD32 cur = VML_READ32(VML_PIPEACONF); + + /* + * We'd like to force planes off here, but then we can't + * force them on again. Hw bug? + */ + + if (blank) { + VML_WRITE32(VML_PIPEACONF, cur | VML_PIPE_FORCE_BORDER); + } else { + VML_WRITE32(VML_PIPEACONF, cur & ~VML_PIPE_FORCE_BORDER); + } + (void)VML_READ32(VML_PIPEACONF); + return TRUE; + +} + +void +VERMILIONDisablePipe(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + + /* Disable the MDVO pad */ + VML_WRITE32(VML_RCOMPSTAT, 0); + while (!(VML_READ32(VML_RCOMPSTAT) & VML_MDVO_VDC_I_RCOMP)) ; + + /* Disable display planes */ + VML_WRITE32(VML_DSPCCNTR, VML_READ32(VML_DSPCCNTR) & ~VML_GFX_ENABLE); + (void)VML_READ32(VML_DSPCCNTR); + /* Wait for vblank for the disable to take effect */ + VERMILIONWaitForVblank(pScrn); + + /* Next, disable display pipes */ + VML_WRITE32(VML_PIPEACONF, 0); + (void)VML_READ32(VML_PIPEACONF); +} + +void +VERMILIONDumpRegs(ScrnInfoPtr pScrn) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + ErrorF("Modesetting register dump:\n"); + ErrorF("\tHTOTAL_A : 0x%08x\n", + (unsigned) VML_READ32(VML_HTOTAL_A)); + ErrorF("\tHBLANK_A : 0x%08x\n", + (unsigned) VML_READ32(VML_HBLANK_A)); + ErrorF("\tHSYNC_A : 0x%08x\n", + (unsigned) VML_READ32(VML_HSYNC_A)); + ErrorF("\tVTOTAL_A : 0x%08x\n", + (unsigned) VML_READ32(VML_VTOTAL_A)); + ErrorF("\tVBLANK_A : 0x%08x\n", + (unsigned) VML_READ32(VML_VBLANK_A)); + ErrorF("\tVSYNC_A : 0x%08x\n", + (unsigned) VML_READ32(VML_VSYNC_A)); + ErrorF("\tDSPCSTRIDE : 0x%08x\n", + (unsigned) VML_READ32(VML_DSPCSTRIDE)); + ErrorF("\tDSPCSIZE : 0x%08x\n", + (unsigned) VML_READ32(VML_DSPCSIZE)); + ErrorF("\tDSPCPOS : 0x%08x\n", + (unsigned) VML_READ32(VML_DSPCPOS)); + ErrorF("\tDSPARB : 0x%08x\n", + (unsigned) VML_READ32(VML_DSPARB)); + ErrorF("\tDSPCADDR : 0x%08x\n", + (unsigned) VML_READ32(VML_DSPCADDR)); + ErrorF("\tBCLRPAT_A : 0x%08x\n", + (unsigned) VML_READ32(VML_BCLRPAT_A)); + ErrorF("\tCANVSCLR_A : 0x%08x\n", + (unsigned) VML_READ32(VML_CANVSCLR_A)); + ErrorF("\tPIPEASRC : 0x%08x\n", + (unsigned) VML_READ32(VML_PIPEASRC)); + ErrorF("\tPIPEACONF : 0x%08x\n", + (unsigned) VML_READ32(VML_PIPEACONF)); + ErrorF("\tDSPCCNTR : 0x%08x\n", + (unsigned) VML_READ32(VML_DSPCCNTR)); + ErrorF("\tRCOMPSTAT : 0x%08x\n", + (unsigned) VML_READ32(VML_RCOMPSTAT)); + ErrorF("End of modesetting register dump.\n"); +} + + +/* + * Sets the given video mode. + */ + +Bool +VERMILIONDoSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Bool plane_enable) +{ + VERMILIONPtr pVermilion = VERMILIONPTR(pScrn); + VERMILIONSys *sys = pVermilion->sys; + CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr; + CARD32 pipesrc, dspsize; + int pixelClock; + Bool ret = FALSE; + int index; + + if (VERMILIONValidMode(pScrn->scrnIndex, pMode, FALSE, 0) != MODE_OK) + goto done; + +#if 0 + if (I830ModesEqual(&pVermilion->curMode, pMode)) + return TRUE; +#endif + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested pix clock: %d\n", + pMode->Clock); + + htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16); + hblank = + (pMode->CrtcHBlankStart - 1) | ((pMode->CrtcHBlankEnd - 1) << 16); + hsync = (pMode->CrtcHSyncStart - 1) | ((pMode->CrtcHSyncEnd - 1) << 16); + vtot = (pMode->CrtcVDisplay - 1) | ((pMode->CrtcVTotal - 1) << 16); + vblank = + (pMode->CrtcVBlankStart - 1) | ((pMode->CrtcVBlankEnd - 1) << 16); + vsync = (pMode->CrtcVSyncStart - 1) | ((pMode->CrtcVSyncEnd - 1) << 16); + pipesrc = ((pMode->HDisplay - 1) << 16) | (pMode->VDisplay - 1); + dspsize = ((pMode->VDisplay - 1) << 16) | (pMode->HDisplay - 1); + pixelClock = VERMILIONNearestClock(pScrn, pMode->Clock, &index); + + if (pVermilion->debug) { + ErrorF + ("hact: %d htot: %d hbstart: %d hbend: %d hsyncstart: %d hsyncend: %d\n", + (int)(htot & 0xffff) + 1, (int)(htot >> 16) + 1, + (int)(hblank & 0xffff) + 1, (int)(hblank >> 16) + 1, + (int)(hsync & 0xffff) + 1, (int)(hsync >> 16) + 1); + ErrorF + ("vact: %d vtot: %d vbstart: %d vbend: %d vsyncstart: %d vsyncend: %d\n", + (int)(vtot & 0xffff) + 1, (int)(vtot >> 16) + 1, + (int)(vblank & 0xffff) + 1, (int)(vblank >> 16) + 1, + (int)(vsync & 0xffff) + 1, (int)(vsync >> 16) + 1); + ErrorF("pipesrc: %dx%d, dspsize: %dx%d\n", (int)(pipesrc >> 16) + 1, + (int)(pipesrc & 0xffff) + 1, (int)(dspsize & 0xffff) + 1, + (int)(dspsize >> 16) + 1); + ErrorF("Actual Pixel clock is %d kHz\n" + "\t Horizontal frequency is %.1f kHz\n" + "\t Vertical frequency is %.1f Hz\n", + pixelClock, + (float)pixelClock / (float)(pMode->CrtcHTotal), + (float)pixelClock / (float)(pMode->CrtcHTotal) / + (float)(pMode->CrtcVTotal) * 1000.); + } + dspcntr = VML_GFX_ENABLE | VML_GFX_GAMMABYPASS; + switch (pScrn->depth) { + case 15: + dspcntr |= VML_GFX_ARGB1555; + break; + case 24: + dspcntr |= VML_GFX_RGB0888; + break; + default: + ErrorF("Unknown display BPP\n"); + goto done; + } + + /* Finally, set the mode. */ + VERMILIONDisablePipe(pScrn); + mem_barrier(); + + /* Set pixel clock */ + if (!sys->setClock(sys, pixelClock)) + return FALSE; + + VML_WRITE32(VML_HTOTAL_A, htot); + VML_WRITE32(VML_HBLANK_A, hblank); + VML_WRITE32(VML_HSYNC_A, hsync); + VML_WRITE32(VML_VTOTAL_A, vtot); + VML_WRITE32(VML_VBLANK_A, vblank); + VML_WRITE32(VML_VSYNC_A, vsync); + VML_WRITE32(VML_DSPCSTRIDE, pVermilion->stride); + VML_WRITE32(VML_DSPCSIZE, dspsize); + VML_WRITE32(VML_DSPCPOS, 0x00000000); + VML_WRITE32(VML_DSPARB, VML_FIFO_DEFAULT); + /* Black border color */ + VML_WRITE32(VML_BCLRPAT_A, 0x00000000); + /* Black canvas color */ + VML_WRITE32(VML_CANVSCLR_A, 0x00000000); + VML_WRITE32(VML_PIPEASRC, pipesrc); + (void)VML_READ32(VML_PIPEASRC); + mem_barrier(); + + /* Then, turn the pipe on first. */ + VML_WRITE32(VML_PIPEACONF, VML_PIPE_ENABLE); + (void)VML_READ32(VML_PIPEACONF); + mem_barrier(); + + VML_WRITE32(VML_DSPCCNTR, dspcntr); + VERMILIONSetGraphicsOffset(pScrn, pVermilion->x, pVermilion->y); + + /* Enable the MDVO pad */ + VML_WRITE32(VML_RCOMPSTAT, VML_MDVO_PAD_ENABLE); + while (!(VML_READ32(VML_RCOMPSTAT) & + (VML_MDVO_VDC_I_RCOMP | VML_MDVO_PAD_ENABLE))) ; + + pVermilion->curMode = *pMode; + if (pVermilion->debug) + VERMILIONDumpRegs(pScrn); + ret = TRUE; + done: + return ret; +} diff --git a/src/vermilion_panels.c b/src/vermilion_panels.c new file mode 100644 index 0000000..6efdc4a --- /dev/null +++ b/src/vermilion_panels.c @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* Authors: + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ + +#include "vermilion.h" +#include "vermilion_reg.h" + +/* + * Add panel timing information and gamma here. + */ + +/* SHARP LQ150X1LGN2A */ +static VERMILIONPanelRec panel0 = { + "SHARP LQ150X1LGN2A", + 80000, + 50000, + 1024, + 1024, + 1720, + 1056, + 768, + 768, + 990, + 773, + 23400, + 16000, + 1.0 +}; + +VERMILIONPanelPtr VERMILIONPanels[] = { + &panel0 +}; + +int VERMILIONNumPanels = sizeof(VERMILIONPanels) / sizeof(VERMILIONPanelPtr); diff --git a/src/vermilion_reg.h b/src/vermilion_reg.h new file mode 100644 index 0000000..6b5ff0b --- /dev/null +++ b/src/vermilion_reg.h @@ -0,0 +1,187 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ + +#ifndef _VERMILION_REG_H_ +#define _VERMILION_REG_H_ + +#define VML_READ32(_offs) \ + (*((volatile CARD32 *) ((volatile CARD8 *)pVermilion->vdcRegsBase + (_offs)))) +#define VML_WRITE32(__offs, _data) \ + (VML_READ32(__offs) = (_data)); + +/* + * Display controller registers: + */ + +/* Display controller 10-bit color representation */ + +#define VML_R_MASK 0x3FF00000 +#define VML_R_SHIFT 20 +#define VML_G_MASK 0x000FFC00 +#define VML_G_SHIFT 10 +#define VML_B_MASK 0x000003FF +#define VML_B_SHIFT 0 + +/* Graphics plane control */ +#define VML_DSPCCNTR 0x00072180 +#define VML_GFX_ENABLE 0x80000000 +#define VML_GFX_GAMMABYPASS 0x40000000 +#define VML_GFX_ARGB1555 0x0C000000 +#define VML_GFX_RGB0888 0x18000000 +#define VML_GFX_ARGB8888 0x1C000000 +#define VML_GFX_ALPHACONST 0x00800000 +#define VML_GFX_CONST_ALPHA 0x000000FF + +/* Graphics plane start address. Pixel aligned. */ +#define VML_DSPCADDR 0x00072184 + +/* Graphics plane stride register. */ +#define VML_DSPCSTRIDE 0x00072188 + +/* Graphics plane position register. */ +#define VML_DSPCPOS 0x0007218C +#define VML_POS_YMASK 0x0FFF0000 +#define VML_POS_YSHIFT 16 +#define VML_POS_XMASK 0x00000FFF +#define VML_POS_XSHIFT 0 + +/* Graphics plane height and width */ +#define VML_DSPCSIZE 0x00072190 +#define VML_SIZE_HMASK 0x0FFF0000 +#define VML_SIZE_HSHIFT 16 +#define VML_SISE_WMASK 0x00000FFF +#define VML_SIZE_WSHIFT 0 + +/* Graphics plane gamma correction lookup table registers (129 * 32 bits) */ +#define VML_DSPCGAMLUT 0x00072200 + +/* Pixel video output configuration register */ +#define VML_PVOCONFIG 0x00061140 +#define VML_CONFIG_BASE 0x80000000 +#define VML_CONFIG_PIXEL_SWAP 0x04000000 +#define VML_CONFIG_DE_INV 0x01000000 +#define VML_CONFIG_HREF_INV 0x00400000 +#define VML_CONFIG_VREF_INV 0x00100000 +#define VML_CONFIG_CLK_INV 0x00040000 +#define VML_CONFIG_CLK_DIV2 0x00010000 +#define VML_CONFIG_ESTRB_INV 0x00008000 + +/* Pipe A Horizontal total register */ +#define VML_HTOTAL_A 0x00060000 +#define VML_HTOTAL_MASK 0x1FFF0000 +#define VML_HTOTAL_SHIFT 16 +#define VML_HTOTAL_VAL 8192 +#define VML_HACTIVE_MASK 0x000007FF +#define VML_HACTIVE_SHIFT 0 +#define VML_HACTIVE_VAL 4096 + +/* Pipe A Horizontal Blank register */ +#define VML_HBLANK_A 0x00060004 +#define VML_HBLANK_END_MASK 0x1FFF0000 +#define VML_HBLANK_END_SHIFT 16 +#define VML_HBLANK_END_VAL 8192 +#define VML_HBLANK_START_MASK 0x00001FFF +#define VML_HBLANK_START_SHIFT 0 +#define VML_HBLANK_START_VAL 8192 + +/* Pipe A Horizontal Sync register */ +#define VML_HSYNC_A 0x00060008 +#define VML_HSYNC_END_MASK 0x1FFF0000 +#define VML_HSYNC_END_SHIFT 16 +#define VML_HSYNC_END_VAL 8192 +#define VML_HSYNC_START_MASK 0x00001FFF +#define VML_HSYNC_START_SHIFT 0 +#define VML_HSYNC_START_VAL 8192 + +/* Pipe A Vertical total register */ +#define VML_VTOTAL_A 0x0006000C +#define VML_VTOTAL_MASK 0x1FFF0000 +#define VML_VTOTAL_SHIFT 16 +#define VML_VTOTAL_VAL 8192 +#define VML_VACTIVE_MASK 0x000007FF +#define VML_VACTIVE_SHIFT 0 +#define VML_VACTIVE_VAL 4096 + +/* Pipe A Vertical Blank register */ +#define VML_VBLANK_A 0x00060010 +#define VML_VBLANK_END_MASK 0x1FFF0000 +#define VML_VBLANK_END_SHIFT 16 +#define VML_VBLANK_END_VAL 8192 +#define VML_VBLANK_START_MASK 0x00001FFF +#define VML_VBLANK_START_SHIFT 0 +#define VML_VBLANK_START_VAL 8192 + +/* Pipe A Vertical Sync register */ +#define VML_VSYNC_A 0x00060014 +#define VML_VSYNC_END_MASK 0x1FFF0000 +#define VML_VSYNC_END_SHIFT 16 +#define VML_VSYNC_END_VAL 8192 +#define VML_VSYNC_START_MASK 0x00001FFF +#define VML_VSYNC_START_SHIFT 0 +#define VML_VSYNC_START_VAL 8192 + +/* Pipe A Source Image size (minus one - equal to active size) + * Programmable while pipe is enabled. + */ +#define VML_PIPEASRC 0x0006001C +#define VML_PIPEASRC_HMASK 0x0FFF0000 +#define VML_PIPEASRC_HSHIFT 16 +#define VML_PIPEASRC_VMASK 0x00000FFF +#define VML_PIPEASRC_VSHIFT 0 + +/* Pipe A Border Color Pattern register (10 bit color) */ +#define VML_BCLRPAT_A 0x00060020 + +/* Pipe A Canvas Color register (10 bit color) */ +#define VML_CANVSCLR_A 0x00060024 + +/* Pipe A Configuration register */ +#define VML_PIPEACONF 0x00070008 +#define VML_PIPE_BASE 0x00000000 +#define VML_PIPE_ENABLE 0x80000000 +#define VML_PIPE_FORCE_BORDER 0x02000000 +#define VML_PIPE_PLANES_OFF 0x00080000 +#define VML_PIPE_ARGB_OUTPUT_MODE 0x00040000 + +/* Pipe A FIFO setting */ +#define VML_DSPARB 0x00070030 +#define VML_FIFO_DEFAULT 0x00001D9C + +/* MDVO rcomp status & pads control register */ +#define VML_RCOMPSTAT 0x00070048 +#define VML_MDVO_VDC_I_RCOMP 0x80000000 +#define VML_MDVO_POWERSAVE_OFF 0x00000008 +#define VML_MDVO_PAD_ENABLE 0x00000004 +#define VML_MDVO_PULLDOWN_ENABLE 0x00000001 + +#endif diff --git a/src/vermilion_sys.c b/src/vermilion_sys.c new file mode 100644 index 0000000..56fd4db --- /dev/null +++ b/src/vermilion_sys.c @@ -0,0 +1,444 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vermilion_kernel.h" +#include "vermilion.h" + +typedef enum +{ + carilloRanch = 0, + numSystems +} VERMILIONSysID; + +typedef struct +{ + VERMILIONSysID sysID; + CARD32 subsys0; + CARD32 subsys1; + const char *sysName; +} VERMILIONSubSystem; + +/* + * We can possibly identify the board type + * based on the PCI subsystem ids + * of the host bridge? + * See the sys initialization function below. + */ + +static VERMILIONSubSystem vSystems[] = { + {carilloRanch, 0x8086, 0x5001, "Carillo Ranch"} +}; + +/* +***************************************************************************** +* Carillo Ranch System info. +*/ + +/* The LVDS- and panel power controls sits on the + GPIO port of the ISA bridge. */ + +#define VML_CR_DEVICE_LPC 0x27B8 +#define VML_CR_REG_GPIOBAR 0x48 +#define VML_CR_REG_GPIOEN 0x4C +#define VML_CR_GPIOEN_BIT (1 << 4) +#define VML_CR_PANEL_PORT 0x38 +#define VML_CR_LVDS_ON 0x00000001 +#define VML_CR_PANEL_ON 0x00000002 +#define VML_CR_BACKLIGHT_OFF 0x00000004 + +/* The PLL Clock register sits on Host bridge */ +#define VML_CR_DEVICE_MCH 0x5001 +#define VML_CR_REG_MCHBAR 0x44 +#define VML_CR_REG_MCHEN 0x54 +#define VML_CR_MCHEN_BIT (1 << 28) +#define VML_CR_MCHMAP_SIZE 4096 +#define VML_CR_REG_CLOCK 0xc3c +#define VML_CR_CLOCK_SHIFT 8 +#define VML_CR_CLOCK_MASK 0x00000f00 + +typedef struct _CRSys +{ + CARD32 mchBAR; + unsigned char *mchRegsBase; + CARD32 gpioBAR; + CARD32 savedPanelState; + CARD32 savedClock; + ScrnInfoPtr pScrn; +} CRSys; + +static const unsigned vermilionCRClocks[] = { + 6750, + 13500, + 27000, + 29700, + 37125, + 54000, + 59400, + 74250, + 120000 + /* + * There are more clocks, but they are disabled on the CR board. + */ +}; + +static const unsigned vermilionCRClockBits[] = { + 0x0a, + 0x09, + 0x08, + 0x07, + 0x06, + 0x05, + 0x04, + 0x03, + 0x0b +}; + +static const unsigned vermilionCRNumClocks = + sizeof(vermilionCRClocks) / sizeof(unsigned); + +static pointer +VERMILIONCRInit(ScrnInfoPtr pScrn) +{ + CRSys *crSys; + CARD32 devEn; + PCITAG curTag; + PCITAG mchTag = pciTag(0x00, 0x00, 0x00); + PCITAG lpcTag = pciTag(0x00, 0x1f, 0x00); + + crSys = (CRSys *) calloc(sizeof(*crSys), 1); + if (!crSys) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Out of memory.\n"); + return NULL; + } + crSys->pScrn = pScrn; + + curTag = pciFindFirst((VML_CR_DEVICE_MCH << 16) | PCI_VENDOR_INTEL, + 0xffffffff); + if (curTag != mchTag) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not find Carillo Ranch " + "MCH device.\n"); + goto out_err; + } + + devEn = (CARD32) pciReadLong(mchTag, VML_CR_REG_MCHEN); + if (!(devEn & VML_CR_MCHEN_BIT)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Carillo Ranch MCH device " + "was not enabled.\n"); + goto out_err; + } + + crSys->mchBAR = (CARD32) pciReadLong(mchTag, VML_CR_REG_MCHBAR); + crSys->mchRegsBase = + VERMILIONMapPciVideo(pScrn, "MCH", + mchTag, crSys->mchBAR, VML_CR_MCHMAP_SIZE, 0, VIDMEM_MMIO); + if (!crSys->mchRegsBase) + goto out_err; + + /* + * Get the gpio bar. + */ + + curTag = pciFindFirst((VML_CR_DEVICE_LPC << 16) | PCI_VENDOR_INTEL, + 0xffffffff); + if (curTag != lpcTag) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not find Carillo Ranch " + "LPC device.\n"); + goto out_err; + } + + devEn = pciReadByte(lpcTag, VML_CR_REG_GPIOEN); + if (!(devEn & VML_CR_GPIOEN_BIT)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Carillo Ranch GPIO " + "was not enabled.\n"); + goto out_err; + } + + crSys->gpioBAR = (CARD32) pciReadLong(lpcTag, VML_CR_REG_GPIOBAR) & ~0x3F; + return crSys; + + out_err: + + if (crSys->mchRegsBase) + xf86UnMapVidMem(crSys->pScrn->scrnIndex, crSys->mchRegsBase, + VML_CR_MCHMAP_SIZE); + + free(crSys); + return NULL; +} + +static void +VERMILIONCRSysDestroy(VERMILIONSys * sys) +{ + CRSys *crSys = (CRSys *) sys->priv; + + if (crSys->mchRegsBase) + xf86UnMapVidMem(crSys->pScrn->scrnIndex, crSys->mchRegsBase, + VML_CR_MCHMAP_SIZE); + + free(crSys); + free(sys); +} + +static void +VERMILIONCRPanelOn(const VERMILIONSys * sys) +{ + CRSys *crSys = (CRSys *) sys->priv; + CARD32 addr = crSys->gpioBAR + VML_CR_PANEL_PORT; + CARD32 cur = inl(addr); + + if (!(cur & VML_CR_PANEL_ON)) { + /* Make sure LVDS controller is down. */ + if (cur & 0x00000001) { + cur &= ~VML_CR_LVDS_ON; + outl(addr, cur); + } + /* Power up Panel */ + usleep(100000); + cur |= VML_CR_PANEL_ON; + outl(addr, cur); + } + + /* Power up LVDS controller */ + + if (!(cur & VML_CR_LVDS_ON)) { + usleep(100000); + outl(addr, cur | VML_CR_LVDS_ON); + } +} + +void +VERMILIONCRPanelOff(const VERMILIONSys * sys) +{ + CRSys *crSys = (CRSys *) sys->priv; + CARD32 addr = crSys->gpioBAR + VML_CR_PANEL_PORT; + CARD32 cur = inl(addr); + + /* Power down LVDS controller first to avoid high currents */ + if (cur & VML_CR_LVDS_ON) { + cur &= ~VML_CR_LVDS_ON; + outl(addr, cur); + } + if (cur & VML_CR_PANEL_ON) { + usleep(100000); + outl(addr, cur & ~VML_CR_PANEL_ON); + } +} + +void +VERMILIONCRBacklightOn(const VERMILIONSys * sys) +{ + CRSys *crSys = (CRSys *) sys->priv; + CARD32 addr = crSys->gpioBAR + VML_CR_PANEL_PORT; + CARD32 cur = inl(addr); + + if (cur & VML_CR_BACKLIGHT_OFF) { + cur &= ~VML_CR_BACKLIGHT_OFF; + outl(addr, cur); + } +} + +void +VERMILIONCRBacklightOff(const VERMILIONSys * sys) +{ + CRSys *crSys = (CRSys *) sys->priv; + CARD32 addr = crSys->gpioBAR + VML_CR_PANEL_PORT; + CARD32 cur = inl(addr); + + if (!(cur & VML_CR_BACKLIGHT_OFF)) { + cur |= VML_CR_BACKLIGHT_OFF; + outl(addr, cur); + } +} + +static Bool +VERMILIONCRSysRestore(VERMILIONSys * sys) +{ + CRSys *crSys = (CRSys *) sys->priv; + volatile CARD32 *clockReg = (volatile CARD32 *) + (crSys->mchRegsBase + VML_CR_REG_CLOCK); + + CARD32 cur = crSys->savedPanelState; + + if (cur & VML_CR_BACKLIGHT_OFF) { + VERMILIONCRBacklightOff(sys); + } else { + VERMILIONCRBacklightOn(sys); + } + + if (cur & VML_CR_PANEL_ON) { + VERMILIONCRPanelOn(sys); + } else { + VERMILIONCRPanelOff(sys); + if (cur & VML_CR_LVDS_ON) { + ; + /* Will not power up LVDS controller while panel is off */ + } + } + + *clockReg = crSys->savedClock; + (void)*clockReg; + + return TRUE; +} + +static Bool +VERMILIONCRSysSave(VERMILIONSys * sys) +{ + CRSys *crSys = (CRSys *) sys->priv; + volatile CARD32 *clockReg = (volatile CARD32 *) + (crSys->mchRegsBase + VML_CR_REG_CLOCK); + + crSys->savedPanelState = inl(crSys->gpioBAR + VML_CR_PANEL_PORT); + crSys->savedClock = *clockReg; + + return TRUE; +} + +static Bool +VERMILIONCRSetClock(VERMILIONSys * sys, int clock) +{ + CRSys *crSys = (CRSys *) sys->priv; + volatile CARD32 *clockReg = (volatile CARD32 *) + (crSys->mchRegsBase + VML_CR_REG_CLOCK); + int index; + CARD32 clockVal; + + index = xf86GetNearestClock(crSys->pScrn, clock, FALSE, 1, 1, NULL); + if (vermilionCRClocks[index] != clock) + return FALSE; + + clockVal = *clockReg & ~VML_CR_CLOCK_MASK; + clockVal = vermilionCRClockBits[index] << VML_CR_CLOCK_SHIFT; + *clockReg = clockVal; + (void)*clockReg; + + return TRUE; +} + +static void +VERMILIONCRClocks(const VERMILIONSys * sys, int *numClocks, int clocks[]) +{ + unsigned i; + + *numClocks = vermilionCRNumClocks; + for (i = 0; i < vermilionCRNumClocks; ++i) { + clocks[i] = vermilionCRClocks[i]; + } +} + +/* +*********************Generic functions****************************** +*/ + +static void +VERMILIONGenericSubSys(VERMILIONSys * sys, char const **name, + unsigned *id0, unsigned *id1) +{ + VERMILIONSubSystem *subSys = &vSystems[(VERMILIONSysID) sys->id]; + + *name = subSys->sysName; + *id0 = subSys->subsys0; + *id1 = subSys->subsys1; +} + +static Bool +VERMILIONFalse(VERMILIONSys * sys) +{ + return FALSE; +} + +static int +VERMILIONPanel0(const VERMILIONSys * sys) +{ + return 0; +} + +static void +VERMILIONGenericClockRanges(const VERMILIONSys * sys, int *low, int *high) +{ + *low = 6500; + *high = 120000; +} + +VERMILIONSys * +VERMILIONCreateSys(ScrnInfoPtr pScrn) +{ + VERMILIONSys *sys; + VERMILIONSysID sysID; + + sys = (VERMILIONSys *) malloc(sizeof(*sys)); + if (!sys) + goto out_error; + + /* + * Add a smart way to detect board id here. + */ + + sysID = carilloRanch; + + sys->id = (int)sysID; + switch (sysID) { + case carilloRanch: + sys->priv = VERMILIONCRInit(pScrn); + if (!sys->priv) + goto out_error; + + sys->subSys = VERMILIONGenericSubSys; + sys->save = VERMILIONCRSysSave; + sys->restore = VERMILIONCRSysRestore; + sys->destroy = VERMILIONCRSysDestroy; + sys->progClock = VERMILIONFalse; + sys->clockRanges = VERMILIONGenericClockRanges; + sys->clocks = VERMILIONCRClocks; + sys->setClock = VERMILIONCRSetClock; + sys->panel = VERMILIONPanel0; + sys->panelOn = VERMILIONCRPanelOn; + sys->panelOff = VERMILIONCRPanelOff; + sys->backlightOn = VERMILIONCRBacklightOn; + sys->backlightOff = VERMILIONCRBacklightOff; + break; + default: + goto out_error; + } + + return sys; + + out_error: + if (sys) + free(sys); + return NULL; +} diff --git a/src/vermilion_sys.h b/src/vermilion_sys.h new file mode 100644 index 0000000..a8680c5 --- /dev/null +++ b/src/vermilion_sys.h @@ -0,0 +1,87 @@ +/************************************************************************** + * + * Copyright (c) Intel Corp. 2007. + * All Rights Reserved. + * + * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + * develop this driver. + * + * 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, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: + * Thomas Hellström <thomas-at-tungstengraphics-dot-com> + */ + +#ifndef _VERMILION_SYS_H_ +#define _VERMILION_SYS_H_ + +struct _VERMILIONSysPriv; + +typedef struct _VERMILIONSys +{ + + /* + * Subsystem identifier: + */ + + void (*subSys) (struct _VERMILIONSys * sys, + const char **name, unsigned *id0, unsigned *id1); + /* + * Save / Restore; + */ + + int (*save) (struct _VERMILIONSys * sys); + int (*restore) (struct _VERMILIONSys * sys); + + /* + * PLL programming; + */ + + void (*destroy) (struct _VERMILIONSys * sys); + Bool(*progClock) (struct _VERMILIONSys * sys); + void (*clockRanges) (const struct _VERMILIONSys * sys, int *low, + int *high); + void (*clocks) (const struct _VERMILIONSys * sys, int *numClocks, + int clocks[]); + Bool(*setClock) (struct _VERMILIONSys * sys, int clock); + + /* + * Panel type and functions. + */ + + int (*panel) (const struct _VERMILIONSys * sys); + void (*panelOn) (const struct _VERMILIONSys * sys); + void (*panelOff) (const struct _VERMILIONSys * sys); + void (*backlightOn) (const struct _VERMILIONSys * sys); + void (*backlightOff) (const struct _VERMILIONSys * sys); + + /* + * Private information. + */ + int id; + pointer *priv; +} VERMILIONSys; + +VERMILIONSys *VERMILIONCreateSys(ScrnInfoPtr pScrn); + +#endif |