xf86-video-omap-0.4.3/000077500000000000000000000000001207404333600143515ustar00rootroot00000000000000xf86-video-omap-0.4.3/.gitignore000066400000000000000000000004501207404333600163400ustar00rootroot00000000000000aclocal.m4 autom4te.cache Makefile.in Makefile INSTALL ChangeLog .deps .libs *.o *.lo *.la libtool *.pc *.tar.gz *.tar.bz2 config.log config.status config.guess config.h config.h.in config.sub config configure install-sh ltmain.sh missing stamp-h1 depcomp .cproject .project .settings man/omap.4 xf86-video-omap-0.4.3/AUTHORS000066400000000000000000000000741207404333600154220ustar00rootroot00000000000000Ian Elliott Rob Clark xf86-video-omap-0.4.3/COPYING000066400000000000000000000021111207404333600153770ustar00rootroot00000000000000Copyright © 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. xf86-video-omap-0.4.3/Makefile.am000066400000000000000000000024701207404333600164100ustar00rootroot00000000000000# 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 xf86-video-omap-0.4.3/NEWS000066400000000000000000000020301207404333600150430ustar00rootroot00000000000000Release 0.3.0 (2012-04-21) ========================== First Release Release 0.4.0 (2012-06-20) ========================== * Port to compat-api so driver will build against latest xserver from git as well as past releases. * DRI2: Fix issue with flipping that would result in deleting kms fb_id while it was being scanned out. * DRI2: Implement support for triple buffering. Release 0.4.1 (2012-10-06) ========================== * xrandr rotation support. * Support for PlatformProbe for latest xserver. * DRI2: fix issue w/ flipping multiple drawables. * Various other fixes, including updates to build with latest xserver. Release 0.4.2 (2012-10-15) ========================== * fix 'make dist' issue that would result in distribution tarballs missing the header files Release 0.4.3 (2012-01-11) ========================== * DRI2: Fix some potential leaks * Fix modesetting issue on kernels prior to rotation support * Remove unnecessary DRI1 check in configure.ac * DRI2: Fix potential triple-buffer loop in SwapComplete xf86-video-omap-0.4.3/README000066400000000000000000000010331207404333600152260ustar00rootroot00000000000000xf86-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 + OMAP5430 + OMAP5432 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.. xf86-video-omap-0.4.3/autogen.sh000077500000000000000000000014671207404333600163620ustar00rootroot00000000000000#! /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 && $autoheader && $libtoolize --copy --force && $automake --copy --add-missing --foreign && $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" xf86-video-omap-0.4.3/configure.ac000066400000000000000000000034771207404333600166520ustar00rootroot00000000000000# -*- 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.4.3], [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 >= 2.4.36] libdrm_omap xf86driproto $REQUIRED_MODULES) sdkdir=$(pkg-config --variable=sdkdir xorg-server) # Checks for header files. AC_HEADER_STDC AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes) if test "$VIDEO_DEBUG" = yes; then AC_DEFINE(VIDEO_DEBUG,1,[Enable debug support]) fi DRIVER_NAME=omap AC_SUBST([DRIVER_NAME]) AC_SUBST([moduledir]) AC_OUTPUT([ Makefile src/Makefile man/Makefile ]) xf86-video-omap-0.4.3/man/000077500000000000000000000000001207404333600151245ustar00rootroot00000000000000xf86-video-omap-0.4.3/man/Makefile.am000066400000000000000000000027351207404333600171670ustar00rootroot00000000000000# # 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) < $< > $@ xf86-video-omap-0.4.3/man/omap.man000066400000000000000000000074221207404333600165620ustar00rootroot00000000000000.\" 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 \*qDRI\*q \*q" boolean \*q Enable DRI2. .IP Default: Enabled .TP .BI "Option \*qNoAccel\*q \*q" boolean \*q Disable hw acceleration. .IP Default: Disabled .TP .BI "Option \*qHWcursor\*q \*q" boolean \*q Enable HW mouse cursor. .IP Default: Enabled .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-" 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. xf86-video-omap-0.4.3/src/000077500000000000000000000000001207404333600151405ustar00rootroot00000000000000xf86-video-omap-0.4.3/src/Makefile.am000066400000000000000000000045541207404333600172040ustar00rootroot00000000000000# 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 # Rob Clark # 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_la_LIBADD = @XORG_LIBS@ omap_drv_ladir = @moduledir@/drivers omap_drv_la_SOURCES = \ drmmode_display.c \ omap_exa.c \ omap_exa.h \ omap_exa_null.c \ omap_exa_utils.c \ omap_xv.c \ omap_dri2.c \ omap_driver.c \ omap_driver.h \ omap_util.h \ compat-api.h xf86-video-omap-0.4.3/src/compat-api.h000066400000000000000000000070171207404333600173500ustar00rootroot00000000000000/* * Copyright 2012 Red Hat, 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. * * Author: Dave Airlie */ /* this file provides API compat between server post 1.13 and pre it, it should be reused inside as many drivers as possible */ #ifndef COMPAT_API_H #define COMPAT_API_H #ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR #define GetGlyphPicture(g, s) GlyphPicture((g))[(s)->myNum] #define SetGlyphPicture(g, s, p) GlyphPicture((g))[(s)->myNum] = p #endif #ifndef XF86_HAS_SCRN_CONV #define xf86ScreenToScrn(s) xf86Screens[(s)->myNum] #define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex] #endif #ifndef XF86_SCRN_INTERFACE #define SCRN_ARG_TYPE int #define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = xf86Screens[(arg1)] #define SCREEN_ARG_TYPE int #define SCREEN_PTR(arg1) ScreenPtr pScreen = screenInfo.screens[(arg1)] #define SCREEN_INIT_ARGS_DECL int index, ScreenPtr pScreen, int argc, char **argv #define BLOCKHANDLER_ARGS_DECL int arg, pointer blockData, pointer pTimeout, pointer pReadmask #define BLOCKHANDLER_ARGS arg, blockData, pTimeout, pReadmask #define CLOSE_SCREEN_ARGS_DECL int scrnIndex, ScreenPtr pScreen #define CLOSE_SCREEN_ARGS scrnIndex, pScreen #define ADJUST_FRAME_ARGS_DECL int arg, int x, int y, int flags #define SWITCH_MODE_ARGS_DECL int arg, DisplayModePtr mode, int flags #define FREE_SCREEN_ARGS_DECL int arg, int flags #define FREE_SCREEN_ARGS(x) (x)->scrnIndex, 0 #define VT_FUNC_ARGS_DECL int arg, int flags #define VT_FUNC_ARGS(flags) pScrn->scrnIndex, (flags) #define ENABLE_DISABLE_FB_ACCESS_ARGS(pScrn, b) pScrn->scrnIndex, b #define XF86_ENABLEDISABLEFB_ARG(x) ((x)->scrnIndex) #else #define SCRN_ARG_TYPE ScrnInfoPtr #define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = (arg1) #define SCREEN_ARG_TYPE ScreenPtr #define SCREEN_PTR(arg1) ScreenPtr pScreen = (arg1) #define SCREEN_INIT_ARGS_DECL ScreenPtr pScreen, int argc, char **argv #define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask #define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask #define CLOSE_SCREEN_ARGS_DECL ScreenPtr pScreen #define CLOSE_SCREEN_ARGS pScreen #define ADJUST_FRAME_ARGS_DECL ScrnInfoPtr arg, int x, int y #define SWITCH_MODE_ARGS_DECL ScrnInfoPtr arg, DisplayModePtr mode #define FREE_SCREEN_ARGS_DECL ScrnInfoPtr arg #define FREE_SCREEN_ARGS(x) (x) #define VT_FUNC_ARGS_DECL ScrnInfoPtr arg #define VT_FUNC_ARGS(flags) pScrn #define ENABLE_DISABLE_FB_ACCESS_ARGS(pScrn, b) pScrn, b #define XF86_ENABLEDISABLEFB_ARG(x) (x) #endif #endif xf86-video-omap-0.4.3/src/drmmode_display.c000066400000000000000000001143451207404333600204700ustar00rootroot00000000000000/* * 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 * Ian Elliott */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* TODO cleanup #includes, remove unnecessary ones */ #include "xorgVersion.h" #include #include #include #include #include #include /* All drivers should typically include these */ #include "xf86.h" #include "xf86_OSproc.h" #define PPC_MMIO_IS_BE #include "compiler.h" #include "mipointer.h" #include "micmap.h" #include "xf86DDC.h" #include "vbe.h" #include "xf86RandR12.h" #include "dixstruct.h" #include "scrnintstr.h" #include "fb.h" #include "xf86cmap.h" #include "shadowfb.h" #include "xf86xv.h" #include #include "xf86Cursor.h" #include "xf86DDC.h" #include "region.h" #include #ifdef HAVE_XEXTPROTO_71 #include #else #define DPMS_SERVER #include #endif #include "omap_driver.h" #include "omap_drm.h" #include "xf86Crtc.h" #include "xf86drmMode.h" #include "drm_fourcc.h" #include "X11/Xatom.h" #include #include typedef struct { /* hardware cursor: */ drmModePlane *ovr; struct omap_bo *bo; uint32_t fb_id; int x, y; int visible; } drmmode_cursor_rec, *drmmode_cursor_ptr; typedef struct { int fd; uint32_t fb_id; drmModeResPtr mode_res; int cpp; struct udev_monitor *uevent_monitor; InputHandlerProc uevent_handler; drmmode_cursor_ptr cursor; int rotated_crtcs; } drmmode_rec, *drmmode_ptr; typedef struct { drmmode_ptr drmmode; drmModeCrtcPtr mode_crtc; Rotation rotation; /* properties that we care about: */ uint32_t prop_rotation; } 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); 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; } 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); } 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; } static void drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode) { // FIXME - Implement this function } #define SUPPORTED_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270 | RR_Reflect_X | RR_Reflect_Y) static Bool drmmode_set_rotation(xf86CrtcPtr crtc, Rotation rotation) { #if XF86_CRTC_VERSION >= 4 ScrnInfoPtr pScrn = crtc->scrn; OMAPPtr pOMAP = OMAPPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; if (has_rotation(pOMAP) && !(rotation & ~SUPPORTED_ROTATIONS)) { int ret; ret = drmModeObjectSetProperty(drmmode_crtc->drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, DRM_MODE_OBJECT_CRTC, drmmode_crtc->prop_rotation, rotation); if (ret) { ERROR_MSG("failed to set orientation %s", strerror(errno)); return FALSE; } crtc->driverIsPerformingTransform = TRUE; } #endif return xf86CrtcRotate(crtc); } static Bool drmmode_restore_crtc(xf86CrtcPtr crtc) { 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; uint32_t *output_ids = NULL; int output_count = 0; int ret = TRUE; int i; drmModeModeInfo kmode; if (drmmode->fb_id == 0) { unsigned int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); 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) { ERROR_MSG("failed to add fb: %s", strerror(errno)); return FALSE; } } output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); if (!output_ids) { ERROR_MSG("allocation failed"); return FALSE; } 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++; } drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode); ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, drmmode->fb_id, crtc->x, crtc->y, output_ids, output_count, &kmode); if (ret) { ERROR_MSG("failed to set mode: %s", strerror(-ret)); ret = FALSE; } else { ret = TRUE; } /* 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); } if (output_ids) { free(output_ids); } return ret; } static Bool drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y) { ScrnInfoPtr pScrn = 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; int ret = TRUE; Bool was_rotated = drmmode->rotated_crtcs > 0; TRACE_ENTER(); /* update the count of number of rotated CRTCs.. if we have one or more * rotated outputs then we want to use a tiled buffer, but otherwise * stick with non-tiled */ if ((drmmode_crtc->rotation != RR_Rotate_0) && (rotation == RR_Rotate_0)) { DEBUG_MSG("disabling rotation for crtc: %u", drmmode_crtc->mode_crtc->crtc_id); drmmode->rotated_crtcs--; } else if ((drmmode_crtc->rotation == RR_Rotate_0) && (rotation != RR_Rotate_0)) { DEBUG_MSG("enabling rotation for crtc: %u", drmmode_crtc->mode_crtc->crtc_id); drmmode->rotated_crtcs++; } drmmode_crtc->rotation = rotation; /* at this point, if we are switching from unrotated to rotated * or visa versa, then we need to reallocate the scanout buffer.. */ if (was_rotated != (drmmode->rotated_crtcs > 0)) { /* reallocate scanout buffer.. */ drmmode_reallocate_scanout(pScrn, TRUE, crtc); } /* note: this needs to be done before setting the mode, otherwise * drm core will reject connecting the fb to crtc due to mismatched * dimensions: */ if (!drmmode_set_rotation(crtc, rotation)) { ERROR_MSG("could not set rotation"); 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; ret = drmmode_restore_crtc(crtc); if (!ret) { /* If there was a problem, restore the old mode: */ crtc->x = saved_x; crtc->y = saved_y; crtc->rotation = saved_rotation; crtc->mode = saved_mode; } TRACE_EXIT(); return ret; } #define CURSORW 64 #define CURSORH 64 static void drmmode_hide_cursor(xf86CrtcPtr crtc) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; drmmode_cursor_ptr cursor = drmmode->cursor; if (!cursor) return; cursor->visible = FALSE; /* set plane's fb_id to 0 to disable it */ drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); } static void drmmode_show_cursor(xf86CrtcPtr crtc) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; drmmode_cursor_ptr cursor = drmmode->cursor; int crtc_x, crtc_y, src_x, src_y, w, h; if (!cursor) return; cursor->visible = TRUE; w = CURSORW; h = CURSORH; crtc_x = cursor->x; crtc_y = cursor->y; src_x = 0; src_y = 0; if (crtc_x < 0) { src_x += -crtc_x; w -= -crtc_x; crtc_x = 0; } if (crtc_y < 0) { src_y += -crtc_y; h -= -crtc_y; crtc_y = 0; } if ((crtc_x + w) > crtc->mode.HDisplay) { w = crtc->mode.HDisplay - crtc_x; } if ((crtc_y + h) > crtc->mode.VDisplay) { h = crtc->mode.VDisplay - crtc_y; } #if XF86_CRTC_VERSION >= 4 /* NOTE: driver is taking care of rotation in hw, which means * we need to deal w/ transformation of mouse cursor ourself: */ if (crtc->driverIsPerformingTransform) { xf86CrtcTransformCursorPos(crtc, &crtc_x, &crtc_y); } #endif /* note src coords (last 4 args) are in Q16 format */ drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id, drmmode_crtc->mode_crtc->crtc_id, cursor->fb_id, 0, crtc_x, crtc_y, w, h, src_x<<16, src_y<<16, w<<16, h<<16); } static void drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; drmmode_cursor_ptr cursor = drmmode->cursor; if (!cursor) return; cursor->x = x; cursor->y = y; if (cursor->visible) drmmode_show_cursor(crtc); } static void drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; drmmode_cursor_ptr cursor = drmmode->cursor; int visible; if (!cursor) return; visible = cursor->visible; if (visible) drmmode_hide_cursor(crtc); memcpy(omap_bo_map(cursor->bo), image, omap_bo_size(cursor->bo)); if (visible) drmmode_show_cursor(crtc); } Bool drmmode_cursor_init(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); drmmode_ptr drmmode = drmmode_from_scrn(pScrn); drmmode_cursor_ptr cursor; drmModePlaneRes *plane_resources; drmModePlane *ovr; /* technically we probably don't have any size limit.. since we * are just using an overlay... but xserver will always create * cursor images in the max size, so don't use width/height values * that are too big */ int w = CURSORW, h = CURSORH; uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */ if (drmmode->cursor) { INFO_MSG("cursor already initialized"); return TRUE; } cursor = calloc(1, sizeof(drmmode_cursor_rec)); /* find an unused plane which can be used as a mouse cursor. Note * that we cheat a bit, in order to not burn one overlay per crtc, * and only show the mouse cursor on one crtc at a time */ plane_resources = drmModeGetPlaneResources(drmmode->fd); if (!plane_resources) { ERROR_MSG("drmModeGetPlaneResources failed: %s", strerror(errno)); return FALSE; } if (plane_resources->count_planes < 1) { ERROR_MSG("not enough planes for HW cursor"); return FALSE; } ovr = drmModeGetPlane(drmmode->fd, plane_resources->planes[0]); if (!ovr) { ERROR_MSG("drmModeGetPlane failed: %s\n", strerror(errno)); return FALSE; } cursor->ovr = ovr; cursor->bo = omap_bo_new(pOMAP->dev, w*h*4, OMAP_BO_SCANOUT | OMAP_BO_WC); handles[0] = omap_bo_handle(cursor->bo); pitches[0] = w*4; offsets[0] = 0; if (drmModeAddFB2(drmmode->fd, w, h, DRM_FORMAT_ARGB8888, handles, pitches, offsets, &cursor->fb_id, 0)) { ERROR_MSG("drmModeAddFB2 failed: %s", strerror(errno)); return FALSE; } if (xf86_cursors_init(pScreen, w, h, HARDWARE_CURSOR_ARGB)) { INFO_MSG("HW cursor initialized"); drmmode->cursor = cursor; return TRUE; } // TODO cleanup when things fail.. return FALSE; } 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) { OMAPPtr pOMAP = OMAPPTR(pScrn); drmModeObjectPropertiesPtr props; 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; drmmode_crtc->rotation = RR_Rotate_0; drmmode_crtc->prop_rotation = 0; /* find properties that we care about: */ props = drmModeObjectGetProperties(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, DRM_MODE_OBJECT_CRTC); if (props) { drmModePropertyPtr prop; int i; for (i = 0; i < props->count_props; i++) { prop = drmModeGetProperty(drmmode->fd, props->props[i]); if (!strcmp(prop->name, "rotation")) { drmmode_crtc->prop_rotation = prop->prop_id; pOMAP->rotation_supported = TRUE; } drmModeFreeProperty(prop); } drmModeFreeObjectProperties(props); } crtc->driver_private = drmmode_crtc; TRACE_EXIT(); return; } 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; TRACE_EXIT(); return; } Bool drmmode_is_rotated(ScrnInfoPtr pScrn) { OMAPPtr pOMAP = OMAPPTR(pScrn); drmmode_ptr drmmode = drmmode_from_scrn(pScrn); return has_rotation(pOMAP) && drmmode->rotated_crtcs > 0; } Bool drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw, xf86CrtcPtr crtc) { OMAPPtr pOMAP = OMAPPTR(pScrn); ScreenPtr pScreen = pScrn->pScreen; int width = pScrn->virtualX; int height = pScrn->virtualY; Bool rotate = drmmode_is_rotated(pScrn); unsigned int pitch; if (rotate) { pitch = OMAPCalculateTiledStride(width, pScrn->bitsPerPixel); } else { pitch = OMAPCalculateStride(width, pScrn->bitsPerPixel); } if ((width != pOMAP->scanout_w) || (height != pOMAP->scanout_h) || (rotate != pOMAP->scanout_rotate)) { uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC; /* remove old fb if it exists */ drmmode_remove_fb(pScrn); if (pScreen && pScrn->EnableDisableFBAccess && redraw) pScrn->EnableDisableFBAccess(ENABLE_DISABLE_FB_ACCESS_ARGS(pScrn, FALSE)); /* delete old scanout buffer */ omap_bo_del(pOMAP->scanout); if (rotate) { DEBUG_MSG("allocating tiled scanout buffer: %dx%d (%d)", width, height, pitch); flags |= OMAPTiledFlags(pScrn->bitsPerPixel); pOMAP->scanout = omap_bo_new_tiled(pOMAP->dev, width, height, flags); } else { DEBUG_MSG("allocating linear scanout buffer: %dx%d (%d)", width, height, pitch); pOMAP->scanout = omap_bo_new(pOMAP->dev, height * pitch, flags); } if (!pOMAP->scanout) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Error reallocating scanout buffer\n"); return FALSE; } pOMAP->scanout_w = width; pOMAP->scanout_h = height; pOMAP->scanout_rotate = rotate; pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); 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)); } if (pScreen && pScrn->EnableDisableFBAccess && redraw) pScrn->EnableDisableFBAccess(ENABLE_DISABLE_FB_ACCESS_ARGS(pScrn, TRUE)); /* if reallocation triggered by a mode-set, we need to reconfigure any * other crtc's which have just been torn down by destroying the old fb: */ if (crtc) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); int i; DEBUG_MSG("restoring CRTCs"); for (i = 0; i < config->num_crtc; i++) { if (config->crtc[i] != crtc) { int ret; DEBUG_MSG("restore CRTC %d", i); ret = drmmode_restore_crtc(config->crtc[i]); if (!ret) { ERROR_MSG("failed to reconfig crtc %d", i); /* hmm, I guess just keep trying the rest? */ } } } } } else { 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)); } } return TRUE; } static Bool drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height) { DEBUG_MSG("Resize! %dx%d", width, height); pScrn->virtualX = width; pScrn->virtualY = height; if (!drmmode_reallocate_scanout(pScrn, FALSE, NULL)) return FALSE; return TRUE; } static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { drmmode_xf86crtc_resize }; Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp) { drmmode_ptr drmmode; int i; TRACE_ENTER(); drmmode = calloc(1, sizeof *drmmode); drmmode->fd = fd; drmmode->fb_id = 0; xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); 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; } void drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y) { 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; } /* * Page Flipping */ typedef struct { drmmode_ptr mode; uint32_t old_fb_id; void *priv; } drmmode_flipdata_rec, *drmmode_flipdata_ptr; static void page_flip_handler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { drmmode_flipdata_ptr flipdata = user_data; OMAPDRI2SwapComplete(flipdata->priv); drmModeRmFB(flipdata->mode->fd, flipdata->old_fb_id); free(flipdata); } static drmEventContext event_context = { .version = DRM_EVENT_CONTEXT_VERSION, .page_flip_handler = page_flip_handler, }; Bool drmmode_page_flip(DrawablePtr pDraw, PixmapPtr back, void *priv) { ScrnInfoPtr pScrn = xf86Screens[pDraw->pScreen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private; drmmode_ptr mode = crtc->drmmode; drmmode_flipdata_ptr flipdata; uint32_t old_fb_id; int ret, i; old_fb_id = mode->fb_id; ret = drmModeAddFB(mode->fd, pDraw->width, pDraw->height, pDraw->depth, pDraw->bitsPerPixel, exaGetPixmapPitch(back), omap_bo_handle(OMAPPixmapBo(back)), &mode->fb_id); if (ret) { DEBUG_MSG("add fb failed, cannot flip: %s", strerror(errno)); return FALSE; } flipdata = calloc(1, sizeof(*flipdata)); if (!flipdata) { WARNING_MSG("flip queue: data alloc failed."); goto error; } flipdata->priv = priv; flipdata->mode = mode; flipdata->old_fb_id = old_fb_id; DEBUG_MSG("flip: %d -> %d", mode->fb_id, old_fb_id); /* if we can flip, we must be fullscreen.. so flip all CRTC's.. */ for (i = 0; i < config->num_crtc; i++) { crtc = config->crtc[i]->driver_private; if (!config->crtc[i]->enabled) continue; ret = drmModePageFlip(mode->fd, crtc->mode_crtc->crtc_id, mode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipdata); if (ret) { WARNING_MSG("flip queue failed: %s", strerror(errno)); return FALSE; } } return TRUE; error: drmModeRmFB(mode->fd, mode->fb_id); mode->fb_id = old_fb_id; return FALSE; } /* * Hot Plug Event handling: */ 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); } static 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(); } static 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(); } static void drmmode_wakeup_handler(pointer data, int err, pointer p) { ScrnInfoPtr pScrn = data; drmmode_ptr drmmode = drmmode_from_scrn(pScrn); fd_set *read_mask = p; if (pScrn == NULL || err < 0) return; drmmode = drmmode_from_scrn(pScrn); if (FD_ISSET(drmmode->fd, read_mask)) drmHandleEvent(drmmode->fd, &event_context); } void drmmode_wait_for_event(ScrnInfoPtr pScrn) { drmmode_ptr drmmode = drmmode_from_scrn(pScrn); drmHandleEvent(drmmode->fd, &event_context); } void drmmode_screen_init(ScrnInfoPtr pScrn) { drmmode_ptr drmmode = drmmode_from_scrn(pScrn); drmmode_uevent_init(pScrn); AddGeneralSocket(drmmode->fd); /* Register a wakeup handler to get informed on DRM events */ RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, drmmode_wakeup_handler, pScrn); } void drmmode_screen_fini(ScrnInfoPtr pScrn) { drmmode_uevent_fini(pScrn); } xf86-video-omap-0.4.3/src/omap_dri2.c000066400000000000000000000427701207404333600171720ustar00rootroot00000000000000/* -*- 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 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "omap_driver.h" #include "omap_exa.h" #include "xf86drmMode.h" #include "dri2.h" /* any point to support earlier? */ #if DRI2INFOREC_VERSION < 4 # error "Requires newer DRI2" #endif typedef struct { DRI2BufferRec base; /** * Pixmap that is backing the buffer * * NOTE: don't track the pixmap ptr for the front buffer if it is * a window.. this could get reallocated from beneath us, so we should * always use draw2pix to be sure to have the correct one */ PixmapPtr pPixmap; /** * The DRI2 buffers are reference counted to avoid crashyness when the * client detaches a dri2 drawable while we are still waiting for a * page_flip event. */ int refcnt; } OMAPDRI2BufferRec, *OMAPDRI2BufferPtr; #define OMAPBUF(p) ((OMAPDRI2BufferPtr)(p)) #define DRIBUF(p) ((DRI2BufferPtr)(&(p)->base)) static void OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer); /* ************************************************************************* */ /** * We implement triple buffering a bit different than some of the other * DDX drivers. Instead of implementing it transparently, we let the * client explicitly request the third buffer. Triple buffering is a * tradeoff between jitter/fps and latency, so some applications might * be better off without triple buffering. */ #define DRI2BufferThirdLeft (DRI2BufferBackLeft | 0x00008000) static DevPrivateKeyRec OMAPDRI2WindowPrivateKeyRec; #define OMAPDRI2WindowPrivateKey (&OMAPDRI2WindowPrivateKeyRec) static DevPrivateKeyRec OMAPDRI2PixmapPrivateKeyRec; #define OMAPDRI2PixmapPrivateKey (&OMAPDRI2PixmapPrivateKeyRec) static RESTYPE OMAPDRI2DrawableRes; typedef struct { DrawablePtr pDraw; /* keep track of the third buffer, if created by the client: */ DRI2BufferPtr pThirdBuffer; /* in case of triple buffering, we can get another swap request * before the previous has completed, so queue up the next one: */ OMAPDRISwapCmd *cmd; /* pending swaps on this drawable (which might or might not be flips) */ int pending_swaps; } OMAPDRI2DrawableRec, *OMAPDRI2DrawablePtr; static int OMAPDRI2DrawableGone(pointer p, XID id) { OMAPDRI2DrawablePtr pPriv = p; DrawablePtr pDraw = pPriv->pDraw; if (pDraw->type == DRAWABLE_WINDOW) { dixSetPrivate(&((WindowPtr)pDraw)->devPrivates, OMAPDRI2WindowPrivateKey, NULL); } else { dixSetPrivate(&((PixmapPtr)pDraw)->devPrivates, OMAPDRI2PixmapPrivateKey, NULL); } free(pPriv); return Success; } static OMAPDRI2DrawablePtr OMAPDRI2GetDrawable(DrawablePtr pDraw) { OMAPDRI2DrawablePtr pPriv; if (pDraw->type == DRAWABLE_WINDOW) { pPriv = dixLookupPrivate(&((WindowPtr)pDraw)->devPrivates, OMAPDRI2WindowPrivateKey); } else { pPriv = dixLookupPrivate(&((PixmapPtr)pDraw)->devPrivates, OMAPDRI2PixmapPrivateKey); } if (!pPriv) { pPriv = calloc(1, sizeof(*pPriv)); pPriv->pDraw = pDraw; if (pDraw->type == DRAWABLE_WINDOW) { dixSetPrivate(&((WindowPtr)pDraw)->devPrivates, OMAPDRI2WindowPrivateKey, pPriv); } else { dixSetPrivate(&((PixmapPtr)pDraw)->devPrivates, OMAPDRI2PixmapPrivateKey, pPriv); } if (!AddResource(pDraw->id, OMAPDRI2DrawableRes, pPriv)) { OMAPDRI2DrawableGone(pPriv, pDraw->id); pPriv = NULL; } } return pPriv; } /* ************************************************************************* */ static inline DrawablePtr dri2draw(DrawablePtr pDraw, DRI2BufferPtr buf) { if (buf->attachment == DRI2BufferFrontLeft) { return pDraw; } else { return &(OMAPBUF(buf)->pPixmap->drawable); } } static inline Bool canexchange(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b) { DrawablePtr da = dri2draw(pDraw, a); DrawablePtr db = dri2draw(pDraw, b); return DRI2CanFlip(pDraw) && (da->width == db->width) && (da->height == db->height) && (da->depth == db->depth); } static Bool canflip(DrawablePtr pDraw) { return (pDraw->type == DRAWABLE_WINDOW) && DRI2CanFlip(pDraw); } static inline Bool exchangebufs(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b) { OMAPPixmapExchange(draw2pix(dri2draw(pDraw, a)), draw2pix(dri2draw(pDraw, b))); exchange(a->name, b->name); return TRUE; } static PixmapPtr createpix(DrawablePtr pDraw, Bool scanout) { ScreenPtr pScreen = pDraw->pScreen; int flags = scanout ? OMAP_CREATE_PIXMAP_SCANOUT : 0; if (scanout) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; Bool rotated = drmmode_is_rotated(pScrn); flags |= rotated ? OMAP_CREATE_PIXMAP_TILED : 0; } return pScreen->CreatePixmap(pScreen, pDraw->width, pDraw->height, pDraw->depth, flags); } /* ************************************************************************* */ /** * Create Buffer. * * Note that 'format' is used from the client side to specify the DRI buffer * format, which could differ from the drawable format. For example, the * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or * perhaps lower bit depth RGB (GL). The color conversion is handled when * blitting to front buffer, and page-flipping (overlay or flipchain) can * only be used if the display supports. */ static DRI2BufferPtr OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment, unsigned int format) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); OMAPDRI2BufferPtr buf = calloc(1, sizeof(*buf)); PixmapPtr pPixmap; struct omap_bo *bo; int ret; DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x", pDraw, attachment, format); if (!buf) { return NULL; } if (attachment == DRI2BufferFrontLeft) { pPixmap = draw2pix(pDraw); /* to do flipping, if we don't have DMM, then we need a scanout * capable (physically contiguous) buffer.. this bit of gymnastics * ensures that. * * TODO we may want to re-allocate and switch back to non-scanout * buffer when client disconnects from drawable.. */ if (canflip(pDraw) && !has_dmm(pOMAP) && (OMAPPixmapBo(pPixmap) != pOMAP->scanout)) { /* need to re-allocate pixmap to get a scanout capable buffer */ PixmapPtr pNewPix = createpix(pDraw, TRUE); // TODO copy contents.. OMAPPixmapExchange(pPixmap, pNewPix); pScreen->DestroyPixmap(pNewPix); } pPixmap->refcnt++; } else { pPixmap = createpix(pDraw, canflip(pDraw)); } bo = OMAPPixmapBo(pPixmap); DRIBUF(buf)->attachment = attachment; DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap); DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8; DRIBUF(buf)->format = format; buf->refcnt = 1; buf->pPixmap = pPixmap; ret = omap_bo_get_name(bo, &DRIBUF(buf)->name); if (ret) { ERROR_MSG("could not get buffer name: %d", ret); OMAPDRI2DestroyBuffer(pDraw, DRIBUF(buf)); return NULL; } if (attachment == DRI2BufferThirdLeft) { OMAPDRI2DrawablePtr pPriv = OMAPDRI2GetDrawable(pDraw); pPriv->pThirdBuffer = DRIBUF(buf); } return DRIBUF(buf); } /** * Destroy Buffer */ static void OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer) { OMAPDRI2BufferPtr buf = OMAPBUF(buffer); /* Note: pDraw may already be deleted, so use the pPixmap here * instead (since it is at least refcntd) */ ScreenPtr pScreen = buf->pPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; if (--buf->refcnt > 0) return; DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer); if (buffer->attachment == DRI2BufferThirdLeft) { OMAPDRI2DrawablePtr pPriv = OMAPDRI2GetDrawable(pDraw); pPriv->pThirdBuffer = NULL; } pScreen->DestroyPixmap(buf->pPixmap); free(buf); } static void OMAPDRI2ReferenceBuffer(DRI2BufferPtr buffer) { OMAPDRI2BufferPtr buf = OMAPBUF(buffer); buf->refcnt++; } /** * */ static void OMAPDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer); DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer); RegionPtr pCopyClip; GCPtr pGC; DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)", pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw); pGC = GetScratchGC(pDstDraw->depth, pScreen); if (!pGC) { return; } pCopyClip = REGION_CREATE(pScreen, NULL, 0); RegionCopy(pCopyClip, pRegion); (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0); ValidateGC(pDstDraw, pGC); /* If the dst is the framebuffer, and we had a way to * schedule a deferred blit synchronized w/ vsync, that * would be a nice thing to do utilize here to avoid * tearing.. when we have sync object support for GEM * buffers, I think we could do something more clever * here. */ pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC, 0, 0, pDraw->width, pDraw->height, 0, 0); FreeScratchGC(pGC); } /** * Get current frame count and frame count timestamp, based on drawable's * crtc. */ static int OMAPDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); drmVBlank vbl = { .request = { .type = DRM_VBLANK_RELATIVE, .sequence = 0, } }; int ret; ret = drmWaitVBlank(pOMAP->drmFD, &vbl); if (ret) { static int limit = 5; if (limit) { WARNING_MSG("get vblank counter failed: %s", strerror(errno)); limit--; } return FALSE; } if (ust) { *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; } if (msc) { *msc = vbl.reply.sequence; } return TRUE; } struct _OMAPDRISwapCmd { int type; ClientPtr client; ScreenPtr pScreen; /* Note: store drawable ID, rather than drawable. It's possible that * the drawable can be destroyed while we wait for page flip event: */ XID draw_id; DRI2BufferPtr pDstBuffer; DRI2BufferPtr pSrcBuffer; DRI2SwapEventPtr func; void *data; }; static const char *swap_names[] = { [DRI2_EXCHANGE_COMPLETE] = "exchange", [DRI2_BLIT_COMPLETE] = "blit", [DRI2_FLIP_COMPLETE] = "flip," }; static void OMAPDRI2SwapDispatch(DrawablePtr pDraw, OMAPDRISwapCmd *cmd) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPDRI2DrawablePtr pPriv = OMAPDRI2GetDrawable(pDraw); OMAPDRI2BufferPtr src = OMAPBUF(cmd->pSrcBuffer); Bool ok_to_flip = drmmode_is_rotated(pScrn) ? OMAPPixmapTiled(src->pPixmap) : TRUE; /* if we can flip, do so: */ if (ok_to_flip && canflip(pDraw) && drmmode_page_flip(pDraw, src->pPixmap, cmd)) { OMAPPTR(pScrn)->pending_page_flips++; cmd->type = DRI2_FLIP_COMPLETE; } else if (canexchange(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer)) { /* we can get away w/ pointer swap.. yah! */ cmd->type = DRI2_EXCHANGE_COMPLETE; } else { /* fallback to blit: */ BoxRec box = { .x1 = 0, .y1 = 0, .x2 = pDraw->width, .y2 = pDraw->height, }; RegionRec region; RegionInit(®ion, &box, 0); OMAPDRI2CopyRegion(pDraw, ®ion, cmd->pDstBuffer, cmd->pSrcBuffer); RegionUninit(®ion); cmd->type = DRI2_BLIT_COMPLETE; } DEBUG_MSG("%s dispatched: %d -> %d", swap_names[cmd->type], cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment); /* for flip/exchange, cycle buffers now, so no next DRI2GetBuffers * gets the new buffer names: */ if (cmd->type != DRI2_BLIT_COMPLETE) { exchangebufs(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer); if (pPriv->pThirdBuffer) { exchangebufs(pDraw, cmd->pSrcBuffer, pPriv->pThirdBuffer); } } /* if we are triple buffering, send event back to client * now, rather than waiting for vblank, so client can * immediately request the new back buffer: */ if (pPriv->pThirdBuffer) { DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type, cmd->func, cmd->data); } /* for exchange/blit, there is no page_flip event to wait for: */ if (cmd->type != DRI2_FLIP_COMPLETE) { OMAPDRI2SwapComplete(cmd); } } void OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd) { ScreenPtr pScreen = cmd->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; DrawablePtr pDraw = NULL; int status; DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type], cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment); if (cmd->type == DRI2_FLIP_COMPLETE) OMAPPTR(pScrn)->pending_page_flips--; status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient, M_ANY, DixWriteAccess); if (status == Success) { OMAPDRI2DrawablePtr pPriv = OMAPDRI2GetDrawable(pDraw); if (!pPriv->pThirdBuffer) { DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type, cmd->func, cmd->data); } if (pPriv->cmd) { /* dispatch queued flip: */ OMAPDRISwapCmd *cmd = pPriv->cmd; pPriv->cmd = NULL; OMAPDRI2SwapDispatch(pDraw, cmd); } pPriv->pending_swaps--; } /* drop extra refcnt we obtained prior to swap: */ OMAPDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer); OMAPDRI2DestroyBuffer(pDraw, cmd->pDstBuffer); free(cmd); } /** * ScheduleSwap is responsible for requesting a DRM vblank event for the * appropriate frame. * * In the case of a blit (e.g. for a windowed swap) or buffer exchange, * the vblank requested can simply be the last queued swap frame + the swap * interval for the drawable. * * In the case of a page flip, we request an event for the last queued swap * frame + swap interval - 1, since we'll need to queue the flip for the frame * immediately following the received event. */ static int OMAPDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw, DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer, CARD64 *target_msc, CARD64 divisor, CARD64 remainder, DRI2SwapEventPtr func, void *data) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPDRI2DrawablePtr pPriv = OMAPDRI2GetDrawable(pDraw); OMAPDRISwapCmd *cmd = calloc(1, sizeof(*cmd)); cmd->client = client; cmd->pScreen = pScreen; cmd->draw_id = pDraw->id; cmd->pSrcBuffer = pSrcBuffer; cmd->pDstBuffer = pDstBuffer; cmd->func = func; cmd->data = data; /* obtain extra ref on buffers to avoid them going away while we await * the page flip event: */ OMAPDRI2ReferenceBuffer(pSrcBuffer); OMAPDRI2ReferenceBuffer(pDstBuffer); pPriv->pending_swaps++; if (pPriv->pending_swaps > 1) { /* if we already have a pending swap, then just queue this * one up: */ if (pPriv->cmd) { ERROR_MSG("already pending a flip!"); pPriv->pending_swaps--; return FALSE; } pPriv->cmd = cmd; } else { OMAPDRI2SwapDispatch(pDraw, cmd); } return TRUE; } /** * Request a DRM event when the requested conditions will be satisfied. * * We need to handle the event and ask the server to wake up the client when * we receive it. */ static int OMAPDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, CARD64 divisor, CARD64 remainder) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; // OMAPPtr pOMAP = OMAPPTR(pScrn); #if 0 #endif ERROR_MSG("not implemented"); return FALSE; } /** * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core */ Bool OMAPDRI2ScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); DRI2InfoRec info = { .version = 6, .fd = pOMAP->drmFD, .driverName = "omap", .deviceName = pOMAP->deviceName, .CreateBuffer = OMAPDRI2CreateBuffer, .DestroyBuffer = OMAPDRI2DestroyBuffer, .CopyRegion = OMAPDRI2CopyRegion, .ScheduleSwap = OMAPDRI2ScheduleSwap, .ScheduleWaitMSC = OMAPDRI2ScheduleWaitMSC, .GetMSC = OMAPDRI2GetMSC, .AuthMagic = drmAuthMagic, }; int minor = 1, major = 0; if (xf86LoaderCheckSymbol("DRI2Version")) { DRI2Version(&major, &minor); } if (minor < 1) { WARNING_MSG("DRI2 requires DRI2 module version 1.1.0 or later"); return FALSE; } OMAPDRI2DrawableRes = CreateNewResourceType( OMAPDRI2DrawableGone, (char *)"OMAPDRI2Drawable"); if (!OMAPDRI2DrawableRes) return FALSE; if (!dixRegisterPrivateKey(&OMAPDRI2WindowPrivateKeyRec, PRIVATE_WINDOW, 0)) return FALSE; if (!dixRegisterPrivateKey(&OMAPDRI2PixmapPrivateKeyRec, PRIVATE_PIXMAP, 0)) return FALSE; return DRI2ScreenInit(pScreen, &info); } /** * The DRI2 CloseScreen() function.. unregister ourself w/ DRI2 core. */ void OMAPDRI2CloseScreen(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); while (pOMAP->pending_page_flips > 0) { DEBUG_MSG("waiting.."); drmmode_wait_for_event(pScrn); } DRI2CloseScreen(pScreen); } xf86-video-omap-0.4.3/src/omap_driver.c000066400000000000000000000667331207404333600176320ustar00rootroot00000000000000/* -*- 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 * Rob Clark */ #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(SCREEN_INIT_ARGS_DECL); static void OMAPLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual); static Bool OMAPCloseScreen(CLOSE_SCREEN_ARGS_DECL); static Bool OMAPCreateScreenResources(ScreenPtr pScreen); static void OMAPBlockHandler(BLOCKHANDLER_ARGS_DECL); static Bool OMAPSwitchMode(SWITCH_MODE_ARGS_DECL); static void OMAPAdjustFrame(ADJUST_FRAME_ARGS_DECL); static Bool OMAPEnterVT(VT_FUNC_ARGS_DECL); static void OMAPLeaveVT(VT_FUNC_ARGS_DECL); static void OMAPFreeScreen(FREE_SCREEN_ARGS_DECL); #ifdef XSERVER_PLATFORM_BUS static Bool OMAPPlatformProbe(DriverPtr drv, int entity_num, int flags, struct xf86_platform_device *dev, intptr_t match_data); #endif /** * 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 #ifdef XSERVER_PLATFORM_BUS OMAPPlatformProbe, #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 ;-)" }, */ { 0x5430, "OMAP5430 with PowerVR SGX544 MP" }, { 0x5432, "OMAP5432 with PowerVR SGX544 MP" }, {-1, NULL } }; /** Supported options, as enum values. */ typedef enum { OPTION_DEBUG, OPTION_DRI, OPTION_NO_ACCEL, OPTION_HW_CURSOR, /* 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_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NO_ACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_HW_CURSOR, "HWcursor", 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; } pOMAP->deviceName = drmGetDeviceNameFromFd(pOMAP->drmFD); 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)) { drmFree(pOMAP->deviceName); 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; } #define TILED_STRIDE_BOUNDARY 4096 unsigned int OMAPCalculateTiledStride(unsigned int width, unsigned int bitsPerPixel) { unsigned int stride = OMAPCalculateStride(width, bitsPerPixel); stride = (stride + (4096 - 1)) & ~(4096 - 1); return stride; } unsigned int OMAPTiledFlags(unsigned int bitsPerPixel) { switch(bitsPerPixel) { case 32: return OMAP_BO_TILED_32; case 16: return OMAP_BO_TILED_16; case 8: return OMAP_BO_TILED_8; default: return 0; } } static Bool OMAPMapMem(ScrnInfoPtr pScrn) { return drmmode_reallocate_scanout(pScrn, FALSE, NULL); } static Bool OMAPUnmapMem(ScrnInfoPtr pScrn) { OMAPPtr pOMAP = OMAPPTR(pScrn); drmmode_remove_fb(pScrn); omap_bo_del(pOMAP->scanout); pOMAP->scanout = NULL; pOMAP->scanout_w = pOMAP->scanout_h = 0; 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; #ifdef XSERVER_PLATFORM_BUS xf86AddDriver(&OMAP, module, HaveDriverFuncs); #else xf86AddDriver(&OMAP, module, 0); #endif /* 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; /* 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"); if (flags & PROBE_DETECT) { /* if we are probing, assume one and lets see if we can * open the device to confirm it is there: */ numDevSections = 1; } else { return FALSE; } } for (i = 0; i < numDevSections; i++) { int fd = OMAPOpenDRM(i); if (fd != -1) { if (flags & PROBE_DETECT) { /* just add the device.. we aren't a PCI device, so * call xf86AddBusDeviceToConfigure() directly */ xf86AddBusDeviceToConfigure(OMAP_DRIVER_NAME, BUS_NONE, NULL, i); foundScreen = TRUE; continue; } pScrn = xf86AllocateScreen(drv, 0); if (!pScrn) { EARLY_ERROR_MSG("Cannot allocate a ScrnInfoPtr"); return FALSE; } if (devSections) { int entity = xf86ClaimNoSlot(drv, 0, devSections[i], TRUE); 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 }; EntityInfoPtr pEnt; 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); pEnt = xf86GetEntityInfo(pScrn->entityList[0]); pOMAP->pEntityInfo = pEnt; 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; #ifdef XSERVER_PLATFORM_BUS if (pEnt->location.type == BUS_PLATFORM) { char *busid = xf86_get_platform_device_attrib(pEnt->location.id.plat, ODEV_ATTRIB_BUSID); pOMAP->drmFD = drmOpen(NULL, busid); if (pOMAP->drmFD < 0) goto fail; pOMAP->deviceName = drmGetDeviceNameFromFd(pOMAP->drmFD); } else #endif 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); pOMAP->dri = xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_DRI, TRUE); /* Determine if user wants to disable hw mouse cursor: */ pOMAP->HWCursor = xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_HW_CURSOR, TRUE); INFO_MSG("Using %s cursor", pOMAP->HWCursor ? "HW" : "SW"); /* 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: case 0x5430: case 0x5432: 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; } /** * Initialize EXA and DRI2 */ static void OMAPAccelInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); if (!pOMAP->NoAccel) { switch (pOMAP->chipset) { case 0x3430: case 0x3630: case 0x4430: case 0x4460: case 0x5430: case 0x5432: INFO_MSG("Initializing the \"%s\" sub-module ...", SUB_MODULE_PVR); pOMAP->pOMAPEXA = InitPowerVREXA(pScreen, pScrn, pOMAP->drmFD); 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; default: ERROR_MSG("Unsupported chipset: %d", pOMAP->chipset); pOMAP->NoAccel = TRUE; break; } } if (!pOMAP->pOMAPEXA) { pOMAP->pOMAPEXA = InitNullEXA(pScreen, pScrn, pOMAP->drmFD); } if (pOMAP->dri && pOMAP->pOMAPEXA) { pOMAP->dri = OMAPDRI2ScreenInit(pScreen); } else { pOMAP->dri = FALSE; } if (OMAPVideoScreenInit(pScreen)) { INFO_MSG("Initialized XV"); } else { ERROR_MSG("Could not initialize XV"); } } /** * The driver's ScreenInit() function. Fill in pScreen, map the frame buffer, * save state, initialize the mode, etc. */ static Bool OMAPScreenInit(SCREEN_INIT_ARGS_DECL) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); VisualPtr visual; xf86CrtcConfigPtr xf86_config; int i; TRACE_ENTER(); /* 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 external sub-modules for EXA now, this has to be before * miDCInitialize() otherwise stacking order for wrapped ScreenPtr fxns * ends up in the wrong order. */ OMAPAccelInit(pScreen); /* Initialize backing store: */ xf86SetBackingStore(pScreen); /* Cause the cursor position to be updated by the mouse signal handler: */ xf86SetSilkenMouse(pScreen); /* Initialize the cursor: */ miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); if (pOMAP->HWCursor) { if (!drmmode_cursor_init(pScreen)) { ERROR_MSG("Hardware cursor initialization failed"); pOMAP->HWCursor = FALSE; } } /* 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(VT_FUNC_ARGS(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 (has_rotation(pOMAP)) { xf86RandR12SetRotations(pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270 | RR_Reflect_X | RR_Reflect_Y); } else { #if XF86_CRTC_VERSION < 4 WARNING_MSG("rotation not supported by XF86_CRTC_VERSION version: %d", XF86_CRTC_VERSION); #endif } 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); drmmode_screen_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(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); OMAPPtr pOMAP = OMAPPTR(pScrn); TRACE_ENTER(); drmmode_screen_fini(pScrn); if (pScrn->vtSema == TRUE) { OMAPLeaveVT(VT_FUNC_ARGS(0)); } if (pOMAP->pOMAPEXA) { if (pOMAP->pOMAPEXA->CloseScreen) { pOMAP->pOMAPEXA->CloseScreen(CLOSE_SCREEN_ARGS); } } if (pOMAP->dri) { OMAPDRI2CloseScreen(pScreen); } OMAPVideoCloseScreen(pScreen); OMAPUnmapMem(pScrn); pScrn->vtSema = FALSE; unwrap(pOMAP, pScreen, CloseScreen); unwrap(pOMAP, pScreen, BlockHandler); unwrap(pOMAP, pScreen, CreateScreenResources); TRACE_EXIT(); return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); } /** * 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(BLOCKHANDLER_ARGS_DECL) { SCREEN_PTR(arg); ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); OMAPPtr pOMAP = OMAPPTR(pScrn); swap(pOMAP, pScreen, BlockHandler); (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); swap(pOMAP, pScreen, BlockHandler); /* TODO OMAPVideoBlockHandler(), etc.. */ } /** * The driver's SwitchMode() function. Initialize the new mode for the * Screen. */ static Bool OMAPSwitchMode(SWITCH_MODE_ARGS_DECL) { SCRN_INFO_PTR(arg); 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(ADJUST_FRAME_ARGS_DECL) { SCRN_INFO_PTR(arg); drmmode_adjust_frame(pScrn, x, y); } /** * 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(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); 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(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); 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(FREE_SCREEN_ARGS_DECL) { SCRN_INFO_PTR(arg); 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(FREE_SCREEN_ARGS(pScrn)); } free(pOMAP->pOMAPEXA); } omap_device_del(pOMAP->dev); OMAPCloseDRMMaster(pScrn); OMAPFreeRec(pScrn); TRACE_EXIT(); } #ifdef XSERVER_PLATFORM_BUS static Bool OMAPPlatformProbe(DriverPtr drv, int entity_num, int flags, struct xf86_platform_device *dev, intptr_t match_data) { ScrnInfoPtr pScrn = NULL; Bool foundScreen = FALSE; char *busid = xf86_get_platform_device_attrib(dev, ODEV_ATTRIB_BUSID); int fd; fd = drmOpen(NULL, busid); if (fd != -1) { pScrn = xf86AllocateScreen(drv, 0); if (!pScrn) { EARLY_ERROR_MSG("Cannot allocate a ScrnInfoPtr"); return FALSE; } xf86AddEntityToScreen(pScrn, entity_num); 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; drmClose(fd); } return foundScreen; } #endif xf86-video-omap-0.4.3/src/omap_driver.h000066400000000000000000000171721207404333600176300ustar00rootroot00000000000000/* -*- 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 * Rob Clark */ #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 "micmap.h" #include "xf86cmap.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" #include "drm_fourcc.h" #include "dri2.h" #ifdef XSERVER_PLATFORM_BUS #include "xf86platformBus.h" #endif #include #include #include #include "compat-api.h" #include "omap_exa.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); extern unsigned int OMAPCalculateTiledStride(unsigned int width, unsigned int bitsPerPixel); unsigned int OMAPTiledFlags(unsigned int bitsPerPixel); /** 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; /** various user-configurable options: */ Bool dri; Bool HWCursor; Bool NoAccel; /** File descriptor of the connection with the DRM. */ int drmFD; char *deviceName; /** DRM device instance */ struct omap_device *dev; /** Scan-out buffer. */ struct omap_bo *scanout; int scanout_w, scanout_h; Bool scanout_rotate; /** Does kernel support rotation? */ Bool rotation_supported; /** 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; XF86VideoAdaptorPtr textureAdaptor; /** Pending page flips we are waiting for: */ int pending_page_flips; } OMAPRec, *OMAPPtr; /* * Misc utility macros: */ /* do we support video? */ static inline Bool has_video(OMAPPtr pOMAP) { return pOMAP->pOMAPEXA && pOMAP->pOMAPEXA->GetFormats && pOMAP->pOMAPEXA->PutTextureImage; } static inline Bool has_dmm(OMAPPtr pOMAP) { return pOMAP->chipset >= 0x4430; } static inline Bool has_rotation(OMAPPtr pOMAP) { #if XF86_CRTC_VERSION >= 4 return has_dmm(pOMAP) && pOMAP->rotation_supported; #else return FALSE; #endif } /** 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; \ } #define exchange(a, b) {\ typeof(a) tmp = a; \ a = b; \ b = tmp; \ } #ifndef ARRAY_SIZE # define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #endif #define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1)) /** * drmmode functions.. */ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp); void drmmode_screen_init(ScrnInfoPtr pScrn); void drmmode_screen_fini(ScrnInfoPtr pScrn); void drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y); void drmmode_remove_fb(ScrnInfoPtr pScrn); Bool drmmode_page_flip(DrawablePtr pDraw, PixmapPtr back, void *priv); void drmmode_wait_for_event(ScrnInfoPtr pScrn); Bool drmmode_cursor_init(ScreenPtr pScreen); Bool drmmode_is_rotated(ScrnInfoPtr pScrn); Bool drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw, xf86CrtcPtr crtc); /** * DRI2 functions.. */ typedef struct _OMAPDRISwapCmd OMAPDRISwapCmd; Bool OMAPDRI2ScreenInit(ScreenPtr pScreen); void OMAPDRI2CloseScreen(ScreenPtr pScreen); void OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd); /** * XV functions.. */ Bool OMAPVideoScreenInit(ScreenPtr pScreen); void OMAPVideoCloseScreen(ScreenPtr pScreen); /** * EXA util functions.. move to EXA core? */ typedef int (*OMAPPutTextureImageProc)( PixmapPtr pSrcPix, BoxPtr pSrcBox, PixmapPtr pOsdPix, BoxPtr pOsdBox, PixmapPtr pDstPix, BoxPtr pDstBox, void *closure); Bool OMAPVidCopyArea(DrawablePtr pSrcDraw, BoxPtr pSrcBox, DrawablePtr pOsdDraw, BoxPtr pOsdBox, DrawablePtr pDstDraw, BoxPtr pDstBox, OMAPPutTextureImageProc PutTextureImage, void *closure, RegionPtr clipBoxes); #endif /* __OMAP_DRV_H__ */ xf86-video-omap-0.4.3/src/omap_exa.c000066400000000000000000000232401207404333600170760ustar00rootroot00000000000000/* -*- 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 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "omap_exa.h" #include "omap_driver.h" /* keep this here, instead of static-inline so submodule doesn't * need to know layout of OMAPPtr.. */ _X_EXPORT OMAPEXAPtr OMAPEXAPTR(ScrnInfoPtr pScrn) { OMAPPtr pOMAP = OMAPPTR(pScrn); return pOMAP->pOMAPEXA; } /* 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. */ /* used by DRI2 code to play buffer switcharoo */ void OMAPPixmapExchange(PixmapPtr a, PixmapPtr b) { OMAPPixmapPrivPtr apriv = exaGetPixmapDriverPrivate(a); OMAPPixmapPrivPtr bpriv = exaGetPixmapDriverPrivate(b); exchange(apriv->priv, bpriv->priv); exchange(apriv->bo, bpriv->bo); } _X_EXPORT 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; } _X_EXPORT void OMAPDestroyPixmap(ScreenPtr pScreen, void *driverPriv) { OMAPPixmapPrivPtr priv = driverPriv; OMAPPtr pOMAP = OMAPPTR_FROM_SCREEN(pScreen); /* scanout buffer is deleted elsewhere.. some refcnt'ing would * make this a bit cleaner.. */ if (priv->bo != pOMAP->scanout) omap_bo_del(priv->bo); free(priv); } _X_EXPORT 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, flags = OMAP_BO_WC; 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"); 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; if (pPixmap->usage_hint & OMAP_CREATE_PIXMAP_SCANOUT) { flags |= OMAP_BO_SCANOUT; } if (pPixmap->usage_hint & OMAP_CREATE_PIXMAP_TILED) { switch (bitsPerPixel) { case 8: flags |= OMAP_BO_TILED_8; break; case 16: flags |= OMAP_BO_TILED_16; break; case 32: flags |= OMAP_BO_TILED_32; break; default: break; } pPixmap->devKind = OMAPCalculateTiledStride(width, bitsPerPixel); } else { 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); if (flags & OMAP_BO_TILED) { priv->bo = omap_bo_new_tiled(pOMAP->dev, width, height, flags); priv->tiled = TRUE; } else { priv->bo = omap_bo_new(pOMAP->dev, size, flags); priv->tiled = FALSE; } } if (!priv->bo) { DEBUG_MSG("failed to allocate %dx%d bo, size=%d, flags=%08x", width, height, size, flags); } return priv->bo != NULL; } /** * WaitMarker is a required EXA callback but synchronization is * performed during OMAPPrepareAccess so this function does not * have anything to do at present */ _X_EXPORT void OMAPWaitMarker(ScreenPtr pScreen, int marker) { /* no-op */ } static inline enum omap_gem_op idx2op(int index) { switch (index) { case EXA_PREPARE_SRC: case EXA_PREPARE_MASK: case EXA_PREPARE_AUX_SRC: case EXA_PREPARE_AUX_MASK: return OMAP_GEM_READ; case EXA_PREPARE_AUX_DEST: case EXA_PREPARE_DEST: default: return OMAP_GEM_READ | OMAP_GEM_WRITE; } } /** * 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. */ _X_EXPORT Bool OMAPPrepareAccess(PixmapPtr pPixmap, int index) { OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap); pPixmap->devPrivate.ptr = omap_bo_map(priv->bo); if (!pPixmap->devPrivate.ptr) { return FALSE; } /* wait for blits complete.. note we could be a bit more clever here * for non-DRI2 buffers and use separate OMAP{Prepare,Finish}GPUAccess() * fxns wrapping accelerated GPU operations.. this way we don't have * to prep/fini around each CPU operation, but only when there is an * intervening GPU operation (or if we go to a stronger op mask, ie. * first CPU access is READ and second is WRITE). */ if (omap_bo_cpu_prep(priv->bo, idx2op(index))) { return FALSE; } 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. */ _X_EXPORT void OMAPFinishAccess(PixmapPtr pPixmap, int index) { OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap); pPixmap->devPrivate.ptr = NULL; /* NOTE: can we use EXA migration module to track which parts of the * buffer was accessed by sw, and pass that info down to kernel to * do a more precise cache flush.. */ omap_bo_cpu_fini(priv->bo, idx2op(index)); } /** * 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. */ _X_EXPORT 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; } xf86-video-omap-0.4.3/src/omap_exa.h000066400000000000000000000117351207404333600171110ustar00rootroot00000000000000/* -*- 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 */ #ifndef OMAP_EXA_COMMON_H_ #define OMAP_EXA_COMMON_H_ /* note: don't include "omap_driver.h" here.. we want to keep some * isolation between structs shared with submodules and stuff internal * to core driver.. */ #include #include "omap_util.h" #include "exa.h" #include "compat-api.h" /** * 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)(CLOSE_SCREEN_ARGS_DECL); /** * 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)(FREE_SCREEN_ARGS_DECL); /** get formats supported by PutTextureImage() (for dri2 video..) */ #define MAX_FORMATS 16 unsigned int (*GetFormats)(unsigned int *formats); Bool (*PutTextureImage)(PixmapPtr pSrcPix, BoxPtr pSrcBox, PixmapPtr pOsdPix, BoxPtr pOsdBox, PixmapPtr pDstPix, BoxPtr pDstBox, unsigned int extraCount, PixmapPtr *extraPix, unsigned int format); /* 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; /** * 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, int fd); /** * Fallback EXA implementation */ OMAPEXAPtr InitNullEXA(ScreenPtr pScreen, ScrnInfoPtr pScrn, int fd); OMAPEXAPtr OMAPEXAPTR(ScrnInfoPtr pScrn); static inline ScrnInfoPtr pix2scrn(PixmapPtr pPixmap) { return xf86Screens[(pPixmap)->drawable.pScreen->myNum]; } static inline PixmapPtr draw2pix(DrawablePtr pDraw) { if (!pDraw) { return NULL; } else if (pDraw->type == DRAWABLE_WINDOW) { return pDraw->pScreen->GetWindowPixmap((WindowPtr)pDraw); } else { return (PixmapPtr)pDraw; } } /* 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; Bool tiled; } OMAPPixmapPrivRec, *OMAPPixmapPrivPtr; #define OMAP_CREATE_PIXMAP_SCANOUT 0x80000000 #define OMAP_CREATE_PIXMAP_TILED 0x40000000 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 pPixmap, int index); void OMAPFinishAccess(PixmapPtr pPixmap, int index); Bool OMAPPixmapIsOffscreen(PixmapPtr pPixmap); static inline struct omap_bo * OMAPPixmapBo(PixmapPtr pPixmap) { OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap); return priv->bo; } static inline Bool OMAPPixmapTiled(PixmapPtr pPixmap) { OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap); return priv->tiled; } void OMAPPixmapExchange(PixmapPtr a, PixmapPtr b); #endif /* OMAP_EXA_COMMON_H_ */ xf86-video-omap-0.4.3/src/omap_exa_null.c000066400000000000000000000077121207404333600201360ustar00rootroot00000000000000/* -*- 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 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "omap_driver.h" #include "omap_exa.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(CLOSE_SCREEN_ARGS_DECL) { #if 0 // TODO need to change CloseScreen/FreeScreen .. exaDriverFini(pScreen); free(pNv->EXADriverPtr); #endif return TRUE; } static void FreeScreen(FREE_SCREEN_ARGS_DECL) { } OMAPEXAPtr InitNullEXA(ScreenPtr pScreen, ScrnInfoPtr pScrn, int fd) { 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; } xf86-video-omap-0.4.3/src/omap_exa_utils.c000066400000000000000000000103031207404333600203120ustar00rootroot00000000000000/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ /* * Copyright © 2012 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 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "omap_driver.h" #include "omap_exa.h" /***** move to common helper code?? in EXA or DRI2? *****/ /* if this is in DRI2, then the driver can't rely on pixmap migration, etc * before PutTextureImage cb is called.. I guess it should be in EXA.. */ #include /** * Helper function to implement video blit, handling clipping, damage, etc.. * * TODO: move to EXA? */ int OMAPVidCopyArea(DrawablePtr pSrcDraw, BoxPtr pSrcBox, DrawablePtr pOsdDraw, BoxPtr pOsdBox, DrawablePtr pDstDraw, BoxPtr pDstBox, OMAPPutTextureImageProc PutTextureImage, void *closure, RegionPtr clipBoxes) { ScreenPtr pScreen = pDstDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; PixmapPtr pSrcPix = draw2pix(pSrcDraw); PixmapPtr pOsdPix = draw2pix(pOsdDraw); PixmapPtr pDstPix = draw2pix(pDstDraw); pixman_fixed_t sx, sy, tx, ty; pixman_transform_t srcxfrm; BoxPtr pbox; int nbox, dx, dy, ret = Success; #ifdef COMPOSITE DEBUG_MSG("--> %dx%d, %dx%d", pDstPix->screen_x, pDstPix->screen_y, pDstDraw->x, pDstDraw->y); /* Convert screen coords to pixmap coords */ if (pDstPix->screen_x || pDstPix->screen_y) { RegionTranslate(clipBoxes, -pDstPix->screen_x, -pDstPix->screen_y); } dx = pDstPix->screen_x; dy = pDstPix->screen_y; #else dx = 0; dy = 0; #endif /* the clip-region gives coordinates in dst's coord space.. generate * a transform that can be used to work backwards from dst->src coord * space: */ sx = ((pixman_fixed_48_16_t) (pSrcBox->x2 - pSrcBox->x1) << 16) / (pDstBox->x2 - pDstBox->x1); sy = ((pixman_fixed_48_16_t) (pSrcBox->y2 - pSrcBox->y1) << 16) / (pDstBox->y2 - pDstBox->y1); tx = ((pixman_fixed_48_16_t)(pDstBox->x1 - dx) << 16); ty = ((pixman_fixed_48_16_t)(pDstBox->y1 - dy) << 16); pixman_transform_init_scale(&srcxfrm, sx, sy); pixman_transform_translate(NULL, &srcxfrm, tx, ty); // TODO generate transform for osd as well pbox = RegionRects(clipBoxes); nbox = RegionNumRects(clipBoxes); while (nbox--) { RegionRec damage; BoxRec dstb = *pbox; BoxRec srcb = *pbox; BoxRec osdb = *pbox; pixman_transform_bounds(&srcxfrm, &srcb); //pixman_transform_bounds(&osdxfrm, &osdb); /* cropping is done in src coord space, post transform: */ srcb.x1 += pSrcBox->x1; srcb.y1 += pSrcBox->y1; srcb.x2 += pSrcBox->x1; srcb.y2 += pSrcBox->y1; DEBUG_MSG("%d,%d %d,%d -> %d,%d %d,%d", srcb.x1, srcb.y1, srcb.x2, srcb.y2, dstb.x1, dstb.y1, dstb.x2, dstb.y2); ret = PutTextureImage(pSrcPix, &srcb, pOsdPix, &osdb, pDstPix, &dstb, closure); if (ret != Success) { break; } RegionInit(&damage, &dstb, 1); #ifdef COMPOSITE /* Convert screen coords to pixmap coords */ if (pDstPix->screen_x || pDstPix->screen_y) { RegionTranslate(&damage, pDstPix->screen_x, pDstPix->screen_y); } #endif DamageRegionAppend(pDstDraw, &damage); RegionUninit(&damage); pbox++; } DamageRegionProcessPending(pDstDraw); return ret; } xf86-video-omap-0.4.3/src/omap_util.h000066400000000000000000000057241207404333600173120ustar00rootroot00000000000000/* -*- 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 * Rob Clark */ #ifndef __OMAP_UTIL_H__ #define __OMAP_UTIL_H__ /* All drivers need the following headers: */ #include "xf86.h" #include "xf86_OSproc.h" /** * 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) extern unsigned int OMAPCalculateStride(unsigned int fbWidth, unsigned int bitsPerPixel); extern unsigned int OMAPCalculateTiledStride(unsigned int width, unsigned int bitsPerPixel); #endif /* __OMAP_UTIL_H__ */ xf86-video-omap-0.4.3/src/omap_xv.c000066400000000000000000000317061207404333600167640ustar00rootroot00000000000000/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ /* * Copyright © 2012 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 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "xf86xv.h" #include #include "fourcc.h" #include "omap_driver.h" #include "omap_exa.h" #define NUM_TEXTURE_PORTS 32 /* this is basically arbitrary */ #define IMAGE_MAX_W 2048 #define IMAGE_MAX_H 2048 typedef struct { unsigned int format; int nplanes; PixmapPtr pSrcPix[3]; } OMAPPortPrivRec, *OMAPPortPrivPtr; static XF86VideoEncodingRec OMAPVideoEncoding[] = { { 0, (char *)"XV_IMAGE", IMAGE_MAX_W, IMAGE_MAX_H, {1, 1} }, }; static XF86VideoFormatRec OMAPVideoFormats[] = { {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, {15, DirectColor}, {16, DirectColor}, {24, DirectColor} }; static XF86AttributeRec OMAPVideoTexturedAttributes[] = { }; static XF86ImageRec OMAPVideoTexturedImages[MAX_FORMATS]; static PixmapPtr setupplane(ScreenPtr pScreen, PixmapPtr pSrcPix, int width, int height, int depth, int srcpitch, int bufpitch, unsigned char **bufp) { struct omap_bo *bo; unsigned char *src, *buf = *bufp; int i; if (pSrcPix && ((pSrcPix->drawable.height != height) || (pSrcPix->drawable.width != width))) { pScreen->DestroyPixmap(pSrcPix); pSrcPix = NULL; } if (!pSrcPix) { pSrcPix = pScreen->CreatePixmap(pScreen, width, height, depth, 0); } bo = OMAPPixmapBo(pSrcPix); omap_bo_cpu_prep(bo, OMAP_GEM_WRITE); src = omap_bo_map(bo); /* copy from buf to src pixmap: */ for (i = 0; i < height; i++) { memcpy(src, buf, srcpitch); src += srcpitch; buf += bufpitch; } omap_bo_cpu_fini(bo, OMAP_GEM_WRITE); *bufp = buf; return pSrcPix; } static void freebufs(ScreenPtr pScreen, OMAPPortPrivPtr pPriv) { int i; for (i = 0; i < ARRAY_SIZE(pPriv->pSrcPix); i++) { if (pPriv->pSrcPix[i]) pScreen->DestroyPixmap(pPriv->pSrcPix[i]); pPriv->pSrcPix[i] = NULL; } } static void OMAPVideoStopVideo(ScrnInfoPtr pScrn, pointer data, Bool exit) { /* maybe we can deallocate pSrcPix here?? */ } static int OMAPVideoSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { return BadMatch; } static int OMAPVideoGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 *value, pointer data) { return BadMatch; } static void OMAPVideoQueryBestSize(ScrnInfoPtr pScrn, Bool motion, short vid_w, short vid_h, short drw_w, short drw_h, unsigned int *p_w, unsigned int *p_h, pointer data) { /* currently no constraints.. */ *p_w = drw_w; *p_h = drw_h; } static int OMAPVideoPutTextureImage( PixmapPtr pSrcPix, BoxPtr pSrcBox, PixmapPtr pOsdPix, BoxPtr pOsdBox, PixmapPtr pDstPix, BoxPtr pDstBox, void *closure) { ScreenPtr pScreen = pDstPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); OMAPPortPrivPtr pPriv = closure; Bool ret; DEBUG_MSG("src: %dx%d; %d,%d %d,%d", pSrcPix->drawable.width, pSrcPix->drawable.height, pSrcBox->x1, pSrcBox->y1, pSrcBox->x2, pSrcBox->y2); DEBUG_MSG("dst: %dx%d; %d,%d %d,%d", pDstPix->drawable.width, pDstPix->drawable.height, pDstBox->x1, pDstBox->y1, pDstBox->x2, pDstBox->y2); ret = pOMAP->pOMAPEXA->PutTextureImage(pSrcPix, pSrcBox, pOsdPix, pOsdBox, pDstPix, pDstBox, pPriv->nplanes - 1, &pPriv->pSrcPix[1], pPriv->format); if (ret) { return Success; } DEBUG_MSG("PutTextureImage failed"); return BadImplementation; } /** * The main function for XV, called to blit/scale/colorcvt an image * to it's destination drawable * * The source rectangle of the video is defined by (src_x, src_y, src_w, src_h). * The dest rectangle of the video is defined by (drw_x, drw_y, drw_w, drw_h). * id is a fourcc code for the format of the video. * buf is the pointer to the source data in system memory. * width and height are the w/h of the source data. * If "sync" is TRUE, then we must be finished with *buf at the point of return * (which we always are). * clipBoxes is the clipping region in screen space. * data is a pointer to our port private. * drawable is some Drawable, which might not be the screen in the case of * compositing. It's a new argument to the function in the 1.1 server. */ static int OMAPVideoPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, short drw_y, short src_w, short src_h, short drw_w, short drw_h, int id, unsigned char *buf, short width, short height, Bool Sync, RegionPtr clipBoxes, pointer data, DrawablePtr pDstDraw) { ScreenPtr pScreen = pDstDraw->pScreen; OMAPPortPrivPtr pPriv = (OMAPPortPrivPtr)data; BoxRec srcb = { .x1 = src_x, .y1 = src_y, .x2 = src_x + src_w, .y2 = src_y + src_h, }; BoxRec dstb = { .x1 = drw_x, .y1 = drw_y, .x2 = drw_x + drw_w, .y2 = drw_y + drw_h, }; int i, depth, nplanes; int srcpitch1, srcpitch2, bufpitch1, bufpitch2, src_h2, src_w2; switch (id) { // case fourcc_code('N','V','1','2'): // break; case fourcc_code('Y','V','1','2'): case fourcc_code('I','4','2','0'): nplanes = 3; srcpitch1 = ALIGN(src_w, 4); srcpitch2 = ALIGN(src_w / 2, 4); bufpitch1 = ALIGN(width, 4); bufpitch2 = ALIGN(width / 2, 4); depth = 8; src_h2 = src_h / 2; src_w2 = src_w / 2; break; case fourcc_code('U','Y','V','Y'): case fourcc_code('Y','U','Y','V'): case fourcc_code('Y','U','Y','2'): nplanes = 1; srcpitch1 = src_w * 2; bufpitch1 = width * 2; depth = 16; srcpitch2 = bufpitch2 = src_h2 = src_w2 = 0; break; default: ERROR_MSG("unexpected format: %08x (%4.4s)", id, (char *)&id); return BadMatch; } if (pPriv->format != id) { freebufs(pScreen, pPriv); } pPriv->format = id; pPriv->nplanes = nplanes; pPriv->pSrcPix[0] = setupplane(pScreen, pPriv->pSrcPix[0], src_w, src_h, depth, srcpitch1, bufpitch1, &buf); for (i = 1; i < pPriv->nplanes; i++) { pPriv->pSrcPix[i] = setupplane(pScreen, pPriv->pSrcPix[i], src_w2, src_h2, depth, srcpitch2, bufpitch2, &buf); } /* note: OMAPVidCopyArea() handles the composite-clip, so we can * ignore clipBoxes */ return OMAPVidCopyArea(&pPriv->pSrcPix[0]->drawable, &srcb, NULL, NULL, pDstDraw, &dstb, OMAPVideoPutTextureImage, pPriv, clipBoxes); } /** * QueryImageAttributes * * calculates * - size (memory required to store image), * - pitches, * - offsets * of image * depending on colorspace (id) and dimensions (w,h) of image * values of * - w, * - h * may be adjusted as needed * * @param pScrn unused * @param id colorspace of image * @param w pointer to width of image * @param h pointer to height of image * @param pitches pitches[i] = length of a scanline in plane[i] * @param offsets offsets[i] = offset of plane i from the beginning of the image * @return size of the memory required for the XvImage queried */ static int OMAPVideoQueryImageAttributes(ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets) { int size, tmp; if (*w > IMAGE_MAX_W) *w = IMAGE_MAX_W; if (*h > IMAGE_MAX_H) *h = IMAGE_MAX_H; *w = (*w + 1) & ~1; // width rounded up to an even number if (offsets) offsets[0] = 0; switch (id) { case fourcc_code('Y','V','1','2'): case fourcc_code('I','4','2','0'): *h = (*h + 1) & ~1; // height rounded up to an even number size = (*w + 3) & ~3; // width rounded up to a multiple of 4 if (pitches) pitches[0] = size; // width rounded up to a multiple of 4 size *= *h; if (offsets) offsets[1] = size; // number of pixels in "rounded up" image tmp = ((*w >> 1) + 3) & ~3; // width/2 rounded up to a multiple of 4 if (pitches) pitches[1] = pitches[2] = tmp; // width/2 rounded up to a multiple of 4 tmp *= (*h >> 1); // 1/4*number of pixels in "rounded up" image size += tmp; // 5/4*number of pixels in "rounded up" image if (offsets) offsets[2] = size; // 5/4*number of pixels in "rounded up" image size += tmp; // = 3/2*number of pixels in "rounded up" image break; case fourcc_code('U','Y','V','Y'): case fourcc_code('Y','U','Y','2'): size = *w << 1; // 2*width if (pitches) pitches[0] = size; // 2*width size *= *h; // 2*width*height break; default: xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown colorspace: %x\n", id); *w = *h = size = 0; break; } return size; } static XF86VideoAdaptorPtr OMAPVideoSetupTexturedVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); XF86VideoAdaptorPtr adapt; OMAPPortPrivPtr pPriv; int i, nformats, nsupported; static unsigned int formats[MAX_FORMATS]; if (!has_video(pOMAP)) { return NULL; } if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + sizeof(OMAPPortPrivRec) + (sizeof(DevUnion) * NUM_TEXTURE_PORTS)))) { return NULL; } adapt->type = XvWindowMask | XvInputMask | XvImageMask; adapt->flags = 0; adapt->name = (char *)"OMAP Textured Video"; adapt->nEncodings = ARRAY_SIZE(OMAPVideoEncoding); adapt->pEncodings = OMAPVideoEncoding; adapt->nFormats = ARRAY_SIZE(OMAPVideoFormats); adapt->pFormats = OMAPVideoFormats; adapt->nPorts = NUM_TEXTURE_PORTS; adapt->pPortPrivates = (DevUnion*)(&adapt[1]); pPriv = (OMAPPortPrivPtr)(&adapt->pPortPrivates[NUM_TEXTURE_PORTS]); for(i = 0; i < NUM_TEXTURE_PORTS; i++) adapt->pPortPrivates[i].ptr = (pointer)(pPriv); adapt->nAttributes = ARRAY_SIZE(OMAPVideoTexturedAttributes); adapt->pAttributes = OMAPVideoTexturedAttributes; nformats = pOMAP->pOMAPEXA->GetFormats(formats); nsupported = 0; for (i = 0; i < nformats; i++) { switch (formats[i]) { // case fourcc_code('N','V','1','2'): // break; case fourcc_code('Y','V','1','2'): OMAPVideoTexturedImages[nsupported++] = (XF86ImageRec)XVIMAGE_YV12; break; case fourcc_code('I','4','2','0'): OMAPVideoTexturedImages[nsupported++] = (XF86ImageRec)XVIMAGE_I420; break; case fourcc_code('U','Y','V','Y'): OMAPVideoTexturedImages[nsupported++] = (XF86ImageRec)XVIMAGE_UYVY; break; case fourcc_code('Y','U','Y','V'): case fourcc_code('Y','U','Y','2'): OMAPVideoTexturedImages[nsupported++] = (XF86ImageRec)XVIMAGE_YUY2; break; default: /* ignore unsupported formats */ break; } } adapt->nImages = nsupported; adapt->pImages = OMAPVideoTexturedImages; adapt->PutVideo = NULL; adapt->PutStill = NULL; adapt->GetVideo = NULL; adapt->GetStill = NULL; adapt->StopVideo = OMAPVideoStopVideo; adapt->SetPortAttribute = OMAPVideoSetPortAttribute; adapt->GetPortAttribute = OMAPVideoGetPortAttribute; adapt->QueryBestSize = OMAPVideoQueryBestSize; adapt->PutImage = OMAPVideoPutImage; adapt->QueryImageAttributes = OMAPVideoQueryImageAttributes; return adapt; } /** * If EXA implementation supports GetFormats() and PutTextureImage() we can * use that to implement XV. There is a copy involve because we need to * copy the buffer to a texture (TODO possibly we can support wrapping * external buffers, but current EXA submodule API doesn't give us a way to * do that). So for optimal path from hw decoders to display, dri2video * should be used. But this at least helps out legacy apps. */ Bool OMAPVideoScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); XF86VideoAdaptorPtr textureAdaptor = OMAPVideoSetupTexturedVideo(pScreen); if (textureAdaptor) { XF86VideoAdaptorPtr *adaptors, *newAdaptors; int n = xf86XVListGenericAdaptors(pScrn, &adaptors); newAdaptors = calloc(n + 1, sizeof(XF86VideoAdaptorPtr *)); memcpy(newAdaptors, adaptors, n * sizeof(XF86VideoAdaptorPtr *)); pOMAP->textureAdaptor = textureAdaptor; newAdaptors[n] = textureAdaptor; xf86XVScreenInit(pScreen, newAdaptors, n + 1); free(newAdaptors); return TRUE; } return FALSE; } void OMAPVideoCloseScreen(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; OMAPPtr pOMAP = OMAPPTR(pScrn); if (pOMAP->textureAdaptor) { OMAPPortPrivPtr pPriv = (OMAPPortPrivPtr) pOMAP->textureAdaptor->pPortPrivates[0].ptr; freebufs(pScreen, pPriv); } }