aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2011-07-17 17:29:02 -0500
committerRob Clark <rob@ti.com>2011-07-19 20:38:19 -0500
commit487687ecc36e158a41378eb48f6ea26332c877d8 (patch)
tree1c9a5d353048e08212635e5b8a735a14f0cf94e4
initial commit
-rw-r--r--AUTHORS2
-rw-r--r--COPYING20
-rw-r--r--Makefile.am34
-rw-r--r--NEWS1
-rw-r--r--README19
-rwxr-xr-xautogen.sh33
-rw-r--r--configure.ac97
-rw-r--r--man/Makefile.am37
-rw-r--r--man/omap.man114
-rw-r--r--src/Makefile.am48
-rw-r--r--src/drmmode_display.c1180
-rw-r--r--src/omap_driver.c989
-rw-r--r--src/omap_driver.h239
-rw-r--r--src/omap_drm.c172
-rw-r--r--src/omap_drm.h99
-rw-r--r--src/omap_exa_common.c231
-rw-r--r--src/omap_exa_common.h57
-rw-r--r--src/omap_exa_null.c153
18 files changed, 3525 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..8a67fe1
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Ian Elliott <ianelliottus@yahoo.com>
+Rob Clark <rob@ti.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..dc52121
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,20 @@
+Copyright © 2011 Texas Instruments, Inc
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..7c0a6a9
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,34 @@
+# 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.
+
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+SUBDIRS = src man
+MAINTAINERCLEANFILES = ChangeLog INSTALL
+
+.PHONY: ChangeLog INSTALL
+
+INSTALL:
+ $(INSTALL_CMD)
+
+ChangeLog:
+ $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog INSTALL
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..a099036
--- /dev/null
+++ b/NEWS
@@ -0,0 +1 @@
+TBD
diff --git a/README b/README
new file mode 100644
index 0000000..c58eaa3
--- /dev/null
+++ b/README
@@ -0,0 +1,19 @@
+xf86-video-omap
+Open-source X.org graphics driver for TI OMAP graphics
+
+Currently relies on a closed-source submodule for EXA acceleration on
+the following chipsets:
+ + OMAP3430
+ + OMAP3630
+ + OMAP4430
+ + OMAP4460
+
+
+NOTE: this driver is work in progress.. you probably don't want to try
+and use it yet. The API/ABI between driver and kernel, and driver and
+acceleration submodules is not stable yet. This driver requires the
+omapdrm kernel driver w/ GEM support.
+
+EXA vs UXA? This is an open question..
+
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..d1885dc
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+cd `dirname $0`
+
+# on some platforms, you have "g" versions of some of these tools instead,
+# ie glibtoolize instead of libtoolize..
+find_tool() {
+ which $1 2> /dev/null || which g$1 2> /dev/null
+}
+
+aclocal=`find_tool aclocal`
+libtoolize=`find_tool libtoolize`
+automake=`find_tool automake`
+autoconf=`find_tool autoconf`
+autoheader=`find_tool autoheader`
+
+mkdir -p config && $aclocal && $libtoolize --copy --force && $automake --copy --add-missing --foreign && $autoheader && $autoconf
+
+test -n "$NOCONFIGURE" && {
+ echo "skipping configure stage as requested."
+ echo "autogen.sh done."
+ exit 0
+}
+
+CONFIGURE_DEF_OPT="--enable-maintainer-mode"
+echo ./configure $CONFIGURE_DEF_OPT $*
+./configure $CONFIGURE_DEF_OPT $* || {
+ echo " configure failed"
+ exit 1
+}
+
+echo "Now type 'make' to compile"
+
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..58516ab
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,97 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.60)
+# XXX bug URL should be https://bugs.freedesktop.org/enter_bug.cgi?product=xorg
+# but this makes autoheader choke..
+AC_INIT([xf86-video-omap],
+ [0.0.1],
+ [https://bugs.freedesktop.org/enter_bug.cgi],
+ [xf86-video-omap])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_AUX_DIR(.)
+
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+AM_MAINTAINER_MODE
+
+# Require xorg-macros: XORG_DEFAULT_OPTIONS
+m4_ifndef([XORG_MACROS_VERSION],
+ [m4_fatal([must install xorg-macros 1.4 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.4)
+XORG_DEFAULT_OPTIONS
+
+# Checks for programs.
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_PROG_CC
+
+AC_CHECK_HEADERS([sys/ioctl.h])
+
+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(RANDR, randrproto)
+XORG_DRIVER_CHECK_EXT(RENDER, renderproto)
+XORG_DRIVER_CHECK_EXT(XV, videoproto)
+XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
+
+# Checks for pkg-config packages
+PKG_CHECK_MODULES(XORG, [xorg-server >= 1.3] xproto fontsproto libdrm xf86driproto $REQUIRED_MODULES)
+sdkdir=$(pkg-config --variable=sdkdir xorg-server)
+
+# Checks for header files.
+AC_HEADER_STDC
+
+save_CFLAGS="$CFLAGS"
+CFLAGS="$XORG_CFLAGS $DRI_CFLAGS $DRM_CFLAGS"
+CPPFLAGS="$XORG_CFLAGS $DRI_CFLAGS $DRM_CFLAGS"
+AC_MSG_CHECKING([whether to include DRI support])
+if test x$DRI != xno; then
+ AC_CHECK_FILE([${sdkdir}/dri.h],
+ [have_dri_h="yes"], [have_dri_h="no"])
+ AC_CHECK_FILE([${sdkdir}/dristruct.h],
+ [have_dristruct_h="yes"], [have_dristruct_h="no"])
+fi
+AC_MSG_CHECKING([whether to include DRI support])
+if test x$DRI = xauto; then
+ if test "$have_dri_h" = yes -a \
+ "$have_dristruct_h" = yes; then
+ DRI="yes"
+ else
+ DRI="no"
+ fi
+fi
+AC_MSG_RESULT([$DRI])
+CFLAGS="$save_CFLAGS $DEBUGFLAGS"
+
+AM_CONDITIONAL(DRI, test x$DRI = xyes)
+if test "$DRI" = yes; then
+ PKG_CHECK_MODULES(DRI, [xf86driproto glproto])
+ AC_DEFINE(XF86DRI,1,[Enable DRI driver support])
+ AC_DEFINE(XF86DRI_DEVEL,1,[Enable developmental DRI driver support])
+fi
+
+AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
+if test "$VIDEO_DEBUG" = yes; then
+ AC_DEFINE(VIDEO_DEBUG,1,[Enable debug support])
+fi
+
+AC_SUBST([DRI_CFLAGS])
+
+DRIVER_NAME=omap
+AC_SUBST([DRIVER_NAME])
+AC_SUBST([moduledir])
+
+AC_OUTPUT([
+ Makefile
+ src/Makefile
+ man/Makefile
+])
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..9ca5ff6
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,37 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+
+drivermandir = $(DRIVER_MAN_DIR)
+driverman_DATA = $(DRIVER_NAME).$(DRIVER_MAN_SUFFIX)
+
+EXTRA_DIST = $(DRIVER_NAME).man
+
+CLEANFILES = $(driverman_DATA)
+
+# String replacements in MAN_SUBSTS now come from xorg-macros.m4 via configure
+
+
+SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
+
+.man.$(DRIVER_MAN_SUFFIX):
+ $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
diff --git a/man/omap.man b/man/omap.man
new file mode 100644
index 0000000..21567ab
--- /dev/null
+++ b/man/omap.man
@@ -0,0 +1,114 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH omap __drivermansuffix__ __vendorversion__
+.SH NAME
+omap \- OMAP SoC graphics
+.SH SYNOPSIS
+.nf
+.B "Section \*qDevice\*q"
+.BI " Identifier \*q" devname \*q
+.B " Driver \*qomap\*q"
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B omap
+is an __xservername__ driver for OMAP SoCs.
+.SH SUPPORTED HARDWARE
+.B omap
+supports the OMAP3430, OMAP3630, OMAP4430, OMAP4460
+
+.SH CONFIGURATION DETAILS
+Please refer to __xconfigfile__(__filemansuffix__) for general configuration
+details. This section only covers configuration details specific to this
+driver.
+.PP
+TODO
+.PP
+The following driver
+.B Options
+are supported
+.TP
+.BI "Option \*qDebug\*q \*q" boolean \*q
+Enable debug logging.
+.IP
+Default: Disabled
+.TP
+.BI "Option \*qNoAccel\*q \*q" boolean \*q
+Disable hw acceleration.
+.IP
+Default: Disabled
+
+.SH OUTPUT CONFIGURATION
+The driver supports runtime configuration of detected outputs. You can use the
+.B xrandr
+tool to control outputs on the command line as follows:
+
+.RS
+.B xrandr \-\-output
+.I output
+.B \-\-set
+.I property value
+.RE
+
+Note that you may need to quote property and value arguments that contain spaces.
+Each output listed below may have one or more properties associated
+with it (like a binary EDID block if one is found). Some outputs have
+unique properties which are described below. See the "MULTIHEAD
+CONFIGURATIONS" section below for additional information.
+
+TODO
+
+.PP
+See __xconfigfile__(__filemansuffix__) for information on associating Monitor
+sections with these outputs for configuration. Associating Monitor sections
+with each output can be helpful if you need to ignore a specific output, for
+example, or statically configure an extended desktop monitor layout.
+
+.SH MULTIHEAD CONFIGURATIONS
+
+The number of independent outputs is dictated by the number of CRTCs
+(in X parlance) a given chip supports. OMAP3xxx supports up to two,
+while OMAP4xxx supports up to three displays. The actual number of
+displays supported will depend on the board. But a built-in LCD and
+external HDMI are a common configuration.
+
+You can use the "xrandr" tool, or various desktop utilities, to change
+your output configuration at runtime. To statically configure your
+outputs, you can use the "Monitor-<type>" options along with
+additional monitor sections in your xorg.conf to create your screen
+topology. The example below puts the VGA output to the right of the
+builtin laptop screen, both running at 1024x768.
+
+.nf
+.B "Section \*qMonitor\*q"
+.BI " Identifier \*qLaptop FooBar Internal Display\*q"
+.BI " Option \*qPosition\*q \*q0 0\*q"
+.B "EndSection"
+
+.B "Section \*qMonitor\*q"
+.BI " Identifier \*qSome Random CRT\*q"
+.BI " Option \*qPosition\*q \*q1024 0\*q"
+.BI " Option \*qRightOf\*q \*qLaptop FoodBar Internal Display\*q"
+.B "EndSection"
+
+.B "Section \*qDevice\*q"
+.BI " Driver \*qomap\*q"
+.BI " Option \*qmonitor-LVDS\*q \*qLaptop FooBar Internal Display\*q"
+.BI " Option \*qmonitor-VGA\*q \*qSome Random CRT\*q"
+.B "EndSection"
+
+.SH REPORTING BUGS
+
+The xf86-video-omap driver is part of the X.Org and Freedesktop.org
+umbrella projects. Report bugs at
+https://bugs.freedesktop.org/enter_bug.cgi?product=xorg. Mailing
+lists are also commonly used to report experiences and ask questions
+about configuration and other topics. See lists.freedesktop.org for
+more information (the xorg@lists.freedesktop.org mailing list is the
+most appropriate place to ask X.Org and driver related questions).
+
+.SH "SEE ALSO"
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
+.SH AUTHORS
+Authors include: Ian Elliott, Rob Clark.
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..86209ef
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,48 @@
+# Copyright © 2011 Texas Instruments Incorporated
+#
+# 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.
+#
+# Authors:
+# Ian Elliott <ianelliottus@yahoo.com>
+# Rob Clark <rob@ti.com>
+
+# 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.
+
+# TODO: probably should have configure script check for what is supported..
+ERROR_CFLAGS = -Werror -Wall -Wdeclaration-after-statement -Wvla \
+ -Wpointer-arith -Wmissing-declarations -Wmissing-prototypes \
+ -Wwrite-strings -Wformat-nonliteral -Wformat-security \
+ -Wold-style-definition -Winit-self -Wmissing-include-dirs \
+ -Waddress -Waggregate-return -Wno-multichar -Wnested-externs
+
+AM_CFLAGS = @XORG_CFLAGS@ $(ERROR_CFLAGS)
+omap_drv_la_LTLIBRARIES = omap_drv.la
+omap_drv_la_LDFLAGS = -module -avoid-version -no-undefined
+omap_drv_ladir = @moduledir@/drivers
+
+omap_drv_la_SOURCES = \
+ drmmode_display.c \
+ omap_exa_common.c \
+ omap_exa_null.c \
+ omap_drm.c \
+ omap_driver.c
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
new file mode 100644
index 0000000..c1e79ad
--- /dev/null
+++ b/src/drmmode_display.c
@@ -0,0 +1,1180 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2008 Maarten Maathuis
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Ian Elliott <ianelliottus@yahoo.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xorgVersion.h"
+
+
+
+#include <sys/stat.h>
+
+
+
+
+// START: THE FOLLOWING #include STATEMENTS WERE COPIED FROM "nv_include.h";
+ // FIXME - DETERMINE WHICH OF THESE ARE REALLY/STILL NEEDED FOR THE TI DRIVER:
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#define PPC_MMIO_IS_BE
+#include "compiler.h"
+
+/* Drivers for PCI hardware need this */
+#include "xf86PciInfo.h"
+
+/* Drivers that need to access the PCI config space directly need this */
+#include "xf86Pci.h"
+
+/* All drivers initialising the SW cursor need this */
+#include "mipointer.h"
+
+/* All drivers implementing backing store need this */
+#include "mibstore.h"
+
+#include "micmap.h"
+
+#include "xf86DDC.h"
+
+#include "vbe.h"
+
+#include "xf86RandR12.h"
+
+//#include "nv_const.h"
+
+#include "dixstruct.h"
+#include "scrnintstr.h"
+
+#include "fb.h"
+
+#include "xf86cmap.h"
+#include "shadowfb.h"
+
+#include "xf86xv.h"
+#include <X11/extensions/Xv.h>
+
+#include "xf86Cursor.h"
+#include "xf86DDC.h"
+
+#include "region.h"
+
+#include <X11/extensions/randr.h>
+
+#ifdef HAVE_XEXTPROTO_71
+#include <X11/extensions/dpmsconst.h>
+#else
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+#endif
+
+// END: THE PREVIOUS #include STATEMENTS WERE COPIED FROM "nv_include.h";
+
+
+
+
+#include "omap_driver.h"
+
+// START: SOME OTHER #include STATEMENTS THAT I NEEDED TO COMPILE.
+ // FIXME - DETERMINE WHICH OF THESE ARE REALLY/STILL NEEDED, AND HOW TO
+ // COALESCE THEM WITH THE OTHER #include STATEMENTS:
+#include "xf86Crtc.h"
+// END: SOME OTHER #include STATEMENTS THAT I NEEDED TO COMPILE.
+
+
+
+
+#include "xf86drmMode.h"
+#include "X11/Xatom.h"
+
+#include <sys/ioctl.h>
+#include <libudev.h>
+
+typedef struct {
+ int fd;
+ uint32_t fb_id;
+ drmModeResPtr mode_res;
+ int cpp;
+ struct udev_monitor *uevent_monitor;
+ InputHandlerProc uevent_handler;
+} drmmode_rec, *drmmode_ptr;
+
+typedef struct {
+ drmmode_ptr drmmode;
+ drmModeCrtcPtr mode_crtc;
+#if 0
+ // Fixme - We need different code to deal with a cursor on OMAP4:
+ struct nouveau_bo *cursor;
+ struct nouveau_bo *rotate_bo;
+#endif
+ uint32_t rotate_pitch;
+ PixmapPtr rotate_pixmap;
+ uint32_t rotate_fb_id;
+ Bool cursor_visible;
+} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
+
+typedef struct {
+ drmModePropertyPtr mode_prop;
+ int index; /* Index within the kernel-side property arrays for
+ * this connector. */
+ int num_atoms; /* if range prop, num_atoms == 1; if enum prop,
+ * num_atoms == num_enums + 1 */
+ Atom *atoms;
+} drmmode_prop_rec, *drmmode_prop_ptr;
+
+typedef struct {
+ drmmode_ptr drmmode;
+ int output_id;
+ drmModeConnectorPtr mode_output;
+ drmModeEncoderPtr mode_encoder;
+ drmModePropertyBlobPtr edid_blob;
+ int num_props;
+ drmmode_prop_ptr props;
+} drmmode_output_private_rec, *drmmode_output_private_ptr;
+
+static void drmmode_output_dpms(xf86OutputPtr output, int mode);
+void drmmode_remove_fb(ScrnInfoPtr pScrn);
+
+#if 0
+static PixmapPtr
+drmmode_pixmap_wrap(ScreenPtr pScreen, int width, int height, int depth,
+ int bpp, int pitch, struct nouveau_bo *bo)
+{
+ PixmapPtr ppix;
+
+ ppix = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0);
+ if (!ppix)
+ return NULL;
+
+ pScreen->ModifyPixmapHeader(ppix, width, height, depth, bpp,
+ pitch, NULL);
+ nouveau_bo_ref(bo, &nouveau_pixmap(ppix)->bo);
+
+ return ppix;
+}
+#endif
+
+static void
+drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
+ DisplayModePtr mode)
+{
+ memset(mode, 0, sizeof(DisplayModeRec));
+ mode->status = MODE_OK;
+
+ mode->Clock = kmode->clock;
+
+ mode->HDisplay = kmode->hdisplay;
+ mode->HSyncStart = kmode->hsync_start;
+ mode->HSyncEnd = kmode->hsync_end;
+ mode->HTotal = kmode->htotal;
+ mode->HSkew = kmode->hskew;
+
+ mode->VDisplay = kmode->vdisplay;
+ mode->VSyncStart = kmode->vsync_start;
+ mode->VSyncEnd = kmode->vsync_end;
+ mode->VTotal = kmode->vtotal;
+ mode->VScan = kmode->vscan;
+
+ mode->Flags = kmode->flags; //& FLAG_BITS;
+ mode->name = strdup(kmode->name);
+
+ DEBUG_MSG("copy mode %s (%p %p)", kmode->name, mode->name, mode);
+
+ if (kmode->type & DRM_MODE_TYPE_DRIVER)
+ mode->type = M_T_DRIVER;
+ if (kmode->type & DRM_MODE_TYPE_PREFERRED)
+ mode->type |= M_T_PREFERRED;
+
+ xf86SetModeCrtc (mode, pScrn->adjustFlags);
+} /* drmmode_ConvertFromKMode() */
+
+static void
+drmmode_ConvertToKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode,
+ DisplayModePtr mode)
+{
+ memset(kmode, 0, sizeof(*kmode));
+
+ kmode->clock = mode->Clock;
+ kmode->hdisplay = mode->HDisplay;
+ kmode->hsync_start = mode->HSyncStart;
+ kmode->hsync_end = mode->HSyncEnd;
+ kmode->htotal = mode->HTotal;
+ kmode->hskew = mode->HSkew;
+
+ kmode->vdisplay = mode->VDisplay;
+ kmode->vsync_start = mode->VSyncStart;
+ kmode->vsync_end = mode->VSyncEnd;
+ kmode->vtotal = mode->VTotal;
+ kmode->vscan = mode->VScan;
+
+ kmode->flags = mode->Flags; //& FLAG_BITS;
+ if (mode->name)
+ strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
+ kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+} /* drmmode_ConvertToKMode() */
+
+static void
+drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
+{
+ // FIXME - Implement this function
+} /* drmmode_crtc_dpms() */
+
+static Bool
+drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+ Rotation rotation, int x, int y)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int saved_x, saved_y;
+ Rotation saved_rotation;
+ DisplayModeRec saved_mode;
+ uint32_t *output_ids = NULL;
+ int output_count = 0;
+ int ret = TRUE;
+ int i;
+ int fb_id;
+ drmModeModeInfo kmode;
+
+ TRACE_ENTER();
+
+ /* remove old fb if it exists */
+ drmmode_remove_fb(pScrn);
+
+ if (drmmode->fb_id == 0) {
+ unsigned int pitch =
+ OMAPCalculateStride(pScrn->virtualX, pScrn->bitsPerPixel);
+
+ DEBUG_MSG("create framebuffer: %dx%d",
+ pScrn->virtualX, pScrn->virtualY);
+
+ ret = drmModeAddFB(drmmode->fd,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->depth, pScrn->bitsPerPixel,
+ pitch, omap_bo_handle(pOMAP->scanout),
+ &drmmode->fb_id);
+ if (ret < 0) {
+ // Fixme - improve this error message:
+ ErrorF("failed to add fb\n");
+ return FALSE;
+ }
+ }
+
+ /* Save the current mode in case there's a problem: */
+ saved_mode = crtc->mode;
+ saved_x = crtc->x;
+ saved_y = crtc->y;
+ saved_rotation = crtc->rotation;
+
+ /* Set the new mode: */
+ crtc->mode = *mode;
+ crtc->x = x;
+ crtc->y = y;
+ crtc->rotation = rotation;
+
+ output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
+ if (!output_ids) {
+ // Fixme - have an error message?
+ ret = FALSE;
+ goto done;
+ }
+
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ drmmode_output_private_ptr drmmode_output;
+
+ if (output->crtc != crtc)
+ continue;
+
+ drmmode_output = output->driver_private;
+ output_ids[output_count] =
+ drmmode_output->mode_output->connector_id;
+ output_count++;
+ }
+
+ if (!xf86CrtcRotate(crtc))
+ goto done;
+
+ // Fixme - Intel puts this function here, and Nouveau puts it at the end
+ // of this function -> determine what's best for TI'S OMAP4:
+ crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
+ crtc->gamma_blue, crtc->gamma_size);
+
+ drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
+
+ fb_id = drmmode->fb_id;
+ if (drmmode_crtc->rotate_fb_id) {
+ fb_id = drmmode_crtc->rotate_fb_id;
+ x = 0;
+ y = 0;
+ }
+ ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ fb_id, x, y, output_ids, output_count, &kmode);
+ if (ret) {
+ xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+ "failed to set mode: %s\n", strerror(-ret));
+ } else {
+ ret = TRUE;
+ }
+
+ // FIXME - DO WE NEED TO CALL TO THE PVR EXA/DRI2 CODE TO UPDATE THEM???
+
+ /* Turn on any outputs on this crtc that may have been disabled: */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+
+ if (output->crtc != crtc)
+ continue;
+
+ drmmode_output_dpms(output, DPMSModeOn);
+ }
+
+ // Fixme - Intel puts a call to set GEM sizes here; do we need to do
+ // something like that?
+
+ if (pScrn->pScreen)
+ xf86_reload_cursors(pScrn->pScreen);
+
+done:
+ if (output_ids) {
+ free(output_ids);
+ }
+ if (!ret) {
+ /* If there was a problem, resture the old mode: */
+ crtc->x = saved_x;
+ crtc->y = saved_y;
+ crtc->rotation = saved_rotation;
+ crtc->mode = saved_mode;
+ }
+
+ TRACE_EXIT();
+ return ret;
+} /* drmmode_set_mode_major() */
+
+static void
+drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+#if 0 // Fixme - address this function when we address HW cursor functionality
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
+#endif
+} /* drmmode_set_cursor_position() */
+
+static void
+drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
+{
+#if 0 // Fixme - address this function when we address HW cursor functionality
+#endif
+} /* drmmode_load_cursor_argb() */
+
+static void
+drmmode_hide_cursor(xf86CrtcPtr crtc)
+{
+#if 0 // Fixme - address this function when we address HW cursor functionality
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ 0, 64, 64);
+ drmmode_crtc->cursor_visible = FALSE;
+#endif
+} /* drmmode_hide_cursor() */
+
+static void
+drmmode_show_cursor(xf86CrtcPtr crtc)
+{
+#if 0 // Fixme - address this function when we address HW cursor functionality
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ // Fixme - Do we may need a different data structure for the cursor handle?:
+ drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ drmmode_crtc->cursor->handle, 64, 64);
+
+ drmmode_crtc->cursor_visible = TRUE;
+#endif
+} /* drmmode_show_cursor() */
+
+static void
+drmmode_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
+ int size)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int ret;
+
+ ret = drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ size, red, green, blue);
+ if (ret != 0) {
+ xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
+ "failed to set gamma: %s\n", strerror(-ret));
+ }
+}
+
+static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
+ .dpms = drmmode_crtc_dpms,
+ .set_mode_major = drmmode_set_mode_major,
+ .set_cursor_position = drmmode_set_cursor_position,
+ .show_cursor = drmmode_show_cursor,
+ .hide_cursor = drmmode_hide_cursor,
+ .load_cursor_argb = drmmode_load_cursor_argb,
+ .gamma_set = drmmode_gamma_set,
+};
+
+
+static void
+drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+ xf86CrtcPtr crtc;
+ drmmode_crtc_private_ptr drmmode_crtc;
+
+ TRACE_ENTER();
+
+ crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
+ if (crtc == NULL)
+ return;
+
+ drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
+ drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd,
+ drmmode->mode_res->crtcs[num]);
+ drmmode_crtc->drmmode = drmmode;
+
+// FIXME - potentially add code to allocate a HW cursor here.
+
+ crtc->driver_private = drmmode_crtc;
+
+ TRACE_EXIT();
+ return;
+} /* drmmode_crtc_init() */
+
+static xf86OutputStatus
+drmmode_output_detect(xf86OutputPtr output)
+{
+ /* go to the hw and retrieve a new output struct */
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ xf86OutputStatus status;
+ drmModeFreeConnector(drmmode_output->mode_output);
+
+ drmmode_output->mode_output =
+ drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
+
+ switch (drmmode_output->mode_output->connection) {
+ case DRM_MODE_CONNECTED:
+ status = XF86OutputStatusConnected;
+ break;
+ case DRM_MODE_DISCONNECTED:
+ status = XF86OutputStatusDisconnected;
+ break;
+ default:
+ case DRM_MODE_UNKNOWNCONNECTION:
+ status = XF86OutputStatusUnknown;
+ break;
+ }
+ return status;
+}
+
+static Bool
+drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
+{
+ if (mode->type & M_T_DEFAULT)
+ /* Default modes are harmful here. */
+ return MODE_BAD;
+
+ return MODE_OK;
+}
+
+static DisplayModePtr
+drmmode_output_get_modes(xf86OutputPtr output)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ DisplayModePtr Modes = NULL, Mode;
+ drmModePropertyPtr props;
+ xf86MonPtr ddc_mon = NULL;
+ int i;
+
+ /* look for an EDID property */
+ for (i = 0; i < koutput->count_props; i++) {
+ props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ if (!props || !(props->flags & DRM_MODE_PROP_BLOB))
+ continue;
+
+ if (!strcmp(props->name, "EDID")) {
+ if (drmmode_output->edid_blob)
+ drmModeFreePropertyBlob(drmmode_output->edid_blob);
+ drmmode_output->edid_blob =
+ drmModeGetPropertyBlob(drmmode->fd,
+ koutput->prop_values[i]);
+ }
+ drmModeFreeProperty(props);
+ }
+
+ if (drmmode_output->edid_blob)
+ ddc_mon = xf86InterpretEDID(pScrn->scrnIndex,
+ drmmode_output->edid_blob->data);
+
+ if (ddc_mon) {
+ XF86_CRTC_CONFIG_PTR(pScrn)->debug_modes = TRUE;
+ xf86PrintEDID(ddc_mon);
+ xf86OutputSetEDID(output, ddc_mon);
+ xf86SetDDCproperties(pScrn, ddc_mon);
+ }
+
+ DEBUG_MSG("count_modes: %d", koutput->count_modes);
+
+ /* modes should already be available */
+ for (i = 0; i < koutput->count_modes; i++) {
+ Mode = xnfalloc(sizeof(DisplayModeRec));
+
+ drmmode_ConvertFromKMode(pScrn, &koutput->modes[i],
+ Mode);
+ Modes = xf86ModesAdd(Modes, Mode);
+
+ }
+ return Modes;
+}
+
+static void
+drmmode_output_destroy(xf86OutputPtr output)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ int i;
+
+ if (drmmode_output->edid_blob)
+ drmModeFreePropertyBlob(drmmode_output->edid_blob);
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmModeFreeProperty(drmmode_output->props[i].mode_prop);
+ free(drmmode_output->props[i].atoms);
+ }
+ drmModeFreeConnector(drmmode_output->mode_output);
+ free(drmmode_output);
+ output->driver_private = NULL;
+}
+
+static void
+drmmode_output_dpms(xf86OutputPtr output, int mode)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr koutput = drmmode_output->mode_output;
+ drmModePropertyPtr props;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ int mode_id = -1, i;
+
+ for (i = 0; i < koutput->count_props; i++) {
+ props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ if (props && (props->flags && DRM_MODE_PROP_ENUM)) {
+ if (!strcmp(props->name, "DPMS")) {
+ mode_id = koutput->props[i];
+ drmModeFreeProperty(props);
+ break;
+ }
+ drmModeFreeProperty(props);
+ }
+ }
+
+ if (mode_id < 0)
+ return;
+
+ drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
+ mode_id, mode);
+}
+
+static Bool
+drmmode_property_ignore(drmModePropertyPtr prop)
+{
+ if (!prop)
+ return TRUE;
+ /* ignore blob prop */
+ if (prop->flags & DRM_MODE_PROP_BLOB)
+ return TRUE;
+ /* ignore standard property */
+ if (!strcmp(prop->name, "EDID") ||
+ !strcmp(prop->name, "DPMS"))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+drmmode_output_create_resources(xf86OutputPtr output)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmModeConnectorPtr mode_output = drmmode_output->mode_output;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ drmModePropertyPtr drmmode_prop;
+ uint32_t value;
+ int i, j, err;
+
+ drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
+ if (!drmmode_output->props)
+ return;
+
+ drmmode_output->num_props = 0;
+ for (i = 0, j = 0; i < mode_output->count_props; i++) {
+ drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
+ if (drmmode_property_ignore(drmmode_prop)) {
+ drmModeFreeProperty(drmmode_prop);
+ continue;
+ }
+ drmmode_output->props[j].mode_prop = drmmode_prop;
+ drmmode_output->props[j].index = i;
+ drmmode_output->num_props++;
+ j++;
+ }
+
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
+ drmmode_prop = p->mode_prop;
+
+ value = drmmode_output->mode_output->prop_values[p->index];
+
+ if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
+ INT32 range[2];
+
+ p->num_atoms = 1;
+ p->atoms = calloc(p->num_atoms, sizeof(Atom));
+ if (!p->atoms)
+ continue;
+ p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+ range[0] = drmmode_prop->values[0];
+ range[1] = drmmode_prop->values[1];
+ err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+ FALSE, TRUE,
+ drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+ 2, range);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+ XA_INTEGER, 32, PropModeReplace, 1,
+ &value, FALSE, FALSE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+ } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
+ p->num_atoms = drmmode_prop->count_enums + 1;
+ p->atoms = calloc(p->num_atoms, sizeof(Atom));
+ if (!p->atoms)
+ continue;
+ p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
+ for (j = 1; j <= drmmode_prop->count_enums; j++) {
+ struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
+ p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
+ }
+ err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
+ FALSE, FALSE,
+ drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
+ p->num_atoms - 1, (INT32 *)&p->atoms[1]);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRConfigureOutputProperty error, %d\n", err);
+ }
+ for (j = 0; j < drmmode_prop->count_enums; j++)
+ if (drmmode_prop->enums[j].value == value)
+ break;
+ /* there's always a matching value */
+ err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
+ XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, FALSE);
+ if (err != 0) {
+ xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
+ "RRChangeOutputProperty error, %d\n", err);
+ }
+ }
+ }
+}
+
+static Bool
+drmmode_output_set_property(xf86OutputPtr output, Atom property,
+ RRPropertyValuePtr value)
+{
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ int i, ret;
+
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
+
+ if (p->atoms[0] != property)
+ continue;
+
+ if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+ uint32_t val;
+
+ if (value->type != XA_INTEGER || value->format != 32 ||
+ value->size != 1)
+ return FALSE;
+ val = *(uint32_t *)value->data;
+
+ ret = drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
+ p->mode_prop->prop_id, (uint64_t)val);
+
+ if (ret)
+ return FALSE;
+
+ return TRUE;
+
+ } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+ Atom atom;
+ const char *name;
+ int j;
+
+ if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
+ return FALSE;
+ memcpy(&atom, value->data, 4);
+ name = NameForAtom(atom);
+
+ /* search for matching name string, then set its value down */
+ for (j = 0; j < p->mode_prop->count_enums; j++) {
+ if (!strcmp(p->mode_prop->enums[j].name, name)) {
+ ret = drmModeConnectorSetProperty(drmmode->fd,
+ drmmode_output->output_id,
+ p->mode_prop->prop_id,
+ p->mode_prop->enums[j].value);
+
+ if (ret)
+ return FALSE;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool
+drmmode_output_get_property(xf86OutputPtr output, Atom property)
+{
+
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ drmmode_ptr drmmode = drmmode_output->drmmode;
+ uint32_t value;
+ int err, i;
+
+ if (output->scrn->vtSema) {
+ drmModeFreeConnector(drmmode_output->mode_output);
+ drmmode_output->mode_output =
+ drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
+ }
+
+ for (i = 0; i < drmmode_output->num_props; i++) {
+ drmmode_prop_ptr p = &drmmode_output->props[i];
+ if (p->atoms[0] != property)
+ continue;
+
+ value = drmmode_output->mode_output->prop_values[p->index];
+
+ if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
+ err = RRChangeOutputProperty(output->randr_output,
+ property, XA_INTEGER, 32,
+ PropModeReplace, 1, &value,
+ FALSE, FALSE);
+
+ return !err;
+ } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
+ int j;
+
+ /* search for matching name string, then set its value down */
+ for (j = 0; j < p->mode_prop->count_enums; j++) {
+ if (p->mode_prop->enums[j].value == value)
+ break;
+ }
+
+ err = RRChangeOutputProperty(output->randr_output, property,
+ XA_ATOM, 32, PropModeReplace, 1,
+ &p->atoms[j+1], FALSE, FALSE);
+
+ return !err;
+ }
+ }
+
+ return FALSE;
+}
+
+static const xf86OutputFuncsRec drmmode_output_funcs = {
+ .create_resources = drmmode_output_create_resources,
+ .dpms = drmmode_output_dpms,
+ .detect = drmmode_output_detect,
+ .mode_valid = drmmode_output_mode_valid,
+ .get_modes = drmmode_output_get_modes,
+ .set_property = drmmode_output_set_property,
+ .get_property = drmmode_output_get_property,
+ .destroy = drmmode_output_destroy
+};
+
+// FIXME - Eliminate the following values that aren't accurate for OMAP4:
+const char *output_names[] = { "None",
+ "VGA",
+ "DVI-I",
+ "DVI-D",
+ "DVI-A",
+ "Composite",
+ "SVIDEO",
+ "LVDS",
+ "CTV",
+ "DIN",
+ "DP",
+ "HDMI",
+ "HDMI",
+ "TV",
+ "eDP",
+};
+#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
+
+static void
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+{
+ xf86OutputPtr output;
+ drmModeConnectorPtr koutput;
+ drmModeEncoderPtr kencoder;
+ drmmode_output_private_ptr drmmode_output;
+ char name[32];
+
+ TRACE_ENTER();
+
+ koutput = drmModeGetConnector(drmmode->fd,
+ drmmode->mode_res->connectors[num]);
+ if (!koutput)
+ return;
+
+ kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]);
+ if (!kencoder) {
+ drmModeFreeConnector(koutput);
+ return;
+ }
+
+ if (koutput->connector_type >= NUM_OUTPUT_NAMES)
+ snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
+ koutput->connector_type_id);
+ else
+ snprintf(name, 32, "%s-%d",
+ output_names[koutput->connector_type],
+ koutput->connector_type_id);
+
+ output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name);
+ if (!output) {
+ drmModeFreeEncoder(kencoder);
+ drmModeFreeConnector(koutput);
+ return;
+ }
+
+ drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
+ if (!drmmode_output) {
+ xf86OutputDestroy(output);
+ drmModeFreeConnector(koutput);
+ drmModeFreeEncoder(kencoder);
+ return;
+ }
+
+ drmmode_output->output_id = drmmode->mode_res->connectors[num];
+ drmmode_output->mode_output = koutput;
+ drmmode_output->mode_encoder = kencoder;
+ drmmode_output->drmmode = drmmode;
+
+ output->mm_width = koutput->mmWidth;
+ output->mm_height = koutput->mmHeight;
+ output->driver_private = drmmode_output;
+
+ output->possible_crtcs = kencoder->possible_crtcs;
+ output->possible_clones = kencoder->possible_clones;
+ output->interlaceAllowed = TRUE;
+#if 0
+// FIXME - check with Rob whether this is supported for OMAP4:
+ output->doubleScanAllowed = TRUE;
+#endif
+
+ TRACE_EXIT();
+ return;
+} /* drmmode_output_init() */
+
+static Bool
+drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
+{
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ ScreenPtr pScreen = pScrn->pScreen;
+ unsigned int pitch;
+
+ TRACE_ENTER();
+
+ /* if fb required size has changed, realloc! */
+
+ DEBUG_MSG("Resize! %dx%d", width, height);
+
+ pScrn->virtualX = width;
+ pScrn->virtualY = height;
+
+ pitch = OMAPCalculateStride(width, pScrn->bitsPerPixel);
+
+ if ((pitch * height) != omap_bo_size(pOMAP->scanout)) {
+ /* hmm, should we remove fb here.. we don't want to keep
+ * scanning out a deallocated buffer..
+ */
+ drmmode_remove_fb(pScrn);
+
+ /* delete old scanout buffer */
+ omap_bo_del(pOMAP->scanout);
+
+ DEBUG_MSG("allocating new scanout buffer: %dx%d (%d)",
+ width, height, pitch);
+
+ /* allocate new scanout buffer */
+ pOMAP->scanout = omap_bo_new(pOMAP->dev, height * pitch,
+ OMAP_BO_SCANOUT | OMAP_BO_WC);
+ if (!pOMAP->scanout) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Error reallocating scanout buffer\n");
+ return FALSE;
+ }
+ }
+
+ if (pScreen && pScreen->ModifyPixmapHeader) {
+ PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ pScreen->ModifyPixmapHeader(rootPixmap,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->depth, pScrn->bitsPerPixel, pitch,
+ omap_bo_map(pOMAP->scanout));
+ }
+
+ TRACE_EXIT();
+ return TRUE;
+} /* drmmode_xf86crtc_resize() */
+
+
+static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
+ drmmode_xf86crtc_resize
+};
+
+
+Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
+{
+ xf86CrtcConfigPtr xf86_config;
+ drmmode_ptr drmmode;
+ int i;
+
+ TRACE_ENTER();
+
+ drmmode = malloc(sizeof *drmmode);
+ drmmode->fd = fd;
+ drmmode->fb_id = 0;
+
+ xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
+ xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+
+ drmmode->cpp = cpp;
+ drmmode->mode_res = drmModeGetResources(drmmode->fd);
+ if (!drmmode->mode_res) {
+ return FALSE;
+ } else {
+ DEBUG_MSG("Got KMS resources");
+ DEBUG_MSG(" %d connectors, %d encoders",
+ drmmode->mode_res->count_connectors,
+ drmmode->mode_res->count_encoders);
+ DEBUG_MSG(" %d crtcs, %d fbs",
+ drmmode->mode_res->count_crtcs, drmmode->mode_res->count_fbs);
+ DEBUG_MSG(" %dx%d minimum resolution",
+ drmmode->mode_res->min_width, drmmode->mode_res->min_height);
+ DEBUG_MSG(" %dx%d maximum resolution",
+ drmmode->mode_res->max_width, drmmode->mode_res->max_height);
+ }
+ xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width,
+ drmmode->mode_res->max_height);
+ for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
+ drmmode_crtc_init(pScrn, drmmode, i);
+
+ for (i = 0; i < drmmode->mode_res->count_connectors; i++)
+ drmmode_output_init(pScrn, drmmode, i);
+
+ xf86InitialConfiguration(pScrn, TRUE);
+
+ TRACE_EXIT();
+
+ return TRUE;
+} /* drmmode_pre_init() */
+
+void
+drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y, int flags)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86OutputPtr output = config->output[config->compat_output];
+ xf86CrtcPtr crtc = output->crtc;
+
+ if (!crtc || !crtc->enabled)
+ return;
+
+ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, x, y);
+}
+
+void
+drmmode_remove_fb(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ xf86CrtcPtr crtc = NULL;
+ drmmode_crtc_private_ptr drmmode_crtc;
+ drmmode_ptr drmmode;
+
+ if (config)
+ crtc = config->crtc[0];
+ if (!crtc)
+ return;
+
+ drmmode_crtc = crtc->driver_private;
+ drmmode = drmmode_crtc->drmmode;
+
+ if (drmmode->fb_id)
+ drmModeRmFB(drmmode->fd, drmmode->fb_id);
+ drmmode->fb_id = 0;
+}
+
+
+/*
+ * Hot Plug Event handling:
+ */
+
+static drmmode_ptr
+drmmode_from_scrn(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ drmmode_crtc_private_ptr drmmode_crtc;
+
+ drmmode_crtc = xf86_config->crtc[0]->driver_private;
+ return drmmode_crtc->drmmode;
+} /* drmmode_from_scrn() */
+
+static void
+drmmode_handle_uevents(int fd, void *closure)
+{
+ ScrnInfoPtr pScrn = closure;
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
+ struct udev_device *dev;
+ const char *hotplug;
+ struct stat s;
+ dev_t udev_devnum;
+
+ dev = udev_monitor_receive_device(drmmode->uevent_monitor);
+ if (!dev)
+ return;
+
+// FIXME - Do we need to keep this code, which Rob originally wrote
+// (i.e. up thru the "if" statement)?:
+
+ /*
+ * Check to make sure this event is directed at our
+ * device (by comparing dev_t values), then make
+ * sure it's a hotplug event (HOTPLUG=1)
+ */
+ udev_devnum = udev_device_get_devnum(dev);
+ fstat(pOMAP->drmFD, &s);
+
+ hotplug = udev_device_get_property_value(dev, "HOTPLUG");
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hotplug=%s, match=%d\n", hotplug,
+ memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)));
+
+ if (memcmp(&s.st_rdev, &udev_devnum, sizeof (dev_t)) == 0 &&
+ hotplug && atoi(hotplug) == 1) {
+ RRGetInfo(screenInfo.screens[pScrn->scrnIndex], TRUE);
+ }
+ udev_device_unref(dev);
+} /* drmmode_handle_uevents() */
+
+void
+drmmode_uevent_init(ScrnInfoPtr pScrn)
+{
+ drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
+ struct udev *u;
+ struct udev_monitor *mon;
+
+ TRACE_ENTER();
+
+ u = udev_new();
+ if (!u)
+ return;
+ mon = udev_monitor_new_from_netlink(u, "udev");
+ if (!mon) {
+ udev_unref(u);
+ return;
+ }
+
+ if (udev_monitor_filter_add_match_subsystem_devtype(mon,
+ "drm",
+ "drm_minor") < 0 ||
+ udev_monitor_enable_receiving(mon) < 0) {
+ udev_monitor_unref(mon);
+ udev_unref(u);
+ return;
+ }
+
+ drmmode->uevent_handler =
+ xf86AddGeneralHandler(udev_monitor_get_fd(mon),
+ drmmode_handle_uevents, pScrn);
+
+ drmmode->uevent_monitor = mon;
+
+ TRACE_EXIT();
+} /* drmmode_uevent_init() */
+
+void
+drmmode_uevent_fini(ScrnInfoPtr pScrn)
+{
+ drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
+
+ TRACE_ENTER();
+
+ if (drmmode->uevent_handler) {
+ struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
+ xf86RemoveGeneralHandler(drmmode->uevent_handler);
+
+ udev_monitor_unref(drmmode->uevent_monitor);
+ udev_unref(u);
+ }
+
+ TRACE_EXIT();
+} /* drmmode_uevent_fini() */
diff --git a/src/omap_driver.c b/src/omap_driver.c
new file mode 100644
index 0000000..a68602c
--- /dev/null
+++ b/src/omap_driver.c
@@ -0,0 +1,989 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Ian Elliott <ianelliottus@yahoo.com>
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "omap_driver.h"
+
+
+Bool omapDebug = 0;
+
+/*
+ * Forward declarations:
+ */
+static const OptionInfoRec *OMAPAvailableOptions(int chipid, int busid);
+static void OMAPIdentify(int flags);
+static Bool OMAPProbe(DriverPtr drv, int flags);
+static Bool OMAPPreInit(ScrnInfoPtr pScrn, int flags);
+static Bool OMAPScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
+ char **argv);
+static void OMAPLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual);
+static Bool OMAPCloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool OMAPCreateScreenResources(ScreenPtr pScreen);
+static void OMAPBlockHandler(int i, pointer blockData, pointer pTimeout,
+ pointer pReadmask);
+static Bool OMAPSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
+static void OMAPAdjustFrame(int scrnIndex, int x, int y, int flags);
+static Bool OMAPEnterVT(int scrnIndex, int flags);
+static void OMAPLeaveVT(int scrnIndex, int flags);
+static void OMAPFreeScreen(int scrnIndex, int flags);
+
+
+
+/**
+ * A structure used by the XFree86 code when loading this driver, so that it
+ * can access the Probe() function, and other functions/info that it uses
+ * before it calls the Probe() function. The name of this structure must be
+ * the all-upper-case version of the driver name.
+ */
+_X_EXPORT DriverRec OMAP = {
+ OMAP_VERSION,
+ (char *)OMAP_DRIVER_NAME,
+ OMAPIdentify,
+ OMAPProbe,
+ OMAPAvailableOptions,
+ NULL,
+ 0,
+ NULL,
+#ifdef XSERVER_LIBPCIACCESS
+ NULL,
+ NULL
+#endif
+};
+
+/** Supported "chipsets." */
+static SymTabRec OMAPChipsets[] = {
+ /* OMAP2 and earlier not supported */
+ { 0x3430, "OMAP3430 with PowerVR SGX530" },
+ { 0x3630, "OMAP3630 with PowerVR SGX530" },
+ { 0x4430, "OMAP4430 with PowerVR SGX540" },
+ { 0x4460, "OMAP4460 with PowerVR SGX540" },
+ /* { 4470, "OMAP4470 with <redacted> ;-)" }, */
+ {-1, NULL }
+};
+
+/** Supported options, as enum values. */
+typedef enum {
+ OPTION_DEBUG,
+ OPTION_NO_ACCEL,
+ /* TODO: probably need to add an option to let user specify bus-id */
+} OMAPOpts;
+
+/** Supported options. */
+static const OptionInfoRec OMAPOptions[] = {
+ { OPTION_DEBUG, "Debug", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_NO_ACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+/**
+ * Helper function for opening a connection to the DRM.
+ */
+
+static int
+OMAPOpenDRM(int n)
+{
+ char bus_id[32];
+ snprintf(bus_id, sizeof(bus_id), "platform:omapdrm:%02d", n);
+ return drmOpen("omapdrm", bus_id);
+}
+
+static Bool
+OMAPOpenDRMMaster(ScrnInfoPtr pScrn, int n)
+{
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ drmSetVersion sv;
+ int err;
+
+ pOMAP->drmFD = OMAPOpenDRM(n);
+ if (pOMAP->drmFD == -1) {
+ ERROR_MSG("Cannot open a connection with the DRM.");
+ return FALSE;
+ }
+
+ /* Check that what we opened was a master or a master-capable FD,
+ * by setting the version of the interface we'll use to talk to it.
+ * (see DRIOpenDRMMaster() in DRI1)
+ */
+ sv.drm_di_major = 1;
+ sv.drm_di_minor = 1;
+ sv.drm_dd_major = -1;
+ sv.drm_dd_minor = -1;
+ err = drmSetInterfaceVersion(pOMAP->drmFD, &sv);
+ if (err != 0) {
+ ERROR_MSG("Cannot set the DRM interface version.");
+ drmClose(pOMAP->drmFD);
+ pOMAP->drmFD = -1;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+/**
+ * Helper function for closing a connection to the DRM.
+ */
+static void
+OMAPCloseDRMMaster(ScrnInfoPtr pScrn)
+{
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+
+ if (pOMAP && (pOMAP->drmFD > 0)) {
+ drmClose(pOMAP->drmFD);
+ pOMAP->drmFD = -1;
+ }
+}
+
+
+
+/**
+ * Helper function for calculating the stride of pixmaps.
+ * TODO get stride requirements from kernel driver, or from EXA module,
+ * rather than hard-coding..
+ */
+#define STRIDE_BOUNDARY 32
+unsigned int
+OMAPCalculateStride(unsigned int width, unsigned int bitsPerPixel)
+{
+ unsigned int alignedWidth;
+
+ alignedWidth = (width + (STRIDE_BOUNDARY - 1)) & ~(STRIDE_BOUNDARY - 1);
+ return ((alignedWidth * bitsPerPixel) + 7) / 8;
+}
+
+
+static Bool
+OMAPMapMem(ScrnInfoPtr pScrn)
+{
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ int pitch;
+
+ pitch = OMAPCalculateStride(pScrn->virtualX, pScrn->bitsPerPixel);
+
+ DEBUG_MSG("allocating new scanout buffer: %dx%d (%d)",
+ pScrn->virtualX, pScrn->virtualY, pitch);
+
+ pOMAP->scanout = omap_bo_new(pOMAP->dev, pScrn->virtualY * pitch,
+ OMAP_BO_SCANOUT | OMAP_BO_WC);
+ if (!pOMAP->scanout) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Error allocating scanout buffer\n");
+ return FALSE;
+ }
+
+ pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
+
+ return TRUE;
+}
+
+
+static Bool
+OMAPUnmapMem(ScrnInfoPtr pScrn)
+{
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ drmmode_remove_fb(pScrn);
+ omap_bo_del(pOMAP->scanout);
+ pOMAP->scanout = NULL;
+ return TRUE;
+}
+
+
+
+/** Let the XFree86 code know the Setup() function. */
+static MODULESETUPPROTO(OMAPSetup);
+
+/** Provide basic version information to the XFree86 code. */
+static XF86ModuleVersionInfo OMAPVersRec =
+{
+ OMAP_DRIVER_NAME,
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ OMAP_MAJOR_VERSION, OMAP_MINOR_VERSION, OMAP_PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+/** Let the XFree86 code know about the VersRec and Setup() function. */
+_X_EXPORT XF86ModuleData omapModuleData = { &OMAPVersRec, OMAPSetup, NULL };
+
+
+/**
+ * The first function that the XFree86 code calls, after loading this module.
+ */
+static pointer
+OMAPSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ /* This module should be loaded only once, but check to be sure: */
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&OMAP, module, 0);
+
+ /* The return value must be non-NULL on success even though there is no
+ * TearDownProc.
+ */
+ return (pointer) 1;
+ } else {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ return NULL;
+ }
+}
+
+
+/**
+ * Allocate the driver's Screen-specific, "private" data structure and hook it
+ * into the ScrnInfoRec's driverPrivate field.
+ */
+static Bool
+OMAPGetRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate != NULL)
+ return TRUE;
+
+ pScrn->driverPrivate = calloc(1, sizeof(OMAPRec));
+ if (pScrn->driverPrivate == NULL)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/**
+ * Free the driver's Screen-specific, "private" data structure and NULL-out the
+ * ScrnInfoRec's driverPrivate field.
+ */
+static void
+OMAPFreeRec(ScrnInfoPtr pScrn)
+{
+ if (pScrn->driverPrivate == NULL)
+ return;
+ free(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+}
+
+
+/**
+ * The mandatory AvailableOptions() function. It returns the available driver
+ * options to the "-configure" option, so that an xorg.conf file can be built
+ * and the user can see which options are available for them to use.
+ */
+static const OptionInfoRec *
+OMAPAvailableOptions(int chipid, int busid)
+{
+ return OMAPOptions;
+}
+
+
+
+/**
+ * The mandatory Identify() function. It is run before Probe(), and prints out
+ * an identifying message, which includes the chipset(s) the driver supports.
+ */
+static void
+OMAPIdentify(int flags)
+{
+ xf86PrintChipsets(OMAP_NAME, "Driver for TI OMAP", OMAPChipsets);
+}
+
+
+
+/**
+ * The driver's Probe() function. This function finds all instances of the
+ * TI OMAP hardware that the driver supports (from within the "xorg.conf"
+ * device sections), and for instances not already claimed by another driver,
+ * claim the instances, and allocate a ScrnInfoRec. Only minimal hardware
+ * probing is allowed here.
+ */
+static Bool
+OMAPProbe(DriverPtr drv, int flags)
+{
+ int i;
+ ScrnInfoPtr pScrn;
+ GDevPtr *devSections;
+ int numDevSections;
+ Bool foundScreen = FALSE;
+
+ if (flags & PROBE_DETECT) {
+ EARLY_ERROR_MSG("The %s driver does not support the \"-configure\" or "
+ "\"-probe\" command line arguments.", OMAP_NAME);
+ return FALSE;
+ }
+
+ /* Get the "xorg.conf" file device sections that match this driver, and
+ * return (error out) if there are none:
+ */
+ numDevSections = xf86MatchDevice(OMAP_DRIVER_NAME, &devSections);
+ if (numDevSections <= 0) {
+ EARLY_ERROR_MSG("Did not find any matching device section in "
+ "configuration file");
+ return FALSE;
+ }
+
+ for (i = 0; i < numDevSections; i++) {
+ int fd = OMAPOpenDRM(i);
+ if (fd != -1) {
+ int entity = xf86ClaimNoSlot(drv, 0, devSections[i], TRUE);
+
+ pScrn = xf86AllocateScreen(drv, 0);
+ if (!pScrn) {
+ EARLY_ERROR_MSG("Cannot allocate a ScrnInfoPtr");
+ return FALSE;
+ }
+ xf86AddEntityToScreen(pScrn, entity);
+
+ foundScreen = TRUE;
+
+ pScrn->driverVersion = OMAP_VERSION;
+ pScrn->driverName = (char *)OMAP_DRIVER_NAME;
+ pScrn->name = (char *)OMAP_NAME;
+ pScrn->Probe = OMAPProbe;
+ pScrn->PreInit = OMAPPreInit;
+ pScrn->ScreenInit = OMAPScreenInit;
+ pScrn->SwitchMode = OMAPSwitchMode;
+ pScrn->AdjustFrame = OMAPAdjustFrame;
+ pScrn->EnterVT = OMAPEnterVT;
+ pScrn->LeaveVT = OMAPLeaveVT;
+ pScrn->FreeScreen = OMAPFreeScreen;
+
+ /* would be nice to be able to keep the connection open.. but
+ * currently we don't allocate the private until PreInit
+ */
+ drmClose(fd);
+ }
+ }
+ free(devSections);
+ return foundScreen;
+}
+
+
+
+/**
+ * The driver's PreInit() function. Additional hardware probing is allowed
+ * now, including display configuration.
+ */
+static Bool
+OMAPPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ OMAPPtr pOMAP;
+ int default_depth, fbbpp;
+ rgb defaultWeight = { 0, 0, 0 };
+ rgb defaultMask = { 0, 0, 0 };
+ Gamma defaultGamma = { 0.0, 0.0, 0.0 };
+ uint64_t value;
+ int i;
+
+ TRACE_ENTER();
+
+ if (flags & PROBE_DETECT) {
+ ERROR_MSG("The %s driver does not support the \"-configure\" or "
+ "\"-probe\" command line arguments.", OMAP_NAME);
+ return FALSE;
+ }
+
+ /* Check the number of entities, and fail if it isn't one. */
+ if (pScrn->numEntities != 1) {
+ ERROR_MSG("Driver expected 1 entity, but found %d for screen %d",
+ pScrn->numEntities, pScrn->scrnIndex);
+ return FALSE;
+ }
+
+ /* Allocate the driver's Screen-specific, "private" data structure: */
+ OMAPGetRec(pScrn);
+ pOMAP = OMAPPTR(pScrn);
+
+ pOMAP->pEntityInfo = xf86GetEntityInfo(pScrn->entityList[0]);
+
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ /* Get the current depth, and set it for XFree86: */
+ default_depth = 24; /* TODO: get from kernel */
+ fbbpp = 32; /* TODO: get from kernel */
+
+ if (!xf86SetDepthBpp(pScrn, default_depth, 0, fbbpp, Support32bppFb)) {
+ /* The above function prints an error message. */
+ goto fail;
+ }
+ xf86PrintDepthBpp(pScrn);
+
+ /* Set the color weight: */
+ if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) {
+ /* The above function prints an error message. */
+ goto fail;
+ }
+
+ /* Set the gamma: */
+ if (!xf86SetGamma(pScrn, defaultGamma)) {
+ /* The above function prints an error message. */
+ goto fail;
+ }
+
+ /* Visual init: */
+ if (!xf86SetDefaultVisual(pScrn, -1)) {
+ /* The above function prints an error message. */
+ goto fail;
+ }
+
+ /* We don't support 8-bit depths: */
+ if (pScrn->depth < 16) {
+ ERROR_MSG("The requested default visual (%s) has an unsupported "
+ "depth (%d).",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ goto fail;
+ }
+
+ /* Using a programmable clock: */
+ pScrn->progClock = TRUE;
+
+ /* Open a connection to the DRM, so we can communicate with the KMS code: */
+ if (!OMAPOpenDRMMaster(pScrn, 0)) {
+ goto fail;
+ }
+ DEBUG_MSG("Became DRM master.");
+
+ /* create DRM device instance: */
+ pOMAP->dev = omap_device_new(pOMAP->drmFD);
+
+ /* query chip-id: */
+ if (omap_get_param(pOMAP->dev, OMAP_PARAM_CHIPSET_ID, &value)) {
+ ERROR_MSG("Could not read chipset");
+ goto fail;
+ }
+ pOMAP->chipset = value;
+
+ /* find matching chipset name: */
+ for (i = 0; OMAPChipsets[i].name; i++) {
+ if (OMAPChipsets[i].token == pOMAP->chipset) {
+ pScrn->chipset = (char *)OMAPChipsets[i].name;
+ break;
+ }
+ }
+
+ if (!pScrn->chipset) {
+ ERROR_MSG("Unknown chipset: %s", pScrn->chipset);
+ goto fail;
+ }
+
+ INFO_MSG("Found chipset: %s", pScrn->chipset);
+
+ /*
+ * Process the "xorg.conf" file options:
+ */
+ xf86CollectOptions(pScrn, NULL);
+ if (!(pOMAP->pOptionInfo = calloc(1, sizeof(OMAPOptions))))
+ return FALSE;
+ memcpy(pOMAP->pOptionInfo, OMAPOptions, sizeof(OMAPOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pOMAP->pEntityInfo->device->options,
+ pOMAP->pOptionInfo);
+
+ /* Determine if the user wants debug messages turned on: */
+ omapDebug = xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_DEBUG, FALSE);
+
+ /* Determine if the user wants to disable acceleration: */
+ pOMAP->NoAccel =
+ xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_NO_ACCEL, FALSE);
+
+ /*
+ * Select the video modes:
+ */
+ INFO_MSG("Setting the video modes ...");
+
+ /* Don't call drmCheckModesettingSupported() as its written only for
+ * PCI devices.
+ */
+
+ /* Do initial KMS setup: */
+ if (!drmmode_pre_init(pScrn, pOMAP->drmFD, (pScrn->bitsPerPixel >> 3))) {
+ ERROR_MSG("Cannot get KMS resources");
+ } else {
+ INFO_MSG("Got KMS resources");
+ }
+
+ xf86RandR12PreInit(pScrn);
+
+ /* Let XFree86 calculate or get (from command line) the display DPI: */
+ xf86SetDpi(pScrn, 0, 0);
+
+ /* Ensure we have a supported depth: */
+ switch (pScrn->bitsPerPixel) {
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ ERROR_MSG("The requested number of bits per pixel (%d) is unsupported.",
+ pScrn->bitsPerPixel);
+ goto fail;
+ }
+
+
+ /* Load external sub-modules now: */
+
+ if (!(xf86LoadSubModule(pScrn, "dri2") &&
+ xf86LoadSubModule(pScrn, "exa") &&
+ xf86LoadSubModule(pScrn, "fb"))) {
+ goto fail;
+ }
+
+ switch (pOMAP->chipset) {
+ case 0x3430:
+ case 0x3630:
+ case 0x4430:
+ case 0x4460:
+ if (xf86LoadSubModule(pScrn, SUB_MODULE_PVR)) {
+ INFO_MSG("Loaded the %s sub-module", SUB_MODULE_PVR);
+ } else {
+ INFO_MSG("Cannot load the %s sub-module", SUB_MODULE_PVR);
+ /* note that this is not fatal.. since IMG/PVR EXA module
+ * is closed source, it is only optional.
+ */
+ pOMAP->NoAccel = TRUE; /* don't call InitPowerVREXA() */
+ }
+ break;
+ /* case 0x4470: ..; break; */
+ default:
+ ERROR_MSG("Unsupported chipset: %d", pOMAP->chipset);
+ goto fail;
+ }
+
+ TRACE_EXIT();
+ return TRUE;
+
+fail:
+ TRACE_EXIT();
+ OMAPFreeRec(pScrn);
+ return FALSE;
+}
+
+
+
+/**
+ * The driver's ScreenInit() function. Fill in pScreen, map the frame buffer,
+ * save state, initialize the mode, etc.
+ */
+static Bool
+OMAPScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ VisualPtr visual;
+ xf86CrtcConfigPtr xf86_config;
+ int i;
+
+ TRACE_ENTER();
+
+#if 0
+ if (!pOMAP->NoAccel)
+ OMAPDRI2Init(pScreen);
+#endif
+
+ /* Allocate and map memory areas we need */
+ if (!OMAPMapMem(pScrn))
+ return FALSE;
+
+ xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+
+ /* need to point to new screen on server regeneration */
+ for (i = 0; i < xf86_config->num_crtc; i++)
+ xf86_config->crtc[i]->scrn = pScrn;
+ for (i = 0; i < xf86_config->num_output; i++)
+ xf86_config->output[i]->scrn = pScrn;
+
+ /*
+ * The next step is to setup the screen's visuals, and initialize the
+ * framebuffer code. In cases where the framebuffer's default
+ * choices for things like visual layouts and bits per RGB are OK,
+ * this may be as simple as calling the framebuffer's ScreenInit()
+ * function. If not, the visuals will need to be setup before calling
+ * a fb ScreenInit() function and fixed up after.
+ *
+ * For most PC hardware at depths >= 8, the defaults that fb uses
+ * are not appropriate. In this driver, we fixup the visuals after.
+ */
+
+ /*
+ * Reset the visual list.
+ */
+
+ miClearVisualTypes();
+ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual)) {
+ ERROR_MSG("Cannot initialize the visual type for %d bits per pixel!",
+ pScrn->bitsPerPixel);
+ goto fail;
+ }
+
+ if (!miSetPixmapDepths()) {
+ ERROR_MSG("Cannot initialize the pixmap depth!");
+ goto fail;
+ }
+
+ /* Initialize some generic 2D drawing functions: */
+ if (!fbScreenInit(pScreen, omap_bo_map(pOMAP->scanout),
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
+ pScrn->bitsPerPixel)) {
+ ERROR_MSG("fbScreenInit() failed!");
+ goto fail;
+ }
+
+ /* 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;
+ }
+ }
+
+ /* Continue initializing the generic 2D drawing functions after fixing the
+ * RGB ordering:
+ */
+ if (!fbPictureInit(pScreen, NULL, 0)) {
+ ERROR_MSG("fbPictureInit() failed!");
+ goto fail;
+ }
+
+ /* Set the initial black & white colormap indices: */
+ xf86SetBlackWhitePixels(pScreen);
+
+ /* Initialize backing store: */
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+
+ /* Initialize the cursor: */
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+ /* Cause the cursor position to be updated by the mouse signal handler: */
+ xf86SetSilkenMouse(pScreen);
+
+ /* XXX -- Is this the right place for this? The Intel i830 driver says:
+ * "Must force it before EnterVT, so we are in control of VT..."
+ */
+ pScrn->vtSema = TRUE;
+
+ /* Take over the virtual terminal from the console, set the desired mode,
+ * etc.:
+ */
+ OMAPEnterVT(scrnIndex, 0);
+
+ /* Set the desired mode(s): */
+ if (!xf86SetDesiredModes(pScrn)) {
+ ERROR_MSG("xf86SetDesiredModes() failed!");
+ goto fail;
+ }
+
+ /* Do some XRandR initialization: */
+ if (!xf86CrtcScreenInit(pScreen)) {
+ ERROR_MSG("xf86CrtcScreenInit() failed!");
+ goto fail;
+ }
+
+ if (!miCreateDefColormap(pScreen)) {
+ ERROR_MSG("Cannot create colormap!");
+ goto fail;
+ }
+
+ if (!xf86HandleColormaps(pScreen, 256, 8, OMAPLoadPalette, NULL,
+ CMAP_PALETTED_TRUECOLOR)) {
+ ERROR_MSG("xf86HandleColormaps() failed!");
+ goto fail;
+ }
+
+ /* Setup power management: */
+ xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+
+ pScreen->SaveScreen = xf86SaveScreen;
+
+ /* Wrap some screen functions: */
+ wrap(pOMAP, pScreen, CloseScreen, OMAPCloseScreen);
+ wrap(pOMAP, pScreen, CreateScreenResources, OMAPCreateScreenResources);
+ wrap(pOMAP, pScreen, BlockHandler, OMAPBlockHandler);
+
+ /*
+ * Initialize external sub-modules for EXA now:
+ */
+
+ if (!pOMAP->NoAccel) {
+ switch (pOMAP->chipset) {
+ case 0x3430:
+ case 0x3630:
+ case 0x4430:
+ case 0x4460:
+ INFO_MSG("Initializing the \"%s\" sub-module ...", SUB_MODULE_PVR);
+ pOMAP->pOMAPEXA = InitPowerVREXA(pScreen, pScrn);
+ if (pOMAP->pOMAPEXA) {
+ INFO_MSG("Successfully initialized the \"%s\" sub-module",
+ SUB_MODULE_PVR);
+ } else {
+ INFO_MSG("Could not initialize the \"%s\" sub-module",
+ SUB_MODULE_PVR);
+ pOMAP->NoAccel = TRUE;
+ }
+ break;
+ /* case 4470: ..; break; */
+ default:
+ ERROR_MSG("Unsupported chipset: %d", pOMAP->chipset);
+ pOMAP->NoAccel = TRUE;
+ break;
+ }
+ }
+
+ if (!pOMAP->pOMAPEXA) {
+ pOMAP->pOMAPEXA = InitNullEXA(pScreen, pScrn);
+ }
+
+ drmmode_uevent_init(pScrn);
+
+ TRACE_EXIT();
+ return TRUE;
+
+fail:
+ TRACE_EXIT();
+ return FALSE;
+}
+
+
+static void
+OMAPLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
+ LOCO * colors, VisualPtr pVisual)
+{
+ TRACE_ENTER();
+ TRACE_EXIT();
+}
+
+
+/**
+ * The driver's CloseScreen() function. This is called at the end of each
+ * server generation. Restore state, unmap the frame buffer (and any other
+ * mapped memory regions), and free per-Screen data structures (except those
+ * held by pScrn).
+ */
+static Bool
+OMAPCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+
+ TRACE_ENTER();
+
+ drmmode_uevent_fini(pScrn);
+
+ if (pScrn->vtSema == TRUE) {
+ OMAPLeaveVT(scrnIndex, 0);
+ }
+
+ if (pOMAP->pOMAPEXA) {
+ if (pOMAP->pOMAPEXA->CloseScreen) {
+ pOMAP->pOMAPEXA->CloseScreen(scrnIndex, pScreen);
+ }
+ }
+
+ OMAPUnmapMem(pScrn);
+
+ pScrn->vtSema = FALSE;
+
+ unwrap(pOMAP, pScreen, CloseScreen);
+ unwrap(pOMAP, pScreen, BlockHandler);
+ unwrap(pOMAP, pScreen, CreateScreenResources);
+
+ TRACE_EXIT();
+
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+
+
+/**
+ * Adjust the screen pixmap for the current location of the front buffer.
+ * This is done at EnterVT when buffers are bound as long as the resources
+ * have already been created, but the first EnterVT happens before
+ * CreateScreenResources.
+ */
+static Bool
+OMAPCreateScreenResources(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+
+ swap(pOMAP, pScreen, CreateScreenResources);
+ if (!(*pScreen->CreateScreenResources) (pScreen))
+ return FALSE;
+ swap(pOMAP, pScreen, CreateScreenResources);
+
+ return TRUE;
+}
+
+
+static void
+OMAPBlockHandler(int i, pointer blockData, pointer pTimeout, pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ ScrnInfoPtr pScrn = xf86Screens[i];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+
+ swap(pOMAP, pScreen, BlockHandler);
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+ swap(pOMAP, pScreen, BlockHandler);
+
+ /* TODO OMAPVideoBlockHandler(), etc.. */
+}
+
+
+
+/**
+ * The driver's SwitchMode() function. Initialize the new mode for the
+ * Screen.
+ */
+static Bool
+OMAPSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
+}
+
+
+
+/**
+ * The driver's AdjustFrame() function. For cases where the frame buffer is
+ * larger than the monitor resolution, this function can pan around the frame
+ * buffer within the "viewport" of the monitor.
+ */
+static void
+OMAPAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ drmmode_adjust_frame(pScrn, x, y, flags);
+}
+
+
+
+/**
+ * The driver's EnterVT() function. This is called at server startup time, and
+ * when the X server takes over the virtual terminal from the console. As
+ * such, it may need to save the current (i.e. console) HW state, and set the
+ * HW state as needed by the X server.
+ */
+static Bool
+OMAPEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ int ret;
+
+ TRACE_ENTER();
+
+ ret = drmSetMaster(pOMAP->drmFD);
+ if (ret) {
+ ERROR_MSG("Cannot get DRM master: %s\n", strerror(ret));
+ }
+
+ if (!xf86SetDesiredModes(pScrn)) {
+ ERROR_MSG("xf86SetDesiredModes() failed!");
+ return FALSE;
+ }
+
+ TRACE_EXIT();
+ return TRUE;
+}
+
+
+
+/**
+ * The driver's LeaveVT() function. This is called when the X server
+ * temporarily gives up the virtual terminal to the console. As such, it may
+ * need to restore the console's HW state.
+ */
+static void
+OMAPLeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ int ret;
+
+ TRACE_ENTER();
+
+ ret = drmDropMaster(pOMAP->drmFD);
+ if (ret) {
+ WARNING_MSG("drmDropMaster failed: %s\n", strerror(errno));
+ }
+
+ TRACE_EXIT();
+}
+
+
+
+/**
+ * The driver's FreeScreen() function. This is called at the server's end of
+ * life. This should free any driver-allocated data that was allocated
+ * up-to-and-including an unsuccessful ScreenInit() call.
+ */
+static void
+OMAPFreeScreen(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+
+ TRACE_ENTER();
+
+ if (!pOMAP) {
+ /* This can happen if a Screen is deleted after Probe(): */
+ return;
+ }
+
+ if (pOMAP->pOMAPEXA) {
+ if (pOMAP->pOMAPEXA->FreeScreen) {
+ pOMAP->pOMAPEXA->FreeScreen(scrnIndex, flags);
+ }
+ free(pOMAP->pOMAPEXA);
+ }
+
+ omap_device_del(pOMAP->dev);
+
+ OMAPCloseDRMMaster(pScrn);
+
+ OMAPFreeRec(pScrn);
+
+ TRACE_EXIT();
+}
+
diff --git a/src/omap_driver.h b/src/omap_driver.h
new file mode 100644
index 0000000..57f809e
--- /dev/null
+++ b/src/omap_driver.h
@@ -0,0 +1,239 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Ian Elliott <ianelliottus@yahoo.com>
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifndef OMAP_DRV_H_
+#define OMAP_DRV_H_
+
+/* All drivers need the following headers: */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+/* XXX - Perhaps, the following header files will only be used temporarily
+ * (i.e. so we can use fbdevHW, SW cursor, etc):
+ * XXX - figure out what can be removed..
+ */
+#include "mipointer.h"
+#include "mibstore.h"
+#include "micmap.h"
+#include "colormapst.h"
+#include "xf86cmap.h"
+#include "shadow.h"
+/* for visuals */
+#include "fb.h"
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
+#include "xf86Resources.h"
+#include "xf86RAC.h"
+#endif
+#include "xf86xv.h"
+#include "xf86Crtc.h"
+#include "xf86RandR12.h"
+#include "xf86drm.h"
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "dri2.h"
+#endif
+
+#include "omap_drm.h"
+
+#include <errno.h>
+
+
+
+
+#define OMAP_VERSION 1000 /* Apparently not used by X server */
+#define OMAP_NAME "OMAP" /* Name used to prefix messages */
+#define OMAP_DRIVER_NAME "omap" /* Driver name as used in config file */
+#define OMAP_MAJOR_VERSION 0
+#define OMAP_MINOR_VERSION 83
+#define OMAP_PATCHLEVEL 0
+
+
+/**
+ * This controls whether debug statements (and function "trace" enter/exit)
+ * messages are sent to the log file (TRUE) or are ignored (FALSE).
+ */
+extern _X_EXPORT Bool omapDebug;
+
+
+/* Various logging/debug macros for use in the X driver and the external
+ * sub-modules:
+ */
+#define TRACE_ENTER() \
+ do { if (omapDebug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s:%d: Entering\n",\
+ __FUNCTION__, __LINE__); } while (0)
+#define TRACE_EXIT() \
+ do { if (omapDebug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s:%d: Exiting\n",\
+ __FUNCTION__, __LINE__); } while (0)
+#define DEBUG_MSG(fmt, ...) \
+ do { if (omapDebug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s:%d " fmt "\n",\
+ __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0)
+#define INFO_MSG(fmt, ...) \
+ do { xf86DrvMsg(pScrn->scrnIndex, X_INFO, fmt "\n",\
+ ##__VA_ARGS__); } while (0)
+#define CONFIG_MSG(fmt, ...) \
+ do { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, fmt "\n",\
+ ##__VA_ARGS__); } while (0)
+#define WARNING_MSG(fmt, ...) \
+ do { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "WARNING: " fmt "\n",\
+ ##__VA_ARGS__); } while (0)
+#define ERROR_MSG(fmt, ...) \
+ do { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ERROR: " fmt "\n",\
+ ##__VA_ARGS__); } while (0)
+#define EARLY_ERROR_MSG(fmt, ...) \
+ do { xf86Msg(X_ERROR, "ERROR: " fmt "\n",\
+ ##__VA_ARGS__); } while (0)
+
+
+/* Forward declarations: */
+struct _OMAPRec;
+
+extern unsigned int
+OMAPCalculateStride(unsigned int fbWidth, unsigned int bitsPerPixel);
+
+
+/**
+ * A per-Screen structure used to communicate and coordinate between the OMAP X
+ * driver and an external EXA sub-module (if loaded).
+ */
+typedef struct _OMAPEXARec
+{
+ union { struct {
+
+ /**
+ * Called by X driver's CloseScreen() function at the end of each server
+ * generation to free per-Screen data structures (except those held by
+ * pScrn).
+ */
+ Bool (*CloseScreen)(int scrnIndex, ScreenPtr pScreen);
+
+ /**
+ * Called by X driver's FreeScreen() function at the end of each server
+ * lifetime to free per-ScrnInfoRec data structures, to close any external
+ * connections (e.g. with PVR2D, DRM), etc.
+ */
+ void (*FreeScreen)(int scrnIndex, int flags);
+
+ /* add new fields here at end, to preserve ABI */
+
+ };
+
+ /* padding to keep ABI stable, so an existing EXA submodule
+ * doesn't need to be recompiled when new fields are added
+ */
+ void *pad[64];
+ };
+
+} OMAPEXARec, *OMAPEXAPtr;
+
+
+
+/** The driver's Screen-specific, "private" data structure. */
+typedef struct _OMAPRec
+{
+ /** Chipset id */
+ int chipset;
+
+ /**
+ * Pointer to a structure used to communicate and coordinate with an
+ * external EXA library (if loaded).
+ */
+ OMAPEXAPtr pOMAPEXA;
+
+ Bool NoAccel;
+
+ /** File descriptor of the connection with the DRM. */
+ int drmFD;
+
+ /** DRM device instance */
+ struct omap_device *dev;
+
+ /** Scan-out buffer. */
+ struct omap_bo *scanout;
+
+ /** Pointer to the options for this screen. */
+ OptionInfoPtr pOptionInfo;
+
+ /** Save (wrap) the original pScreen functions. */
+ CloseScreenProcPtr SavedCloseScreen;
+ CreateScreenResourcesProcPtr SavedCreateScreenResources;
+ ScreenBlockHandlerProcPtr SavedBlockHandler;
+
+ /** Pointer to the entity structure for this screen. */
+ EntityInfoPtr pEntityInfo;
+
+} OMAPRec, *OMAPPtr;
+
+/*
+ * Misc utility macros:
+ */
+
+/** Return a pointer to the driver's private structure. */
+#define OMAPPTR(p) ((OMAPPtr)((p)->driverPrivate))
+#define OMAPPTR_FROM_SCREEN(pScreen) \
+ ((OMAPPtr)(xf86Screens[(pScreen)->myNum])->driverPrivate);
+
+#define wrap(priv, real, mem, func) {\
+ priv->Saved##mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv, real, mem) {\
+ real->mem = priv->Saved##mem; \
+}
+
+#define swap(priv, real, mem) {\
+ void *tmp = priv->Saved##mem; \
+ priv->Saved##mem = real->mem; \
+ real->mem = tmp; \
+}
+
+
+/**
+ * Canonical name of an external sub-module providing support for EXA
+ * acceleration, that utiltizes the OMAP's PowerVR accelerator and uses closed
+ * source from Imaginations Technology Limited.
+ */
+#define SUB_MODULE_PVR "omap_pvr"
+OMAPEXAPtr InitPowerVREXA(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+
+/**
+ * Fallback EXA implementation
+ */
+OMAPEXAPtr InitNullEXA(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+
+/**
+ * drmmode functions..
+ */
+Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp);
+void drmmode_uevent_init(ScrnInfoPtr pScrn);
+void drmmode_uevent_fini(ScrnInfoPtr pScrn);
+void drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y, int flags);
+void drmmode_remove_fb(ScrnInfoPtr pScrn);
+
+#endif /* OMAP_DRV_H_ */
diff --git a/src/omap_drm.c b/src/omap_drm.c
new file mode 100644
index 0000000..003a758
--- /dev/null
+++ b/src/omap_drm.c
@@ -0,0 +1,172 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <rob@ti.com>
+ */
+
+/* This file is a staging area for OMAP DRM ioctl wrapper stuff that should
+ * eventually become part of libdrm.. for now, I'm still sorting the API out
+ * so it remains here until things stabilize.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#include "omap_drm.h"
+
+struct omap_device {
+ int fd;
+};
+
+/* a GEM buffer object allocated from the DRM device */
+struct omap_bo {
+ struct omap_device *dev;
+ void *map; /* userspace mmap'ing (if there is one) */
+ uint32_t size;
+ uint32_t handle;
+ uint64_t offset; /* offset to mmap() */
+};
+
+struct omap_device * omap_device_new(int fd)
+{
+ struct omap_device *dev = calloc(sizeof(*dev), 1);
+ dev->fd = fd;
+ return dev;
+}
+
+void omap_device_del(struct omap_device *dev)
+{
+ free(dev);
+}
+
+int omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value)
+{
+ struct drm_omap_param req = {
+ .param = param,
+ };
+ int ret;
+
+ ret = drmCommandWriteRead(dev->fd, DRM_OMAP_GET_PARAM, &req, sizeof(req));
+ if (ret) {
+ return ret;
+ }
+
+ *value = req.value;
+
+ return 0;
+}
+
+int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value)
+{
+ struct drm_omap_param req = {
+ .param = param,
+ .value = value,
+ };
+ return drmCommandWrite(dev->fd, DRM_OMAP_GET_PARAM, &req, sizeof(req));
+}
+
+/* allocate a new (un-tiled) buffer object */
+struct omap_bo * omap_bo_new(struct omap_device *dev,
+ uint32_t size, uint32_t flags)
+{
+ struct omap_bo *bo = calloc(sizeof(*bo), 1);
+ struct drm_omap_gem_new req = {
+ .size = size,
+ .flags = flags,
+ };
+
+ if (size == 0) {
+ goto fail;
+ }
+
+ if (!bo) {
+ goto fail;
+ }
+
+ bo->dev = dev;
+ bo->size = size;
+
+ if (drmCommandWriteRead(dev->fd, DRM_OMAP_GEM_NEW,
+ &req, sizeof(req))) {
+ goto fail;
+ }
+
+ bo->handle = req.handle;
+ bo->offset = req.offset;
+
+ return bo;
+
+fail:
+ free(bo);
+ return NULL;
+}
+
+/* destroy a buffer object */
+void omap_bo_del(struct omap_bo *bo)
+{
+ if (!bo) {
+ return;
+ }
+
+ if (bo->map) {
+ munmap(bo->map, bo->size);
+ }
+
+ if (bo->handle) {
+ struct drm_gem_close req = {
+ .handle = bo->handle,
+ };
+
+ drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+ }
+
+ free(bo);
+}
+
+uint32_t omap_bo_handle(struct omap_bo *bo)
+{
+ return bo->handle;
+}
+
+uint32_t omap_bo_size(struct omap_bo *bo)
+{
+ return bo->size;
+}
+
+void * omap_bo_map(struct omap_bo *bo)
+{
+ if (!bo->map) {
+ bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, bo->dev->fd, bo->offset);
+ if (bo->map == MAP_FAILED) {
+ bo->map = NULL;
+ }
+ }
+ return bo->map;
+}
diff --git a/src/omap_drm.h b/src/omap_drm.h
new file mode 100644
index 0000000..f15c527
--- /dev/null
+++ b/src/omap_drm.h
@@ -0,0 +1,99 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifndef OMAP_DRM_H_
+#define OMAP_DRM_H_
+
+#include <xf86drm.h>
+#include <stdint.h>
+
+/* This file is a staging area for OMAP DRM ioctl wrapper stuff that should
+ * eventually become part of libdrm.. for now, I'm still sorting the API out
+ * so it remains here until things stabilize.
+ */
+
+
+/**************************/
+/**************************/
+/**************************/
+/* these should be in kernel header.. */
+#define OMAP_PARAM_CHIPSET_ID 1 /* ie. 0x3430, 0x4430, etc */
+
+struct drm_omap_param {
+ uint64_t param; /* in */
+ uint64_t value; /* in (set_param), out (get_param) */
+};
+
+struct drm_omap_get_base {
+ char plugin_name[64]; /* in */
+ uint32_t ioctl_base; /* out */
+};
+
+#define OMAP_BO_SCANOUT 0x00000001 /* scanout capable (phys contiguous) */
+#define OMAP_BO_WC 0x00000002 /* map write-combine (default cached) */
+
+struct drm_omap_gem_new {
+ uint32_t size; /* in */
+ uint32_t flags; /* in */
+ uint32_t handle; /* out */
+ uint64_t offset; /* out */
+};
+
+#define DRM_OMAP_GET_PARAM 0x00
+#define DRM_OMAP_SET_PARAM 0x01
+#define DRM_OMAP_GET_BASE 0x02
+#define DRM_OMAP_GEM_NEW 0x03
+#define DRM_OMAP_NUM_IOCTLS 0x04
+/**************************/
+/**************************/
+/**************************/
+
+
+struct omap_bo;
+struct omap_device;
+
+/* device related functions:
+ */
+
+struct omap_device * omap_device_new(int fd);
+void omap_device_del(struct omap_device *dev);
+int omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value);
+int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value);
+
+/* buffer-object related functions:
+ */
+
+struct omap_bo * omap_bo_new(struct omap_device *dev,
+ uint32_t size, uint32_t flags);
+void omap_bo_del(struct omap_bo *bo);
+uint32_t omap_bo_handle(struct omap_bo *bo);
+uint32_t omap_bo_size(struct omap_bo *bo);
+void * omap_bo_map(struct omap_bo *bo);
+
+
+#endif /* OMAP_DRM_H_ */
diff --git a/src/omap_exa_common.c b/src/omap_exa_common.c
new file mode 100644
index 0000000..13585e0
--- /dev/null
+++ b/src/omap_exa_common.c
@@ -0,0 +1,231 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "omap_exa_common.h"
+
+#include "exa.h"
+
+
+#define pix2scrn(pPixmap) \
+ xf86Screens[(pPixmap)->drawable.pScreen->myNum]
+
+
+/* Common OMAP EXA functions, mostly related to pixmap/buffer allocation.
+ * Individual driver submodules can use these directly, or wrap them with
+ * there own functions if anything additional is required. Submodules
+ * can use OMAPPrixmapPrivPtr#priv for their own private data.
+ */
+
+void *
+OMAPCreatePixmap (ScreenPtr pScreen, int width, int height,
+ int depth, int usage_hint, int bitsPerPixel,
+ int *new_fb_pitch)
+{
+ OMAPPixmapPrivPtr priv = calloc(sizeof(OMAPPixmapPrivRec), 1);
+
+ /* actual allocation of buffer is in OMAPModifyPixmapHeader */
+
+ return priv;
+}
+
+void
+OMAPDestroyPixmap(ScreenPtr pScreen, void *driverPriv)
+{
+ OMAPPixmapPrivPtr priv = driverPriv;
+
+ if (priv->bo) {
+ omap_bo_del(priv->bo);
+ }
+
+ free(priv);
+}
+
+Bool
+OMAPModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+ int depth, int bitsPerPixel, int devKind,
+ pointer pPixData)
+{
+ OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap);
+ ScrnInfoPtr pScrn = pix2scrn(pPixmap);
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ uint32_t size;
+ Bool ret;
+
+ ret = miModifyPixmapHeader(pPixmap, width, height, depth,
+ bitsPerPixel, devKind, pPixData);
+ if (!ret) {
+ return ret;
+ }
+
+ if (pPixData == omap_bo_map(pOMAP->scanout)) {
+ DEBUG_MSG("wrapping scanout buffer");
+ if (priv->bo != pOMAP->scanout) {
+ omap_bo_del(priv->bo);
+ priv->bo = pOMAP->scanout;
+ }
+ return TRUE;
+ } else if (pPixData) {
+ /* we can't accelerate this pixmap, and don't ever want to
+ * see it again..
+ */
+ pPixmap->devPrivate.ptr = pPixData;
+ pPixmap->devKind = devKind;
+
+ /* scratch-pixmap (see GetScratchPixmapHeader()) gets recycled,
+ * so could have a previous bo!
+ */
+ omap_bo_del(priv->bo);
+ priv->bo = NULL;
+
+ return FALSE;
+ }
+
+ /* passed in values could be zero, indicating that existing values
+ * should be kept.. miModifyPixmapHeader() will deal with that, but
+ * we need to resync to ensure we have the right values in the rest
+ * of this function
+ */
+ width = pPixmap->drawable.width;
+ height = pPixmap->drawable.height;
+ depth = pPixmap->drawable.depth;
+ bitsPerPixel = pPixmap->drawable.bitsPerPixel;
+
+
+ pPixmap->devKind = OMAPCalculateStride(width, bitsPerPixel);
+ size = pPixmap->devKind * height;
+
+ if ((!priv->bo) || (omap_bo_size(priv->bo) != size)) {
+ /* re-allocate buffer! */
+ omap_bo_del(priv->bo);
+ priv->bo = omap_bo_new(pOMAP->dev, size, 0);
+ }
+
+ return TRUE;
+}
+
+/**
+ * WaitMarker is a required EXA callback but synchronization is
+ * performed during OMAPPrepareAccess so this function does not
+ * have anything to do at present
+ */
+void
+OMAPWaitMarker(ScreenPtr pScreen, int marker)
+{
+ /* no-op */
+}
+
+/**
+ * PrepareAccess() is called before CPU access to an offscreen pixmap.
+ *
+ * @param pPix the pixmap being accessed
+ * @param index the index of the pixmap being accessed.
+ *
+ * PrepareAccess() will be called before CPU access to an offscreen pixmap.
+ * This can be used to set up hardware surfaces for byteswapping or
+ * untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
+ * making CPU access use a different aperture.
+ *
+ * The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC,
+ * #EXA_PREPARE_MASK, #EXA_PREPARE_AUX_DEST, #EXA_PREPARE_AUX_SRC, or
+ * #EXA_PREPARE_AUX_MASK. Since only up to #EXA_NUM_PREPARE_INDICES pixmaps
+ * will have PrepareAccess() called on them per operation, drivers can have
+ * a small, statically-allocated space to maintain state for PrepareAccess()
+ * and FinishAccess() in. Note that PrepareAccess() is only called once per
+ * pixmap and operation, regardless of whether the pixmap is used as a
+ * destination and/or source, and the index may not reflect the usage.
+ *
+ * PrepareAccess() may fail. An example might be the case of hardware that
+ * can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess()
+ * fails, EXA will migrate the pixmap to system memory.
+ * DownloadFromScreen() must be implemented and must not fail if a driver
+ * wishes to fail in PrepareAccess(). PrepareAccess() must not fail when
+ * pPix is the visible screen, because the visible screen can not be
+ * migrated.
+ *
+ * @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU
+ * drawing.
+ * @return FALSE if PrepareAccess() is unsuccessful and EXA should use
+ * DownloadFromScreen() to migate the pixmap out.
+ */
+Bool
+OMAPPrepareAccess(PixmapPtr pPixmap, int index)
+{
+ OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap);
+
+ /* TODO: wait for blits complete on priv->bo.. */
+
+ pPixmap->devPrivate.ptr = omap_bo_map(priv->bo);
+
+ return TRUE;
+}
+
+/**
+ * FinishAccess() is called after CPU access to an offscreen pixmap.
+ *
+ * @param pPix the pixmap being accessed
+ * @param index the index of the pixmap being accessed.
+ *
+ * FinishAccess() will be called after finishing CPU access of an offscreen
+ * pixmap set up by PrepareAccess(). Note that the FinishAccess() will not be
+ * called if PrepareAccess() failed and the pixmap was migrated out.
+ */
+void
+OMAPFinishAccess(PixmapPtr pPixmap, int index)
+{
+ pPixmap->devPrivate.ptr = NULL;
+}
+
+/**
+ * PixmapIsOffscreen() is an optional driver replacement to
+ * exaPixmapHasGpuCopy(). Set to NULL if you want the standard behaviour
+ * of exaPixmapHasGpuCopy().
+ *
+ * @param pPix the pixmap
+ * @return TRUE if the given drawable is in framebuffer memory.
+ *
+ * exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
+ * memory, meaning that acceleration could probably be done to it, and that it
+ * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
+ * with the CPU.
+ */
+Bool
+OMAPPixmapIsOffscreen(PixmapPtr pPixmap)
+{
+ /* offscreen means in 'gpu accessible memory', not that it's off the
+ * visible screen. We currently have no special constraints, since
+ * OMAP has a flat memory model (no separate GPU memory). If
+ * individual EXA implementation has additional constraints, like
+ * buffer size or mapping in GPU MMU, it should wrap this function.
+ */
+ OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap);
+ return priv && priv->bo;
+}
diff --git a/src/omap_exa_common.h b/src/omap_exa_common.h
new file mode 100644
index 0000000..a1bd955
--- /dev/null
+++ b/src/omap_exa_common.h
@@ -0,0 +1,57 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifndef OMAP_EXA_COMMON_H_
+#define OMAP_EXA_COMMON_H_
+
+#include "omap_driver.h"
+
+/* Common OMAP EXA functions, mostly related to pixmap/buffer allocation.
+ * Individual driver submodules can use these directly, or wrap them with
+ * there own functions if anything additional is required. Submodules
+ * can use OMAPPrixmapPrivPtr#priv for their own private data.
+ */
+
+typedef struct {
+ void *priv; /* EXA submodule private data */
+ struct omap_bo *bo;
+} OMAPPixmapPrivRec, *OMAPPixmapPrivPtr;
+
+void * OMAPCreatePixmap (ScreenPtr pScreen, int width, int height,
+ int depth, int usage_hint, int bitsPerPixel,
+ int *new_fb_pitch);
+void OMAPDestroyPixmap(ScreenPtr pScreen, void *driverPriv);
+Bool OMAPModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+ int depth, int bitsPerPixel, int devKind,
+ pointer pPixData);
+void OMAPWaitMarker(ScreenPtr pScreen, int marker);
+Bool OMAPPrepareAccess(PixmapPtr pPix, int index);
+void OMAPFinishAccess(PixmapPtr pPix, int index);
+Bool OMAPPixmapIsOffscreen(PixmapPtr pPix);
+
+#endif /* OMAP_EXA_COMMON_H_ */
diff --git a/src/omap_exa_null.c b/src/omap_exa_null.c
new file mode 100644
index 0000000..524045b
--- /dev/null
+++ b/src/omap_exa_null.c
@@ -0,0 +1,153 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright © 2011 Texas Instruments, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark <rob@ti.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "omap_driver.h"
+#include "omap_exa_common.h"
+
+#include "exa.h"
+
+/* This file has a trivial EXA implementation which accelerates nothing. It
+ * is used as the fall-back in case the EXA implementation for the current
+ * chipset is not available. (For example, on chipsets which used the closed
+ * source IMG PowerVR EXA implementation, if the closed-source submodule is
+ * not installed.
+ */
+
+typedef struct {
+ OMAPEXARec base;
+ ExaDriverPtr exa;
+ /* add any other driver private data here.. */
+} OMAPNullEXARec, *OMAPNullEXAPtr;
+
+
+static Bool
+PrepareSolidFail(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fill_colour)
+{
+ return FALSE;
+}
+
+static Bool
+PrepareCopyFail(PixmapPtr pSrc, PixmapPtr pDst, int xdir, int ydir,
+ int alu, Pixel planemask)
+{
+ return FALSE;
+}
+
+static Bool
+CheckCompositeFail(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ return FALSE;
+}
+
+static Bool
+PrepareCompositeFail(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+ return FALSE;
+}
+
+static Bool
+CloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+#if 0 // TODO need to change CloseScreen/FreeScreen ..
+ exaDriverFini(pScreen);
+ free(pNv->EXADriverPtr);
+#endif
+ return TRUE;
+}
+
+static void
+FreeScreen(int scrnIndex, int flags)
+{
+}
+
+
+OMAPEXAPtr
+InitNullEXA(ScreenPtr pScreen, ScrnInfoPtr pScrn)
+{
+ OMAPNullEXAPtr null_exa = calloc(sizeof (*null_exa), 1);
+ OMAPEXAPtr omap_exa = (OMAPEXAPtr)null_exa;
+ ExaDriverPtr exa;
+
+ INFO_MSG("Soft EXA mode");
+
+ exa = exaDriverAlloc();
+ if (!exa) {
+ goto fail;
+ }
+
+ null_exa->exa = exa;
+
+ exa->exa_major = EXA_VERSION_MAJOR;
+ exa->exa_minor = EXA_VERSION_MINOR;
+
+ exa->pixmapOffsetAlign = 0;
+ exa->pixmapPitchAlign = 32 * 4; // see OMAPCalculateStride()
+ exa->flags = EXA_OFFSCREEN_PIXMAPS |
+ EXA_HANDLES_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX;
+ exa->maxX = 4096;
+ exa->maxY = 4096;
+
+ /* Required EXA functions: */
+ exa->WaitMarker = OMAPWaitMarker;
+ exa->CreatePixmap2 = OMAPCreatePixmap;
+ exa->DestroyPixmap = OMAPDestroyPixmap;
+ exa->ModifyPixmapHeader = OMAPModifyPixmapHeader;
+
+ exa->PrepareAccess = OMAPPrepareAccess;
+ exa->FinishAccess = OMAPFinishAccess;
+ exa->PixmapIsOffscreen = OMAPPixmapIsOffscreen;
+
+ // Always fallback for software operations
+ exa->PrepareCopy = PrepareCopyFail;
+ exa->PrepareSolid = PrepareSolidFail;
+ exa->CheckComposite = CheckCompositeFail;
+ exa->PrepareComposite = PrepareCompositeFail;
+
+ if (! exaDriverInit(pScreen, exa)) {
+ ERROR_MSG("exaDriverInit failed");
+ goto fail;
+ }
+
+ omap_exa->CloseScreen = CloseScreen;
+ omap_exa->FreeScreen = FreeScreen;
+
+ return omap_exa;
+
+fail:
+ if (null_exa) {
+ free(null_exa);
+ }
+ return NULL;
+}
+